Staging: add rt2870 wireless driver
authorGreg Kroah-Hartman <gregkh@suse.de>
Thu, 18 Dec 2008 01:04:23 +0000 (17:04 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 6 Jan 2009 21:52:35 +0000 (13:52 -0800)
This is the Ralink RT2870 driver from the company that does horrible
things like reading a config file from /etc.  However, the driver that
is currently under development from the wireless development community
is not working at all yet, so distros and users are using this version
instead (quite common hardware on a lot of netbook machines).

So here is this driver, for now, until the wireless developers get a
"clean" version into the main tree, or until this version is cleaned up
sufficiently to move out of the staging tree.

Ported to the Linux build system and cleaned up a bit already by me.

Cc: Linux wireless <linux-wireless@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
70 files changed:
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/rt2870/2870_main_dev.c [new file with mode: 0644]
drivers/staging/rt2870/Kconfig [new file with mode: 0644]
drivers/staging/rt2870/Makefile [new file with mode: 0644]
drivers/staging/rt2870/TODO [new file with mode: 0644]
drivers/staging/rt2870/aironet.h [new file with mode: 0644]
drivers/staging/rt2870/ap.h [new file with mode: 0644]
drivers/staging/rt2870/chlist.h [new file with mode: 0644]
drivers/staging/rt2870/common/2870_rtmp_init.c [new file with mode: 0644]
drivers/staging/rt2870/common/action.c [new file with mode: 0644]
drivers/staging/rt2870/common/action.h [new file with mode: 0644]
drivers/staging/rt2870/common/ba_action.c [new file with mode: 0644]
drivers/staging/rt2870/common/cmm_data.c [new file with mode: 0644]
drivers/staging/rt2870/common/cmm_data_2870.c [new file with mode: 0644]
drivers/staging/rt2870/common/cmm_info.c [new file with mode: 0644]
drivers/staging/rt2870/common/cmm_sanity.c [new file with mode: 0644]
drivers/staging/rt2870/common/cmm_sync.c [new file with mode: 0644]
drivers/staging/rt2870/common/cmm_wpa.c [new file with mode: 0644]
drivers/staging/rt2870/common/dfs.c [new file with mode: 0644]
drivers/staging/rt2870/common/eeprom.c [new file with mode: 0644]
drivers/staging/rt2870/common/firmware.h [new file with mode: 0644]
drivers/staging/rt2870/common/md5.c [new file with mode: 0644]
drivers/staging/rt2870/common/mlme.c [new file with mode: 0644]
drivers/staging/rt2870/common/netif_block.c [new file with mode: 0644]
drivers/staging/rt2870/common/rtmp_init.c [new file with mode: 0644]
drivers/staging/rt2870/common/rtmp_tkip.c [new file with mode: 0644]
drivers/staging/rt2870/common/rtmp_wep.c [new file with mode: 0644]
drivers/staging/rt2870/common/rtusb_bulk.c [new file with mode: 0644]
drivers/staging/rt2870/common/rtusb_data.c [new file with mode: 0644]
drivers/staging/rt2870/common/rtusb_io.c [new file with mode: 0644]
drivers/staging/rt2870/common/spectrum.c [new file with mode: 0644]
drivers/staging/rt2870/dfs.h [new file with mode: 0644]
drivers/staging/rt2870/leap.h [new file with mode: 0644]
drivers/staging/rt2870/link_list.h [new file with mode: 0644]
drivers/staging/rt2870/md4.h [new file with mode: 0644]
drivers/staging/rt2870/md5.h [new file with mode: 0644]
drivers/staging/rt2870/mlme.h [new file with mode: 0644]
drivers/staging/rt2870/netif_block.h [new file with mode: 0644]
drivers/staging/rt2870/oid.h [new file with mode: 0644]
drivers/staging/rt2870/rt2870.h [new file with mode: 0644]
drivers/staging/rt2870/rt28xx.h [new file with mode: 0644]
drivers/staging/rt2870/rt_ate.c [new file with mode: 0644]
drivers/staging/rt2870/rt_ate.h [new file with mode: 0644]
drivers/staging/rt2870/rt_config.h [new file with mode: 0644]
drivers/staging/rt2870/rt_linux.c [new file with mode: 0644]
drivers/staging/rt2870/rt_linux.h [new file with mode: 0644]
drivers/staging/rt2870/rt_main_dev.c [new file with mode: 0644]
drivers/staging/rt2870/rt_profile.c [new file with mode: 0644]
drivers/staging/rt2870/rtmp.h [new file with mode: 0644]
drivers/staging/rt2870/rtmp_ckipmic.h [new file with mode: 0644]
drivers/staging/rt2870/rtmp_def.h [new file with mode: 0644]
drivers/staging/rt2870/rtmp_type.h [new file with mode: 0644]
drivers/staging/rt2870/spectrum.h [new file with mode: 0644]
drivers/staging/rt2870/spectrum_def.h [new file with mode: 0644]
drivers/staging/rt2870/sta/aironet.c [new file with mode: 0644]
drivers/staging/rt2870/sta/assoc.c [new file with mode: 0644]
drivers/staging/rt2870/sta/auth.c [new file with mode: 0644]
drivers/staging/rt2870/sta/auth_rsp.c [new file with mode: 0644]
drivers/staging/rt2870/sta/connect.c [new file with mode: 0644]
drivers/staging/rt2870/sta/dls.c [new file with mode: 0644]
drivers/staging/rt2870/sta/rtmp_data.c [new file with mode: 0644]
drivers/staging/rt2870/sta/sanity.c [new file with mode: 0644]
drivers/staging/rt2870/sta/sync.c [new file with mode: 0644]
drivers/staging/rt2870/sta/wpa.c [new file with mode: 0644]
drivers/staging/rt2870/sta_ioctl.c [new file with mode: 0644]
drivers/staging/rt2870/sta_ioctl.c.patch [new file with mode: 0644]
drivers/staging/rt2870/tmp60 [new file with mode: 0644]
drivers/staging/rt2870/tmp61 [new file with mode: 0644]
drivers/staging/rt2870/wpa.h [new file with mode: 0644]

index 9845eab9ebfe051776c29733af6d23e0e752484c..e2f57e9b694c77836966fa9c31d022cd8144406f 100644 (file)
@@ -71,6 +71,8 @@ source "drivers/staging/otus/Kconfig"
 
 source "drivers/staging/rt2860/Kconfig"
 
+source "drivers/staging/rt2870/Kconfig"
+
 source "drivers/staging/benet/Kconfig"
 
 source "drivers/staging/comedi/Kconfig"
index 968f333a659bb0916e5a9c343d01fa54c974acaf..94efc9df5a85f071415564917cf1d309574b0b47 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_POCH)            += poch/
 obj-$(CONFIG_AGNX)             += agnx/
 obj-$(CONFIG_OTUS)             += otus/
 obj-$(CONFIG_RT2860)           += rt2860/
+obj-$(CONFIG_RT2870)           += rt2870/
 obj-$(CONFIG_BENET)            += benet/
 obj-$(CONFIG_COMEDI)           += comedi/
 obj-$(CONFIG_ASUS_OLED)                += asus_oled/
diff --git a/drivers/staging/rt2870/2870_main_dev.c b/drivers/staging/rt2870/2870_main_dev.c
new file mode 100644 (file)
index 0000000..91da4e2
--- /dev/null
@@ -0,0 +1,1612 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    rtmp_main.c
+
+    Abstract:
+    main initialization routines
+
+    Revision History:
+    Who         When            What
+    --------    ----------      ----------------------------------------------
+    Name        Date            Modification logs
+    Jan Lee            01-10-2005          modified
+       Sample          Jun/01/07               Merge RT2870 and RT2860 drivers.
+*/
+
+#include "rt_config.h"
+
+
+// Following information will be show when you run 'modinfo'
+// *** If you have a solution for the bug in current version of driver, please mail to me.
+// Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. ***
+MODULE_AUTHOR("Paul Lin <paul_lin@ralinktech.com>");
+MODULE_DESCRIPTION("RT2870 Wireless Lan Linux Driver");
+#ifdef CONFIG_STA_SUPPORT
+MODULE_LICENSE("GPL");
+#ifdef MODULE_VERSION
+MODULE_VERSION(STA_DRIVER_VERSION);
+#endif
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef MULTIPLE_CARD_SUPPORT
+// record whether the card in the card list is used in the card file
+extern UINT8  MC_CardUsed[];
+#endif // MULTIPLE_CARD_SUPPORT //
+
+/* Kernel thread and vars, which handles packets that are completed. Only
+ * packets that have a "complete" function are sent here. This way, the
+ * completion is run out of kernel context, and doesn't block the rest of
+ * the stack. */
+
+extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
+                                                                       IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
+
+
+/* module table */
+struct usb_device_id    rtusb_usb_id[] = RT2870_USB_DEVICES;
+INT const               rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id);
+MODULE_DEVICE_TABLE(usb, rtusb_usb_id);
+
+#ifndef PF_NOFREEZE
+#define PF_NOFREEZE  0
+#endif
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+
+/**************************************************************************/
+/**************************************************************************/
+//tested for kernel 2.4 series
+/**************************************************************************/
+/**************************************************************************/
+static void *rtusb_probe(struct usb_device *dev, UINT interface,
+                                               const struct usb_device_id *id_table);
+static void rtusb_disconnect(struct usb_device *dev, void *ptr);
+
+struct usb_driver rtusb_driver = {
+               name:"rt2870",
+               probe:rtusb_probe,
+               disconnect:rtusb_disconnect,
+               id_table:rtusb_usb_id,
+       };
+
+#else
+
+#ifdef CONFIG_PM
+static int rt2870_suspend(struct usb_interface *intf, pm_message_t state);
+static int rt2870_resume(struct usb_interface *intf);
+#endif // CONFIG_PM //
+
+/**************************************************************************/
+/**************************************************************************/
+//tested for kernel 2.6series
+/**************************************************************************/
+/**************************************************************************/
+static int rtusb_probe (struct usb_interface *intf,
+                                               const struct usb_device_id *id);
+static void rtusb_disconnect(struct usb_interface *intf);
+
+struct usb_driver rtusb_driver = {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+       .owner = THIS_MODULE,
+#endif
+       .name="rt2870",
+       .probe=rtusb_probe,
+       .disconnect=rtusb_disconnect,
+       .id_table=rtusb_usb_id,
+
+#ifdef CONFIG_PM
+       suspend:        rt2870_suspend,
+       resume:         rt2870_resume,
+#endif
+       };
+
+#ifdef CONFIG_PM
+
+VOID RT2860RejectPendingPackets(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       // clear PS packets
+       // clear TxSw packets
+}
+
+static int rt2870_suspend(
+       struct usb_interface *intf,
+       pm_message_t state)
+{
+       struct net_device *net_dev;
+       PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n"));
+       net_dev = pAd->net_dev;
+       netif_device_detach (net_dev);
+
+       pAd->PM_FlgSuspend = 1;
+       if (netif_running(net_dev)) {
+               RTUSBCancelPendingBulkInIRP(pAd);
+               RTUSBCancelPendingBulkOutIRP(pAd);
+       }
+       DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n"));
+       return 0;
+}
+
+static int rt2870_resume(
+       struct usb_interface *intf)
+{
+       struct net_device *net_dev;
+       PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n"));
+
+       pAd->PM_FlgSuspend = 0;
+       net_dev = pAd->net_dev;
+       netif_device_attach (net_dev);
+       netif_start_queue(net_dev);
+       netif_carrier_on(net_dev);
+       netif_wake_queue(net_dev);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n"));
+       return 0;
+}
+#endif // CONFIG_PM //
+#endif // LINUX_VERSION_CODE //
+
+
+// Init driver module
+INT __init rtusb_init(void)
+{
+       printk("rtusb init --->\n");
+       return usb_register(&rtusb_driver);
+}
+
+// Deinit driver module
+VOID __exit rtusb_exit(void)
+{
+       usb_deregister(&rtusb_driver);
+       printk("<--- rtusb exit\n");
+}
+
+module_init(rtusb_init);
+module_exit(rtusb_exit);
+
+
+
+
+/*---------------------------------------------------------------------        */
+/* function declarations                                                                                               */
+/*---------------------------------------------------------------------        */
+
+/*
+========================================================================
+Routine Description:
+    MLME kernel thread.
+
+Arguments:
+       *Context                        the pAd, driver control block pointer
+
+Return Value:
+    0                                  close the thread
+
+Note:
+========================================================================
+*/
+INT MlmeThread(
+       IN void *Context)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER)Context;
+       POS_COOKIE      pObj;
+       int status;
+
+       pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+       rtmp_os_thread_init("rt2870MlmeThread", (PVOID)&(pAd->mlmeComplete));
+
+       while (pAd->mlme_kill == 0)
+       {
+               /* lock the device pointers */
+               //down(&(pAd->mlme_semaphore));
+               status = down_interruptible(&(pAd->mlme_semaphore));
+
+               /* lock the device pointers , need to check if required*/
+               //down(&(pAd->usbdev_semaphore));
+
+               if (!pAd->PM_FlgSuspend)
+               MlmeHandler(pAd);
+
+               /* unlock the device pointers */
+               //up(&(pAd->usbdev_semaphore));
+               if (status != 0)
+               {
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+                       break;
+               }
+       }
+
+       /* notify the exit routine that we're actually exiting now
+        *
+        * complete()/wait_for_completion() is similar to up()/down(),
+        * except that complete() is safe in the case where the structure
+        * is getting deleted in a parallel mode of execution (i.e. just
+        * after the down() -- that's necessary for the thread-shutdown
+        * case.
+        *
+        * complete_and_exit() goes even further than this -- it is safe in
+        * the case that the thread of the caller is going away (not just
+        * the structure) -- this is necessary for the module-remove case.
+        * This is important in preemption kernels, which transfer the flow
+        * of execution immediately upon a complete().
+        */
+       DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__));
+
+       pObj->MLMEThr_pid = THREAD_PID_INIT_VALUE;
+
+       complete_and_exit (&pAd->mlmeComplete, 0);
+       return 0;
+
+}
+
+
+/*
+========================================================================
+Routine Description:
+    USB command kernel thread.
+
+Arguments:
+       *Context                        the pAd, driver control block pointer
+
+Return Value:
+    0                                  close the thread
+
+Note:
+========================================================================
+*/
+INT RTUSBCmdThread(
+       IN void * Context)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER)Context;
+       POS_COOKIE              pObj;
+       int status;
+
+       pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+       rtmp_os_thread_init("rt2870CmdThread", (PVOID)&(pAd->CmdQComplete));
+
+       NdisAcquireSpinLock(&pAd->CmdQLock);
+       pAd->CmdQ.CmdQState = RT2870_THREAD_RUNNING;
+       NdisReleaseSpinLock(&pAd->CmdQLock);
+
+       while (pAd->CmdQ.CmdQState == RT2870_THREAD_RUNNING)
+       {
+               /* lock the device pointers */
+               //down(&(pAd->RTUSBCmd_semaphore));
+               status = down_interruptible(&(pAd->RTUSBCmd_semaphore));
+
+               if (pAd->CmdQ.CmdQState == RT2870_THREAD_STOPED)
+                       break;
+
+               if (status != 0)
+               {
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+                       break;
+               }
+               /* lock the device pointers , need to check if required*/
+               //down(&(pAd->usbdev_semaphore));
+
+               if (!pAd->PM_FlgSuspend)
+               CMDHandler(pAd);
+
+               /* unlock the device pointers */
+               //up(&(pAd->usbdev_semaphore));
+       }
+
+       if (!pAd->PM_FlgSuspend)
+       {       // Clear the CmdQElements.
+               CmdQElmt        *pCmdQElmt = NULL;
+
+               NdisAcquireSpinLock(&pAd->CmdQLock);
+               pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
+               while(pAd->CmdQ.size)
+               {
+                       RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt);
+                       if (pCmdQElmt)
+                       {
+                               if (pCmdQElmt->CmdFromNdis == TRUE)
+                               {
+                                       if (pCmdQElmt->buffer != NULL)
+                                               NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
+
+                                       NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
+                               }
+                               else
+                               {
+                                       if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0))
+                                               NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
+                           {
+                                               NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
+                                       }
+                               }
+                       }
+               }
+
+               NdisReleaseSpinLock(&pAd->CmdQLock);
+       }
+       /* notify the exit routine that we're actually exiting now
+        *
+        * complete()/wait_for_completion() is similar to up()/down(),
+        * except that complete() is safe in the case where the structure
+        * is getting deleted in a parallel mode of execution (i.e. just
+        * after the down() -- that's necessary for the thread-shutdown
+        * case.
+        *
+        * complete_and_exit() goes even further than this -- it is safe in
+        * the case that the thread of the caller is going away (not just
+        * the structure) -- this is necessary for the module-remove case.
+        * This is important in preemption kernels, which transfer the flow
+        * of execution immediately upon a complete().
+        */
+       DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n"));
+
+       pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE;
+
+       complete_and_exit (&pAd->CmdQComplete, 0);
+       return 0;
+
+}
+
+
+static void RT2870_TimerQ_Handle(RTMP_ADAPTER *pAd)
+{
+       int status;
+       RALINK_TIMER_STRUCT     *pTimer;
+       RT2870_TIMER_ENTRY      *pEntry;
+       unsigned long   irqFlag;
+
+       while(!pAd->TimerFunc_kill)
+       {
+//             printk("waiting for event!\n");
+               pTimer = NULL;
+
+               status = down_interruptible(&(pAd->RTUSBTimer_semaphore));
+
+               if (pAd->TimerQ.status == RT2870_THREAD_STOPED)
+                       break;
+
+               // event happened.
+               while(pAd->TimerQ.pQHead)
+               {
+                       RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlag);
+                       pEntry = pAd->TimerQ.pQHead;
+                       if (pEntry)
+                       {
+                               pTimer = pEntry->pRaTimer;
+
+                               // update pQHead
+                               pAd->TimerQ.pQHead = pEntry->pNext;
+                               if (pEntry == pAd->TimerQ.pQTail)
+                                       pAd->TimerQ.pQTail = NULL;
+
+                               // return this queue entry to timerQFreeList.
+                               pEntry->pNext = pAd->TimerQ.pQPollFreeList;
+                               pAd->TimerQ.pQPollFreeList = pEntry;
+                       }
+                       RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlag);
+
+                       if (pTimer)
+                       {
+                               if (pTimer->handle != NULL)
+                               if (!pAd->PM_FlgSuspend)
+                                       pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer);
+                               if ((pTimer->Repeat) && (pTimer->State == FALSE))
+                                       RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue);
+                       }
+               }
+
+               if (status != 0)
+               {
+                       pAd->TimerQ.status = RT2870_THREAD_STOPED;
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+                       break;
+               }
+       }
+}
+
+
+INT TimerQThread(
+       IN OUT PVOID Context)
+{
+       PRTMP_ADAPTER   pAd;
+       POS_COOKIE      pObj;
+
+       pAd = (PRTMP_ADAPTER)Context;
+       pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+       rtmp_os_thread_init("rt2870TimerQHandle", (PVOID)&(pAd->TimerQComplete));
+
+       RT2870_TimerQ_Handle(pAd);
+
+       /* notify the exit routine that we're actually exiting now
+        *
+        * complete()/wait_for_completion() is similar to up()/down(),
+        * except that complete() is safe in the case where the structure
+        * is getting deleted in a parallel mode of execution (i.e. just
+        * after the down() -- that's necessary for the thread-shutdown
+        * case.
+        *
+        * complete_and_exit() goes even further than this -- it is safe in
+        * the case that the thread of the caller is going away (not just
+        * the structure) -- this is necessary for the module-remove case.
+        * This is important in preemption kernels, which transfer the flow
+        * of execution immediately upon a complete().
+        */
+       DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__));
+
+       pObj->TimerQThr_pid = THREAD_PID_INIT_VALUE;
+
+       complete_and_exit(&pAd->TimerQComplete, 0);
+       return 0;
+
+}
+
+
+RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert(
+       IN RTMP_ADAPTER *pAd,
+       IN RALINK_TIMER_STRUCT *pTimer)
+{
+       RT2870_TIMER_ENTRY *pQNode = NULL, *pQTail;
+       unsigned long irqFlags;
+
+
+       RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
+       if (pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT)
+       {
+               if(pAd->TimerQ.pQPollFreeList)
+               {
+                       pQNode = pAd->TimerQ.pQPollFreeList;
+                       pAd->TimerQ.pQPollFreeList = pQNode->pNext;
+
+                       pQNode->pRaTimer = pTimer;
+                       pQNode->pNext = NULL;
+
+                       pQTail = pAd->TimerQ.pQTail;
+                       if (pAd->TimerQ.pQTail != NULL)
+                               pQTail->pNext = pQNode;
+                       pAd->TimerQ.pQTail = pQNode;
+                       if (pAd->TimerQ.pQHead == NULL)
+                               pAd->TimerQ.pQHead = pQNode;
+               }
+               RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
+
+               if (pQNode)
+                       up(&pAd->RTUSBTimer_semaphore);
+                       //wake_up(&timerWaitQ);
+       }
+       else
+       {
+               RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
+       }
+       return pQNode;
+}
+
+
+BOOLEAN RT2870_TimerQ_Remove(
+       IN RTMP_ADAPTER *pAd,
+       IN RALINK_TIMER_STRUCT *pTimer)
+{
+       RT2870_TIMER_ENTRY *pNode, *pPrev = NULL;
+       unsigned long irqFlags;
+
+       RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
+       if (pAd->TimerQ.status >= RT2870_THREAD_INITED)
+       {
+               pNode = pAd->TimerQ.pQHead;
+               while (pNode)
+               {
+                       if (pNode->pRaTimer == pTimer)
+                               break;
+                       pPrev = pNode;
+                       pNode = pNode->pNext;
+               }
+
+               // Now move it to freeList queue.
+               if (pNode)
+               {
+                       if (pNode == pAd->TimerQ.pQHead)
+                               pAd->TimerQ.pQHead = pNode->pNext;
+                       if (pNode == pAd->TimerQ.pQTail)
+                               pAd->TimerQ.pQTail = pPrev;
+                       if (pPrev != NULL)
+                               pPrev->pNext = pNode->pNext;
+
+                       // return this queue entry to timerQFreeList.
+                       pNode->pNext = pAd->TimerQ.pQPollFreeList;
+                       pAd->TimerQ.pQPollFreeList = pNode;
+               }
+       }
+       RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
+
+       return TRUE;
+}
+
+
+void RT2870_TimerQ_Exit(RTMP_ADAPTER *pAd)
+{
+       RT2870_TIMER_ENTRY *pTimerQ;
+       unsigned long irqFlags;
+
+       RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
+       while (pAd->TimerQ.pQHead)
+       {
+               pTimerQ = pAd->TimerQ.pQHead;
+               pAd->TimerQ.pQHead = pTimerQ->pNext;
+               // remove the timeQ
+       }
+       pAd->TimerQ.pQPollFreeList = NULL;
+       os_free_mem(pAd, pAd->TimerQ.pTimerQPoll);
+       pAd->TimerQ.pQTail = NULL;
+       pAd->TimerQ.pQHead = NULL;
+       pAd->TimerQ.status = RT2870_THREAD_STOPED;
+       RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
+
+}
+
+
+void RT2870_TimerQ_Init(RTMP_ADAPTER *pAd)
+{
+       int     i;
+       RT2870_TIMER_ENTRY *pQNode, *pEntry;
+       unsigned long irqFlags;
+
+       NdisAllocateSpinLock(&pAd->TimerQLock);
+
+       RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
+       NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));
+       //InterlockedExchange(&pAd->TimerQ.count, 0);
+
+       /* Initialise the wait q head */
+       //init_waitqueue_head(&timerWaitQ);
+
+       os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RT2870_TIMER_ENTRY) * TIMER_QUEUE_SIZE_MAX);
+       if (pAd->TimerQ.pTimerQPoll)
+       {
+               pEntry = NULL;
+               pQNode = (RT2870_TIMER_ENTRY *)pAd->TimerQ.pTimerQPoll;
+               for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)
+               {
+                       pQNode->pNext = pEntry;
+                       pEntry = pQNode;
+                       pQNode++;
+               }
+               pAd->TimerQ.pQPollFreeList = pEntry;
+               pAd->TimerQ.pQHead = NULL;
+               pAd->TimerQ.pQTail = NULL;
+               pAd->TimerQ.status = RT2870_THREAD_INITED;
+       }
+       RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
+}
+
+
+VOID RT2870_WatchDog(IN RTMP_ADAPTER *pAd)
+{
+       PHT_TX_CONTEXT          pHTTXContext;
+       int                                     idx;
+       ULONG                           irqFlags;
+       PURB                            pUrb;
+       BOOLEAN                         needDumpSeq = FALSE;
+       UINT32                  MACValue;
+
+
+       idx = 0;
+       RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
+       if ((MACValue & 0xff) !=0 )
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
+               RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012);
+               while((MACValue &0xff) != 0 && (idx++ < 10))
+               {
+                       RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
+                       NdisMSleep(1);
+               }
+               RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
+       }
+
+       idx = 0;
+       if ((MACValue & 0xff00) !=0 )
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
+               RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf4000a);
+               while((MACValue &0xff00) != 0 && (idx++ < 10))
+               {
+                       RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
+                       NdisMSleep(1);
+               }
+               RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
+       }
+
+
+       if (pAd->watchDogRxOverFlowCnt >= 2)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
+               if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                                       fRTMP_ADAPTER_BULKIN_RESET |
+                                                                       fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                                       fRTMP_ADAPTER_NIC_NOT_EXIST))))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0);
+                       needDumpSeq = TRUE;
+               }
+               pAd->watchDogRxOverFlowCnt = 0;
+       }
+
+
+       for (idx = 0; idx < NUM_OF_TX_RING; idx++)
+       {
+               pUrb = NULL;
+
+               RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags);
+               if ((pAd->BulkOutPending[idx] == TRUE) && pAd->watchDogTxPendingCnt)
+               {
+                       pAd->watchDogTxPendingCnt[idx]++;
+
+                       if ((pAd->watchDogTxPendingCnt[idx] > 2) &&
+                                (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET)))
+                               )
+                       {
+                               // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!
+                               pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[idx]);
+                               if (pHTTXContext->IRPPending)
+                               {       // Check TxContext.
+                                       pUrb = pHTTXContext->pUrb;
+                               }
+                               else if (idx == MGMTPIPEIDX)
+                               {
+                                       PTX_CONTEXT pMLMEContext, pNULLContext, pPsPollContext;
+
+                                       //Check MgmtContext.
+                                       pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa);
+                                       pPsPollContext = (PTX_CONTEXT)(&pAd->PsPollContext);
+                                       pNULLContext = (PTX_CONTEXT)(&pAd->NullContext);
+
+                                       if (pMLMEContext->IRPPending)
+                                       {
+                                               ASSERT(pMLMEContext->IRPPending);
+                                               pUrb = pMLMEContext->pUrb;
+                                       }
+                                       else if (pNULLContext->IRPPending)
+                                       {
+                                               ASSERT(pNULLContext->IRPPending);
+                                               pUrb = pNULLContext->pUrb;
+                                       }
+                                       else if (pPsPollContext->IRPPending)
+                                       {
+                                               ASSERT(pPsPollContext->IRPPending);
+                                               pUrb = pPsPollContext->pUrb;
+                                       }
+                               }
+
+                               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx));
+                               if (pUrb)
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n"));
+                                       // unlink it now
+                                       RTUSB_UNLINK_URB(pUrb);
+                                       // Sleep 200 microseconds to give cancellation time to work
+                                       RTMPusecDelay(200);
+                                       needDumpSeq = TRUE;
+                               }
+                               else
+                               {
+                                       DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
+                               }
+                       }
+                       else
+                       {
+                               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
+                       }
+               }
+               else
+               {
+                       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
+               }
+       }
+
+#ifdef DOT11_N_SUPPORT
+       // For Sigma debug, dump the ba_reordering sequence.
+       if((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0))
+       {
+               USHORT                          Idx;
+               PBA_REC_ENTRY           pBAEntry = NULL;
+               UCHAR                           count = 0;
+               struct reordering_mpdu *mpdu_blk;
+
+               Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0];
+
+               pBAEntry = &pAd->BATable.BARecEntry[Idx];
+               if((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
+                       NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+                       mpdu_blk = pBAEntry->list.next;
+                       while (mpdu_blk)
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("\t%d:Seq-%d, bAMSDU-%d!\n", count, mpdu_blk->Sequence, mpdu_blk->bAMSDU));
+                               mpdu_blk = mpdu_blk->next;
+                               count++;
+                       }
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq));
+                       NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+               }
+       }
+#endif // DOT11_N_SUPPORT //
+}
+
+/*
+========================================================================
+Routine Description:
+    Release allocated resources.
+
+Arguments:
+    *dev                               Point to the PCI or USB device
+       pAd                                     driver control block pointer
+
+Return Value:
+    None
+
+Note:
+========================================================================
+*/
+static void _rtusb_disconnect(struct usb_device *dev, PRTMP_ADAPTER pAd)
+{
+       struct net_device       *net_dev = NULL;
+
+
+       DBGPRINT(RT_DEBUG_ERROR, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",
+                               dev->bus->bus_name, dev->devpath));
+       if (!pAd)
+       {
+#ifdef MULTIPLE_CARD_SUPPORT
+               if ((pAd->MC_RowID >= 0) && (pAd->MC_RowID <= MAX_NUM_OF_MULTIPLE_CARD))
+                       MC_CardUsed[pAd->MC_RowID] = 0; // not clear MAC address
+#endif // MULTIPLE_CARD_SUPPORT //
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
+               while(MOD_IN_USE > 0)
+               {
+                       MOD_DEC_USE_COUNT;
+               }
+#else
+               usb_put_dev(dev);
+#endif // LINUX_VERSION_CODE //
+
+               printk("rtusb_disconnect: pAd == NULL!\n");
+               return;
+       }
+       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
+
+
+
+       // for debug, wait to show some messages to /proc system
+       udelay(1);
+
+
+
+
+       net_dev = pAd->net_dev;
+       if (pAd->net_dev != NULL)
+       {
+               printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev->name);
+               unregister_netdev (pAd->net_dev);
+       }
+       udelay(1);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
+#else
+       flush_scheduled_work();
+#endif // LINUX_VERSION_CODE //
+       udelay(1);
+
+       // free net_device memory
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
+       kfree(net_dev);
+#else
+       free_netdev(net_dev);
+#endif // LINUX_VERSION_CODE //
+
+       // free adapter memory
+       RTMPFreeAdapter(pAd);
+
+       // release a use of the usb device structure
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
+       while(MOD_IN_USE > 0)
+       {
+               MOD_DEC_USE_COUNT;
+       }
+#else
+       usb_put_dev(dev);
+#endif // LINUX_VERSION_CODE //
+       udelay(1);
+
+       DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n"));
+}
+
+
+/*
+========================================================================
+Routine Description:
+    Probe RT28XX chipset.
+
+Arguments:
+    *dev                               Point to the PCI or USB device
+       interface
+       *id_table                       Point to the PCI or USB device ID
+
+Return Value:
+    None
+
+Note:
+========================================================================
+*/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
+static void *rtusb_probe(struct usb_device *dev, UINT interface,
+                                               const struct usb_device_id *id)
+{
+       PRTMP_ADAPTER pAd;
+       rt28xx_probe((void *)dev, (void *)id, interface, &pAd);
+       return (void *)pAd;
+}
+
+//Disconnect function is called within exit routine
+static void rtusb_disconnect(struct usb_device *dev, void *ptr)
+{
+       _rtusb_disconnect(dev, ((PRTMP_ADAPTER)ptr));
+}
+
+#else  /* kernel 2.6 series */
+static int rtusb_probe (struct usb_interface *intf,
+                                               const struct usb_device_id *id)
+{
+       PRTMP_ADAPTER pAd;
+       return (int)rt28xx_probe((void *)intf, (void *)id, 0, &pAd);
+}
+
+
+static void rtusb_disconnect(struct usb_interface *intf)
+{
+       struct usb_device   *dev = interface_to_usbdev(intf);
+       PRTMP_ADAPTER       pAd;
+
+
+       pAd = usb_get_intfdata(intf);
+       usb_set_intfdata(intf, NULL);
+
+       _rtusb_disconnect(dev, pAd);
+}
+#endif // LINUX_VERSION_CODE //
+
+
+/*
+========================================================================
+Routine Description:
+    Close kernel threads.
+
+Arguments:
+       *pAd                            the raxx interface data pointer
+
+Return Value:
+    NONE
+
+Note:
+========================================================================
+*/
+VOID RT28xxThreadTerminate(
+       IN RTMP_ADAPTER *pAd)
+{
+       POS_COOKIE      pObj = (POS_COOKIE) pAd->OS_Cookie;
+       INT                     ret;
+
+
+       // Sleep 50 milliseconds so pending io might finish normally
+       RTMPusecDelay(50000);
+
+       // We want to wait until all pending receives and sends to the
+       // device object. We cancel any
+       // irps. Wait until sends and receives have stopped.
+       RTUSBCancelPendingIRPs(pAd);
+
+       // Terminate Threads
+       CHECK_PID_LEGALITY(pObj->TimerQThr_pid)
+       {
+               POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+               printk("Terminate the TimerQThr_pid=%d!\n", GET_PID_NUMBER(pObj->TimerQThr_pid));
+               mb();
+               pAd->TimerFunc_kill = 1;
+               mb();
+               ret = KILL_THREAD_PID(pObj->TimerQThr_pid, SIGTERM, 1);
+               if (ret)
+               {
+                       printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
+                                       pAd->net_dev->name, GET_PID_NUMBER(pObj->TimerQThr_pid), ret);
+               }
+               else
+               {
+                       wait_for_completion(&pAd->TimerQComplete);
+                       pObj->TimerQThr_pid = THREAD_PID_INIT_VALUE;
+               }
+       }
+
+       CHECK_PID_LEGALITY(pObj->MLMEThr_pid)
+       {
+               printk("Terminate the MLMEThr_pid=%d!\n", GET_PID_NUMBER(pObj->MLMEThr_pid));
+               mb();
+               pAd->mlme_kill = 1;
+               //RT28XX_MLME_HANDLER(pAd);
+               mb();
+               ret = KILL_THREAD_PID(pObj->MLMEThr_pid, SIGTERM, 1);
+               if (ret)
+               {
+                       printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n",
+                                       pAd->net_dev->name, GET_PID_NUMBER(pObj->MLMEThr_pid), ret);
+               }
+               else
+               {
+                       //wait_for_completion (&pAd->notify);
+                       wait_for_completion (&pAd->mlmeComplete);
+                       pObj->MLMEThr_pid = THREAD_PID_INIT_VALUE;
+               }
+       }
+
+       CHECK_PID_LEGALITY(pObj->RTUSBCmdThr_pid)
+       {
+               printk("Terminate the RTUSBCmdThr_pid=%d!\n", GET_PID_NUMBER(pObj->RTUSBCmdThr_pid));
+               mb();
+               NdisAcquireSpinLock(&pAd->CmdQLock);
+               pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
+               NdisReleaseSpinLock(&pAd->CmdQLock);
+               mb();
+               //RTUSBCMDUp(pAd);
+               ret = KILL_THREAD_PID(pObj->RTUSBCmdThr_pid, SIGTERM, 1);
+               if (ret)
+               {
+                       printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
+                                       pAd->net_dev->name, GET_PID_NUMBER(pObj->RTUSBCmdThr_pid), ret);
+               }
+               else
+               {
+                       //wait_for_completion (&pAd->notify);
+                       wait_for_completion (&pAd->CmdQComplete);
+                       pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE;
+       }
+       }
+
+
+       // Kill tasklets
+       pAd->mlme_kill = 0;
+       pAd->CmdQ.CmdQState = RT2870_THREAD_UNKNOWN;
+       pAd->TimerFunc_kill = 0;
+}
+
+
+void kill_thread_task(IN PRTMP_ADAPTER pAd)
+{
+       POS_COOKIE pObj;
+
+       pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+       tasklet_kill(&pObj->rx_done_task);
+       tasklet_kill(&pObj->mgmt_dma_done_task);
+       tasklet_kill(&pObj->ac0_dma_done_task);
+       tasklet_kill(&pObj->ac1_dma_done_task);
+       tasklet_kill(&pObj->ac2_dma_done_task);
+       tasklet_kill(&pObj->ac3_dma_done_task);
+       tasklet_kill(&pObj->hcca_dma_done_task);
+       tasklet_kill(&pObj->tbtt_task);
+
+}
+
+
+/*
+========================================================================
+Routine Description:
+    Check the chipset vendor/product ID.
+
+Arguments:
+    _dev_p                             Point to the PCI or USB device
+
+Return Value:
+    TRUE                               Check ok
+       FALSE                           Check fail
+
+Note:
+========================================================================
+*/
+BOOLEAN RT28XXChipsetCheck(
+       IN void *_dev_p)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
+       struct usb_device *dev_p = (struct usb_device *)_dev_p;
+#else
+       struct usb_interface *intf = (struct usb_interface *)_dev_p;
+       struct usb_device *dev_p = interface_to_usbdev(intf);
+#endif // LINUX_VERSION_CODE //
+       UINT32 i;
+
+
+       for(i=0; i<rtusb_usb_id_len; i++)
+       {
+               if (dev_p->descriptor.idVendor == rtusb_usb_id[i].idVendor &&
+                       dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct)
+               {
+                       printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
+                                       dev_p->descriptor.idVendor, dev_p->descriptor.idProduct);
+                       break;
+               }
+       }
+
+       if (i == rtusb_usb_id_len)
+       {
+               printk("rt2870: Error! Device Descriptor not matching!\n");
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+    Init net device structure.
+
+Arguments:
+    _dev_p                             Point to the PCI or USB device
+    *net_dev                   Point to the net device
+       *pAd                            the raxx interface data pointer
+
+Return Value:
+    TRUE                               Init ok
+       FALSE                           Init fail
+
+Note:
+========================================================================
+*/
+BOOLEAN RT28XXNetDevInit(
+       IN void                                 *_dev_p,
+       IN struct  net_device   *net_dev,
+       IN RTMP_ADAPTER                 *pAd)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
+       struct usb_device *dev_p = (struct usb_device *)_dev_p;
+#else
+       struct usb_interface *intf = (struct usb_interface *)_dev_p;
+       struct usb_device *dev_p = interface_to_usbdev(intf);
+#endif // LINUX_VERSION_CODE //
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
+       pAd->config = dev_p->config;
+#else
+       pAd->config = &dev_p->config->desc;
+#endif // LINUX_VERSION_CODE //
+       return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+    Init net device structure.
+
+Arguments:
+    _dev_p                             Point to the PCI or USB device
+       *pAd                            the raxx interface data pointer
+
+Return Value:
+    TRUE                               Config ok
+       FALSE                           Config fail
+
+Note:
+========================================================================
+*/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+BOOLEAN RT28XXProbePostConfig(
+       IN void                                 *_dev_p,
+       IN RTMP_ADAPTER                 *pAd,
+       IN INT32                                interface)
+{
+       struct usb_device *dev_p = (struct usb_device *)_dev_p;
+       struct usb_interface *intf;
+       struct usb_interface_descriptor *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       ULONG BulkOutIdx;
+       UINT32 i;
+
+
+       /* get the active interface descriptor */
+       intf = &dev_p->actconfig->interface[interface];
+       iface_desc = &intf->altsetting[0];
+
+       /* get # of enpoints */
+       pAd->NumberOfPipes = iface_desc->bNumEndpoints;
+       DBGPRINT(RT_DEBUG_TRACE, ("NumEndpoints=%d\n", iface_desc->bNumEndpoints));
+
+       /* Configure Pipes */
+       endpoint = &iface_desc->endpoint[0];
+       BulkOutIdx = 0;
+
+       for(i=0; i<pAd->NumberOfPipes; i++)
+       {
+               if ((endpoint[i].bmAttributes == USB_ENDPOINT_XFER_BULK) &&
+                       ((endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN))
+               {
+                       pAd->BulkInEpAddr = endpoint[i].bEndpointAddress;
+                       pAd->BulkInMaxPacketSize = endpoint[i].wMaxPacketSize;
+
+                       DBGPRINT_RAW(RT_DEBUG_TRACE,
+                               ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize));
+                       DBGPRINT_RAW(RT_DEBUG_TRACE,
+                               ("EP address = 0x%2x  \n", endpoint[i].bEndpointAddress));
+               }
+               else if ((endpoint[i].bmAttributes == USB_ENDPOINT_XFER_BULK) &&
+                               ((endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT))
+               {
+                       // There are 6 bulk out EP. EP6 highest priority.
+                       // EP1-4 is EDCA.  EP5 is HCCA.
+                       pAd->BulkOutEpAddr[BulkOutIdx++] = endpoint[i].bEndpointAddress;
+                       pAd->BulkOutMaxPacketSize = endpoint[i].wMaxPacketSize;
+
+                       DBGPRINT_RAW(RT_DEBUG_TRACE,
+                               ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize));
+                       DBGPRINT_RAW(RT_DEBUG_TRACE,
+                               ("EP address = 0x%2x  \n", endpoint[i].bEndpointAddress));
+               }
+       }
+
+       if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0]))
+       {
+               printk("Could not find both bulk-in and bulk-out endpoints\n");
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+#else
+BOOLEAN RT28XXProbePostConfig(
+       IN void                                 *_dev_p,
+       IN RTMP_ADAPTER                 *pAd,
+       IN INT32                                interface)
+{
+       struct usb_interface *intf = (struct usb_interface *)_dev_p;
+       struct usb_host_interface *iface_desc;
+       ULONG BulkOutIdx;
+       UINT32 i;
+
+
+       /* get the active interface descriptor */
+       iface_desc = intf->cur_altsetting;
+
+       /* get # of enpoints  */
+       pAd->NumberOfPipes = iface_desc->desc.bNumEndpoints;
+       DBGPRINT(RT_DEBUG_TRACE,
+                       ("NumEndpoints=%d\n", iface_desc->desc.bNumEndpoints));
+
+       /* Configure Pipes */
+       BulkOutIdx = 0;
+
+       for(i=0; i<pAd->NumberOfPipes; i++)
+       {
+               if ((iface_desc->endpoint[i].desc.bmAttributes ==
+                               USB_ENDPOINT_XFER_BULK) &&
+                       ((iface_desc->endpoint[i].desc.bEndpointAddress &
+                               USB_ENDPOINT_DIR_MASK) == USB_DIR_IN))
+               {
+                       pAd->BulkInEpAddr = iface_desc->endpoint[i].desc.bEndpointAddress;
+                       pAd->BulkInMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
+
+                       DBGPRINT_RAW(RT_DEBUG_TRACE,
+                               ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize));
+                       DBGPRINT_RAW(RT_DEBUG_TRACE,
+                               ("EP address = 0x%2x\n", iface_desc->endpoint[i].desc.bEndpointAddress));
+               }
+               else if ((iface_desc->endpoint[i].desc.bmAttributes ==
+                                       USB_ENDPOINT_XFER_BULK) &&
+                               ((iface_desc->endpoint[i].desc.bEndpointAddress &
+                                       USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT))
+               {
+                       // there are 6 bulk out EP. EP6 highest priority.
+                       // EP1-4 is EDCA.  EP5 is HCCA.
+                       pAd->BulkOutEpAddr[BulkOutIdx++] = iface_desc->endpoint[i].desc.bEndpointAddress;
+                       pAd->BulkOutMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
+
+                       DBGPRINT_RAW(RT_DEBUG_TRACE,
+                               ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize));
+                       DBGPRINT_RAW(RT_DEBUG_TRACE,
+                               ("EP address = 0x%2x  \n", iface_desc->endpoint[i].desc.bEndpointAddress));
+               }
+       }
+
+       if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0]))
+       {
+               printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __FUNCTION__);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+#endif // LINUX_VERSION_CODE //
+
+
+/*
+========================================================================
+Routine Description:
+    Disable DMA.
+
+Arguments:
+       *pAd                            the raxx interface data pointer
+
+Return Value:
+       None
+
+Note:
+========================================================================
+*/
+VOID RT28XXDMADisable(
+       IN RTMP_ADAPTER                 *pAd)
+{
+       // no use
+}
+
+
+
+/*
+========================================================================
+Routine Description:
+    Enable DMA.
+
+Arguments:
+       *pAd                            the raxx interface data pointer
+
+Return Value:
+       None
+
+Note:
+========================================================================
+*/
+VOID RT28XXDMAEnable(
+       IN RTMP_ADAPTER                 *pAd)
+{
+       WPDMA_GLO_CFG_STRUC     GloCfg;
+       USB_DMA_CFG_STRUC       UsbCfg;
+       int                                     i = 0;
+
+
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
+       do
+       {
+               RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
+               if ((GloCfg.field.TxDMABusy == 0)  && (GloCfg.field.RxDMABusy == 0))
+                       break;
+
+               DBGPRINT(RT_DEBUG_TRACE, ("==>  DMABusy\n"));
+               RTMPusecDelay(1000);
+               i++;
+       }while ( i <200);
+
+
+       RTMPusecDelay(50);
+       GloCfg.field.EnTXWriteBackDDONE = 1;
+       GloCfg.field.EnableRxDMA = 1;
+       GloCfg.field.EnableTxDMA = 1;
+       DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
+       RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
+
+       UsbCfg.word = 0;
+       UsbCfg.field.phyclear = 0;
+       /* usb version is 1.1,do not use bulk in aggregation */
+       if (pAd->BulkInMaxPacketSize == 512)
+                       UsbCfg.field.RxBulkAggEn = 1;
+       /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
+       UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE /1024)-3;
+       UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */
+       UsbCfg.field.RxBulkEn = 1;
+       UsbCfg.field.TxBulkEn = 1;
+
+       RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word);
+
+}
+
+/*
+========================================================================
+Routine Description:
+    Write Beacon buffer to Asic.
+
+Arguments:
+       *pAd                            the raxx interface data pointer
+
+Return Value:
+       None
+
+Note:
+========================================================================
+*/
+VOID RT28xx_UpdateBeaconToAsic(
+       IN RTMP_ADAPTER         *pAd,
+       IN INT                          apidx,
+       IN ULONG                        FrameLen,
+       IN ULONG                        UpdatePos)
+{
+       PUCHAR          pBeaconFrame = NULL;
+       UCHAR                   *ptr;
+       UINT                    i, padding;
+       BEACON_SYNC_STRUCT      *pBeaconSync = pAd->CommonCfg.pBeaconSync;
+       UINT32                  longValue;
+       BOOLEAN                 bBcnReq = FALSE;
+       UCHAR                   bcn_idx = 0;
+
+
+       if (pBeaconFrame == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("pBeaconFrame is NULL!\n"));
+               return;
+       }
+
+       if (pBeaconSync == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("pBeaconSync is NULL!\n"));
+               return;
+       }
+
+       //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) ||
+       //      ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
+       //      )
+       if (bBcnReq == FALSE)
+       {
+               /* when the ra interface is down, do not send its beacon frame */
+               /* clear all zero */
+               for(i=0; i<TXWI_SIZE; i+=4) {
+                       RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
+               }
+               pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
+               NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE);
+       }
+       else
+       {
+               ptr = (PUCHAR)&pAd->BeaconTxWI;
+#ifdef RT_BIG_ENDIAN
+               RTMPWIEndianChange(ptr, TYPE_TXWI);
+#endif
+               if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE)
+               {       // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames.
+                       pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
+                       NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE);
+               }
+
+               if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != (1 << bcn_idx))
+               {
+                       for (i=0; i<TXWI_SIZE; i+=4)  // 16-byte TXWI field
+                       {
+                               longValue =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
+                               RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longValue);
+                               ptr += 4;
+                       }
+               }
+
+               ptr = pBeaconSync->BeaconBuf[bcn_idx];
+               padding = (FrameLen & 0x01);
+               NdisZeroMemory((PUCHAR)(pBeaconFrame + FrameLen), padding);
+               FrameLen += padding;
+               for (i = 0 ; i < FrameLen /*HW_BEACON_OFFSET*/; i += 2)
+               {
+                       if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE)
+                       {
+                               NdisMoveMemory(ptr, pBeaconFrame, 2);
+                               //shortValue = *ptr + (*(ptr+1)<<8);
+                               //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue);
+                               RTUSBMultiWrite(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, ptr, 2);
+                       }
+                       ptr +=2;
+                       pBeaconFrame += 2;
+               }
+
+               pBeaconSync->BeaconBitMap |= (1 << bcn_idx);
+       }
+
+}
+
+
+VOID RT2870_BssBeaconStop(
+       IN RTMP_ADAPTER *pAd)
+{
+       BEACON_SYNC_STRUCT      *pBeaconSync;
+       int i, offset;
+       BOOLEAN Cancelled = TRUE;
+
+       pBeaconSync = pAd->CommonCfg.pBeaconSync;
+       if (pBeaconSync && pBeaconSync->EnableBeacon)
+       {
+               INT NumOfBcn;
+
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       NumOfBcn = MAX_MESH_NUM;
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+               RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
+
+               for(i=0; i<NumOfBcn; i++)
+               {
+                       NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
+                       NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
+
+                       for (offset=0; offset<HW_BEACON_OFFSET; offset+=4)
+                               RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[i] + offset, 0x00);
+
+                       pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
+                       pBeaconSync->TimIELocationInBeacon[i] = 0;
+               }
+               pBeaconSync->BeaconBitMap = 0;
+               pBeaconSync->DtimBitOn = 0;
+       }
+}
+
+
+VOID RT2870_BssBeaconStart(
+       IN RTMP_ADAPTER *pAd)
+{
+       int apidx;
+       BEACON_SYNC_STRUCT      *pBeaconSync;
+//     LARGE_INTEGER   tsfTime, deltaTime;
+
+       pBeaconSync = pAd->CommonCfg.pBeaconSync;
+       if (pBeaconSync && pBeaconSync->EnableBeacon)
+       {
+               INT NumOfBcn;
+
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       NumOfBcn = MAX_MESH_NUM;
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+               for(apidx=0; apidx<NumOfBcn; apidx++)
+               {
+                       UCHAR CapabilityInfoLocationInBeacon = 0;
+                       UCHAR TimIELocationInBeacon = 0;
+
+                       NdisZeroMemory(pBeaconSync->BeaconBuf[apidx], HW_BEACON_OFFSET);
+                       pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = CapabilityInfoLocationInBeacon;
+                       pBeaconSync->TimIELocationInBeacon[apidx] = TimIELocationInBeacon;
+                       NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], TXWI_SIZE);
+               }
+               pBeaconSync->BeaconBitMap = 0;
+               pBeaconSync->DtimBitOn = 0;
+               pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE;
+
+               pAd->CommonCfg.BeaconAdjust = 0;
+               pAd->CommonCfg.BeaconFactor = 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10);
+               pAd->CommonCfg.BeaconRemain = (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1;
+               printk("RT2870_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd->CommonCfg.BeaconFactor, pAd->CommonCfg.BeaconRemain);
+               RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, pAd->CommonCfg.BeaconPeriod);
+
+       }
+}
+
+
+VOID RT2870_BssBeaconInit(
+       IN RTMP_ADAPTER *pAd)
+{
+       BEACON_SYNC_STRUCT      *pBeaconSync;
+       int i;
+
+       NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(BEACON_SYNC_STRUCT), MEM_ALLOC_FLAG);
+       if (pAd->CommonCfg.pBeaconSync)
+       {
+               pBeaconSync = pAd->CommonCfg.pBeaconSync;
+               NdisZeroMemory(pBeaconSync, sizeof(BEACON_SYNC_STRUCT));
+               for(i=0; i < HW_BEACON_MAX_COUNT; i++)
+               {
+                       NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
+                       pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
+                       pBeaconSync->TimIELocationInBeacon[i] = 0;
+                       NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
+               }
+               pBeaconSync->BeaconBitMap = 0;
+
+               //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE);
+               pBeaconSync->EnableBeacon = TRUE;
+       }
+}
+
+
+VOID RT2870_BssBeaconExit(
+       IN RTMP_ADAPTER *pAd)
+{
+       BEACON_SYNC_STRUCT      *pBeaconSync;
+       BOOLEAN Cancelled = TRUE;
+       int i;
+
+       if (pAd->CommonCfg.pBeaconSync)
+       {
+               pBeaconSync = pAd->CommonCfg.pBeaconSync;
+               pBeaconSync->EnableBeacon = FALSE;
+               RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
+               pBeaconSync->BeaconBitMap = 0;
+
+               for(i=0; i<HW_BEACON_MAX_COUNT; i++)
+               {
+                       NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
+                       pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
+                       pBeaconSync->TimIELocationInBeacon[i] = 0;
+                       NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
+               }
+
+               NdisFreeMemory(pAd->CommonCfg.pBeaconSync, HW_BEACON_OFFSET * HW_BEACON_MAX_COUNT, 0);
+               pAd->CommonCfg.pBeaconSync = NULL;
+       }
+}
+
+VOID BeaconUpdateExec(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER)FunctionContext;
+       LARGE_INTEGER   tsfTime_a;//, tsfTime_b, deltaTime_exp, deltaTime_ab;
+       UINT32                  delta, remain, remain_low, remain_high;
+//     BOOLEAN                 positive;
+
+       ReSyncBeaconTime(pAd);
+
+
+
+       RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart);
+       RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart);
+
+
+       //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp);
+       remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart;
+       remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10);
+       remain = (remain_high + remain_low)%(pAd->CommonCfg.BeaconPeriod << 10);
+       delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain;
+
+       pAd->CommonCfg.BeaconUpdateTimer.TimerValue = (delta >> 10) + 10;
+
+}
+
diff --git a/drivers/staging/rt2870/Kconfig b/drivers/staging/rt2870/Kconfig
new file mode 100644 (file)
index 0000000..8398d97
--- /dev/null
@@ -0,0 +1,6 @@
+config RT2870
+       tristate "Ralink 2870 wireless support"
+       depends on USB && X86 && WLAN_80211
+       ---help---
+         This is an experimental driver for the Ralink 2870 wireless chip.
+
diff --git a/drivers/staging/rt2870/Makefile b/drivers/staging/rt2870/Makefile
new file mode 100644 (file)
index 0000000..1a015f4
--- /dev/null
@@ -0,0 +1,47 @@
+obj-$(CONFIG_RT2870)   += rt2870sta.o
+
+# TODO: all of these should be removed
+EXTRA_CFLAGS += -DLINUX -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT
+EXTRA_CFLAGS += -DRT2870
+EXTRA_CFLAGS += -DCONFIG_STA_SUPPORT
+EXTRA_CFLAGS += -DDBG
+EXTRA_CFLAGS += -DDOT11_N_SUPPORT
+EXTRA_CFLAGS += -DWPA_SUPPLICANT_SUPPORT
+EXTRA_CFLAGS += -DNATIVE_WPA_SUPPLICANT_SUPPORT
+
+rt2870sta-objs :=              \
+       common/md5.o            \
+       common/mlme.o           \
+       common/rtmp_wep.o       \
+       common/action.o         \
+       common/cmm_data.o       \
+       common/rtmp_init.o      \
+       common/rtmp_tkip.o      \
+       common/cmm_sync.o       \
+       common/eeprom.o         \
+       common/cmm_sanity.o     \
+       common/cmm_info.o       \
+       common/cmm_wpa.o        \
+       common/dfs.o            \
+       common/spectrum.o       \
+       sta/assoc.o             \
+       sta/aironet.o           \
+       sta/auth.o              \
+       sta/auth_rsp.o          \
+       sta/sync.o              \
+       sta/sanity.o            \
+       sta/rtmp_data.o         \
+       sta/connect.o           \
+       sta/wpa.o               \
+       rt_linux.o              \
+       rt_profile.o            \
+       rt_main_dev.o           \
+       sta_ioctl.o             \
+       common/ba_action.o      \
+       2870_main_dev.o         \
+       common/2870_rtmp_init.o \
+       common/rtusb_io.o       \
+       common/rtusb_bulk.o     \
+       common/rtusb_data.o     \
+       common/cmm_data_2870.o
+
diff --git a/drivers/staging/rt2870/TODO b/drivers/staging/rt2870/TODO
new file mode 100644 (file)
index 0000000..eae1ac4
--- /dev/null
@@ -0,0 +1,10 @@
+TODO:
+       - checkpatch.pl clean
+       - sparse clean
+       - port to in-kernel 80211 stack
+       - remove reading from /etc/ config files
+       - review by the wireless developer community
+
+Please send any patches or complaints about this driver to Greg
+Kroah-Hartman <greg@kroah.com> and don't bother the upstream wireless
+kernel developers about it, they want nothing to do with it.
diff --git a/drivers/staging/rt2870/aironet.h b/drivers/staging/rt2870/aironet.h
new file mode 100644 (file)
index 0000000..1e07b19
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       aironet.h
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Name            Date                    Modification logs
+       Paul Lin        04-06-15                Initial
+*/
+
+#ifndef        __AIRONET_H__
+#define        __AIRONET_H__
+
+// Measurement Type definition
+#define        MSRN_TYPE_UNUSED                                0
+#define        MSRN_TYPE_CHANNEL_LOAD_REQ              1
+#define        MSRN_TYPE_NOISE_HIST_REQ                2
+#define        MSRN_TYPE_BEACON_REQ                    3
+#define        MSRN_TYPE_FRAME_REQ                             4
+
+// Scan Mode in Beacon Request
+#define        MSRN_SCAN_MODE_PASSIVE                  0
+#define        MSRN_SCAN_MODE_ACTIVE                   1
+#define        MSRN_SCAN_MODE_BEACON_TABLE             2
+
+// PHY type definition for Aironet beacon report, CCX 2 table 36-9
+#define        PHY_FH                                                  1
+#define        PHY_DSS                                                 2
+#define        PHY_UNUSED                                              3
+#define        PHY_OFDM                                                4
+#define        PHY_HR_DSS                                              5
+#define        PHY_ERP                                                 6
+
+// RPI table in dBm
+#define        RPI_0                   0                       //      Power <= -87
+#define        RPI_1                   1                       //      -87 < Power <= -82
+#define        RPI_2                   2                       //      -82 < Power <= -77
+#define        RPI_3                   3                       //      -77 < Power <= -72
+#define        RPI_4                   4                       //      -72 < Power <= -67
+#define        RPI_5                   5                       //      -67 < Power <= -62
+#define        RPI_6                   6                       //      -62 < Power <= -57
+#define        RPI_7                   7                       //      -57 < Power
+
+// Cisco Aironet IAPP definetions
+#define        AIRONET_IAPP_TYPE                                       0x32
+#define        AIRONET_IAPP_SUBTYPE_REQUEST            0x01
+#define        AIRONET_IAPP_SUBTYPE_REPORT                     0x81
+
+// Measurement Request detail format
+typedef        struct  _MEASUREMENT_REQUEST    {
+       UCHAR   Channel;
+       UCHAR   ScanMode;                       // Use only in beacon request, other requests did not use this field
+       USHORT  Duration;
+}      MEASUREMENT_REQUEST, *PMEASUREMENT_REQUEST;
+
+// Beacon Measurement Report
+// All these field might change to UCHAR, because we didn't do anything to these report.
+// We copy all these beacons and report to CCX 2 AP.
+typedef        struct  _BEACON_REPORT  {
+       UCHAR   Channel;
+       UCHAR   Spare;
+       USHORT  Duration;
+       UCHAR   PhyType;                        // Definiation is listed above table 36-9
+       UCHAR   RxPower;
+       UCHAR   BSSID[6];
+       UCHAR   ParentTSF[4];
+       UCHAR   TargetTSF[8];
+       USHORT  BeaconInterval;
+       USHORT  CapabilityInfo;
+}      BEACON_REPORT, *PBEACON_REPORT;
+
+// Frame Measurement Report (Optional)
+typedef        struct  _FRAME_REPORT   {
+       UCHAR   Channel;
+       UCHAR   Spare;
+       USHORT  Duration;
+       UCHAR   TA;
+       UCHAR   BSSID[6];
+       UCHAR   RSSI;
+       UCHAR   Count;
+}      FRAME_REPORT, *PFRAME_REPORT;
+
+#pragma pack(1)
+// Channel Load Report
+typedef        struct  _CHANNEL_LOAD_REPORT    {
+       UCHAR   Channel;
+       UCHAR   Spare;
+       USHORT  Duration;
+       UCHAR   CCABusy;
+}      CHANNEL_LOAD_REPORT, *PCHANNEL_LOAD_REPORT;
+#pragma pack()
+
+// Nosie Histogram Report
+typedef        struct  _NOISE_HIST_REPORT      {
+       UCHAR   Channel;
+       UCHAR   Spare;
+       USHORT  Duration;
+       UCHAR   Density[8];
+}      NOISE_HIST_REPORT, *PNOISE_HIST_REPORT;
+
+// Radio Management Capability element
+typedef        struct  _RADIO_MANAGEMENT_CAPABILITY    {
+       UCHAR   Eid;                            // TODO: Why the Eid is 1 byte, not normal 2 bytes???
+       UCHAR   Length;
+       UCHAR   AironetOui[3];          // AIronet OUI (00 40 96)
+       UCHAR   Type;                           // Type / Version
+       USHORT  Status;                         // swap16 required
+}      RADIO_MANAGEMENT_CAPABILITY, *PRADIO_MANAGEMENT_CAPABILITY;
+
+// Measurement Mode Bit definition
+typedef        struct  _MEASUREMENT_MODE       {
+       UCHAR   Rsvd:4;
+       UCHAR   Report:1;
+       UCHAR   NotUsed:1;
+       UCHAR   Enable:1;
+       UCHAR   Parallel:1;
+}      MEASUREMENT_MODE, *PMEASUREMENT_MODE;
+
+// Measurement Request element, This is little endian mode
+typedef        struct  _MEASUREMENT_REQUEST_ELEMENT    {
+       USHORT                          Eid;
+       USHORT                          Length;                         // swap16 required
+       USHORT                          Token;                          // non-zero unique token
+       UCHAR                           Mode;                           // Measurement Mode
+       UCHAR                           Type;                           // Measurement type
+}      MEASUREMENT_REQUEST_ELEMENT, *PMEASUREMENT_REQUEST_ELEMENT;
+
+// Measurement Report element, This is little endian mode
+typedef        struct  _MEASUREMENT_REPORT_ELEMENT     {
+       USHORT                          Eid;
+       USHORT                          Length;                         // swap16 required
+       USHORT                          Token;                          // non-zero unique token
+       UCHAR                           Mode;                           // Measurement Mode
+       UCHAR                           Type;                           // Measurement type
+}      MEASUREMENT_REPORT_ELEMENT, *PMEASUREMENT_REPORT_ELEMENT;
+
+// Cisco Aironet IAPP Frame Header, Network byte order used
+typedef        struct  _AIRONET_IAPP_HEADER {
+       UCHAR   CiscoSnapHeader[8];     // 8 bytes Cisco snap header
+       USHORT  Length;                         // IAPP ID & length, remember to swap16 in LE system
+       UCHAR   Type;                           // IAPP type
+       UCHAR   SubType;                        // IAPP subtype
+       UCHAR   DA[6];                          // Destination MAC address
+       UCHAR   SA[6];                          // Source MAC address
+       USHORT  Token;                          // Dialog token, no need to swap16 since it is for yoken usage only
+}      AIRONET_IAPP_HEADER, *PAIRONET_IAPP_HEADER;
+
+// Radio Measurement Request frame
+typedef        struct  _AIRONET_RM_REQUEST_FRAME       {
+    AIRONET_IAPP_HEADER        IAPP;                   // Common header
+       UCHAR                           Delay;                  // Activation Delay
+       UCHAR                           Offset;                 // Measurement offset
+}      AIRONET_RM_REQUEST_FRAME, *PAIRONET_RM_REQUEST_FRAME;
+
+// Radio Measurement Report frame
+typedef        struct  _AIRONET_RM_REPORT_FRAME        {
+    AIRONET_IAPP_HEADER        IAPP;                   // Common header
+}      AIRONET_RM_REPORT_FRAME, *PAIRONET_RM_REPORT_FRAME;
+
+// Saved element request actions which will saved in StaCfg.
+typedef        struct  _RM_REQUEST_ACTION      {
+       MEASUREMENT_REQUEST_ELEMENT     ReqElem;                // Saved request element
+       MEASUREMENT_REQUEST                     Measurement;    // Saved measurement within the request element
+}      RM_REQUEST_ACTION, *PRM_REQUEST_ACTION;
+
+// CCX administration control
+typedef        union   _CCX_CONTROL    {
+       struct  {
+               UINT32          Enable:1;                       // Enable CCX2
+               UINT32          LeapEnable:1;           // Enable LEAP at CCX2
+               UINT32          RMEnable:1;                     // Radio Measurement Enable
+               UINT32          DCRMEnable:1;           // Non serving channel Radio Measurement enable
+               UINT32          QOSEnable:1;            // Enable QOS for CCX 2.0 support
+               UINT32          FastRoamEnable:1;       // Enable fast roaming
+               UINT32          Rsvd:2;                         // Not used
+               UINT32          dBmToRoam:8;            // the condition to roam when receiving Rssi less than this value. It's negative value.
+               UINT32          TuLimit:16;                     // Limit for different channel scan
+       }       field;
+       UINT32                  word;
+}      CCX_CONTROL, *PCCX_CONTROL;
+
+#endif // __AIRONET_H__
diff --git a/drivers/staging/rt2870/ap.h b/drivers/staging/rt2870/ap.h
new file mode 100644 (file)
index 0000000..0dc5575
--- /dev/null
@@ -0,0 +1,562 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    ap.h
+
+    Abstract:
+    Miniport generic portion header file
+
+    Revision History:
+    Who         When          What
+    --------    ----------    ----------------------------------------------
+    Paul Lin    08-01-2002    created
+    James Tan   09-06-2002    modified (Revise NTCRegTable)
+    John Chang  12-22-2004    modified for RT2561/2661. merge with STA driver
+*/
+#ifndef __AP_H__
+#define __AP_H__
+
+
+
+// ========================= AP RTMP.h ================================
+
+
+
+// =============================================================
+//      Function Prototypes
+// =============================================================
+
+// ap_data.c
+
+BOOLEAN APBridgeToWirelessSta(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          pHeader,
+    IN  UINT            HdrLen,
+    IN  PUCHAR          pData,
+    IN  UINT            DataLen,
+    IN  ULONG           fromwdsidx);
+
+BOOLEAN APHandleRxDoneInterrupt(
+    IN  PRTMP_ADAPTER   pAd);
+
+VOID   APSendPackets(
+       IN      NDIS_HANDLE             MiniportAdapterContext,
+       IN      PPNDIS_PACKET   ppPacketArray,
+       IN      UINT                    NumberOfPackets);
+
+NDIS_STATUS APSendPacket(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PNDIS_PACKET    pPacket);
+
+
+NDIS_STATUS APHardTransmit(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      UCHAR                   QueIdx);
+
+VOID APRxEAPOLFrameIndicate(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MAC_TABLE_ENTRY *pEntry,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID);
+
+NDIS_STATUS APCheckRxError(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PRT28XX_RXD_STRUC               pRxD,
+       IN      UCHAR                   Wcid);
+
+BOOLEAN APCheckClass2Class3Error(
+    IN  PRTMP_ADAPTER   pAd,
+       IN ULONG Wcid,
+       IN  PHEADER_802_11  pHeader);
+
+VOID APHandleRxPsPoll(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pAddr,
+       IN      USHORT                  Aid,
+    IN BOOLEAN                 isActive);
+
+VOID    RTMPDescriptorEndianChange(
+    IN  PUCHAR          pData,
+    IN  ULONG           DescriptorType);
+
+VOID    RTMPFrameEndianChange(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          pData,
+    IN  ULONG           Dir,
+    IN  BOOLEAN         FromRxDoneInt);
+
+// ap_assoc.c
+
+VOID APAssocStateMachineInit(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  STATE_MACHINE *S,
+    OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID  APPeerAssocReqAction(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  MLME_QUEUE_ELEM *Elem);
+
+VOID  APPeerReassocReqAction(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  MLME_QUEUE_ELEM *Elem);
+
+VOID  APPeerDisassocReqAction(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  MLME_QUEUE_ELEM *Elem);
+
+VOID MbssKickOutStas(
+       IN PRTMP_ADAPTER pAd,
+       IN INT apidx,
+       IN USHORT Reason);
+
+VOID APMlmeKickOutSta(
+    IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pStaAddr,
+       IN UCHAR Wcid,
+       IN USHORT Reason);
+
+VOID APMlmeDisassocReqAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID  APCls3errAction(
+    IN  PRTMP_ADAPTER   pAd,
+       IN      ULONG Wcid,
+    IN PHEADER_802_11  pHeader);
+
+
+USHORT APBuildAssociation(
+    IN PRTMP_ADAPTER pAd,
+    IN MAC_TABLE_ENTRY *pEntry,
+    IN USHORT CapabilityInfo,
+    IN UCHAR  MaxSupportedRateIn500Kbps,
+    IN UCHAR  *RSN,
+    IN UCHAR  *pRSNLen,
+    IN BOOLEAN bWmmCapable,
+    IN ULONG  RalinkIe,
+#ifdef DOT11N_DRAFT3
+    IN EXT_CAP_INFO_ELEMENT ExtCapInfo,
+#endif // DOT11N_DRAFT3 //
+       IN HT_CAPABILITY_IE             *pHtCapability,
+       IN UCHAR                 HtCapabilityLen,
+    OUT USHORT *pAid);
+
+/*
+VOID   RTMPAddClientSec(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR   BssIdx,
+       IN UCHAR                 KeyIdx,
+       IN UCHAR                 CipherAlg,
+       IN PUCHAR                pKey,
+       IN PUCHAR                pTxMic,
+       IN PUCHAR                pRxMic,
+       IN MAC_TABLE_ENTRY *pEntry);
+*/
+
+// ap_auth.c
+
+void APAuthStateMachineInit(
+    IN PRTMP_ADAPTER pAd,
+    IN STATE_MACHINE *Sm,
+    OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID APMlmeDeauthReqAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID APCls2errAction(
+    IN PRTMP_ADAPTER pAd,
+       IN      ULONG Wcid,
+    IN PHEADER_802_11  pHeader);
+
+// ap_authrsp.c
+
+VOID APAuthRspStateMachineInit(
+    IN PRTMP_ADAPTER pAd,
+    IN PSTATE_MACHINE Sm,
+    IN STATE_MACHINE_FUNC Trans[]);
+
+VOID APPeerAuthAtAuthRspIdleAction(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerDeauthReqAction(
+    IN PRTMP_ADAPTER   pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerAuthSimpleRspGenAndSend(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PHEADER_802_11 pHdr80211,
+    IN  USHORT Alg,
+    IN  USHORT Seq,
+    IN  USHORT StatusCode);
+
+// ap_connect.c
+
+BOOLEAN BeaconTransmitRequired(
+       IN PRTMP_ADAPTER        pAd,
+       IN INT                          apidx);
+
+VOID APMakeBssBeacon(
+    IN  PRTMP_ADAPTER   pAd,
+       IN      INT                             apidx);
+
+VOID  APUpdateBeaconFrame(
+    IN  PRTMP_ADAPTER   pAd,
+       IN      INT                             apidx);
+
+VOID APMakeAllBssBeacon(
+    IN  PRTMP_ADAPTER   pAd);
+
+VOID  APUpdateAllBeaconFrame(
+    IN  PRTMP_ADAPTER   pAd);
+
+
+// ap_sync.c
+
+VOID APSyncStateMachineInit(
+    IN PRTMP_ADAPTER pAd,
+    IN STATE_MACHINE *Sm,
+    OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID APScanTimeout(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID APInvalidStateWhenScan(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID APScanTimeoutAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerProbeReqAction(
+    IN  PRTMP_ADAPTER pAd,
+    IN  MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerBeaconAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID APMlmeScanReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerBeaconAtScanAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID APScanCnclAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID ApSiteSurvey(
+       IN PRTMP_ADAPTER pAd);
+
+VOID SupportRate(
+       IN PUCHAR SupRate,
+       IN UCHAR SupRateLen,
+       IN PUCHAR ExtRate,
+       IN UCHAR ExtRateLen,
+       OUT PUCHAR *Rates,
+       OUT PUCHAR RatesLen,
+       OUT PUCHAR pMaxSupportRate);
+
+
+BOOLEAN ApScanRunning(
+       IN PRTMP_ADAPTER pAd);
+
+#ifdef DOT11N_DRAFT3
+VOID APOverlappingBSSScan(
+       IN RTMP_ADAPTER *pAd);
+#endif // DOT11N_DRAFT3 //
+
+// ap_wpa.c
+
+VOID APWpaStateMachineInit(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  STATE_MACHINE *Sm,
+    OUT STATE_MACHINE_FUNC Trans[]);
+
+// ap_mlme.c
+
+VOID APMlmePeriodicExec(
+    IN  PRTMP_ADAPTER   pAd);
+
+VOID APMlmeSelectTxRateTable(
+       IN PRTMP_ADAPTER                pAd,
+       IN PMAC_TABLE_ENTRY             pEntry,
+       IN PUCHAR                               *ppTable,
+       IN PUCHAR                               pTableSize,
+       IN PUCHAR                               pInitTxRateIdx);
+
+VOID APMlmeSetTxRate(
+       IN PRTMP_ADAPTER                pAd,
+       IN PMAC_TABLE_ENTRY             pEntry,
+       IN PRTMP_TX_RATE_SWITCH pTxRate);
+
+VOID APMlmeDynamicTxRateSwitching(
+    IN PRTMP_ADAPTER pAd);
+
+VOID APQuickResponeForRateUpExec(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3);
+
+BOOLEAN APMsgTypeSubst(
+    IN PRTMP_ADAPTER pAd,
+    IN PFRAME_802_11 pFrame,
+    OUT INT *Machine,
+    OUT INT *MsgType);
+
+VOID APQuickResponeForRateUpExec(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3);
+
+#ifdef RT2870
+VOID BeaconUpdateExec(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3);
+#endif // RT2870 //
+
+VOID RTMPSetPiggyBack(
+       IN PRTMP_ADAPTER        pAd,
+       IN BOOLEAN                      bPiggyBack);
+
+VOID APAsicEvaluateRxAnt(
+       IN PRTMP_ADAPTER        pAd);
+
+VOID APAsicRxAntEvalTimeout(
+       IN PRTMP_ADAPTER        pAd);
+
+// ap.c
+
+VOID APSwitchChannel(
+       IN PRTMP_ADAPTER pAd,
+       IN INT Channel);
+
+NDIS_STATUS APInitialize(
+    IN  PRTMP_ADAPTER   pAd);
+
+VOID APShutdown(
+    IN PRTMP_ADAPTER    pAd);
+
+VOID APStartUp(
+    IN  PRTMP_ADAPTER   pAd);
+
+VOID APStop(
+    IN  PRTMP_ADAPTER   pAd);
+
+VOID APCleanupPsQueue(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PQUEUE_HEADER   pQueue);
+
+VOID MacTableReset(
+    IN  PRTMP_ADAPTER   pAd);
+
+MAC_TABLE_ENTRY *MacTableInsertEntry(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          pAddr,
+       IN      UCHAR                   apidx,
+       IN BOOLEAN      CleanAll);
+
+BOOLEAN MacTableDeleteEntry(
+    IN  PRTMP_ADAPTER   pAd,
+       IN USHORT wcid,
+    IN  PUCHAR          pAddr);
+
+MAC_TABLE_ENTRY *MacTableLookup(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          pAddr);
+
+VOID MacTableMaintenance(
+    IN PRTMP_ADAPTER pAd);
+
+UINT32 MacTableAssocStaNumGet(
+       IN PRTMP_ADAPTER pAd);
+
+MAC_TABLE_ENTRY *APSsPsInquiry(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          pAddr,
+    OUT SST             *Sst,
+    OUT USHORT          *Aid,
+    OUT UCHAR           *PsMode,
+    OUT UCHAR           *Rate);
+
+BOOLEAN APPsIndicate(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          pAddr,
+       IN ULONG Wcid,
+    IN  UCHAR           Psm);
+
+VOID ApLogEvent(
+    IN PRTMP_ADAPTER    pAd,
+    IN PUCHAR           pAddr,
+    IN USHORT           Event);
+
+#ifdef DOT11_N_SUPPORT
+VOID APUpdateOperationMode(
+    IN PRTMP_ADAPTER pAd);
+#endif // DOT11_N_SUPPORT //
+
+VOID APUpdateCapabilityAndErpIe(
+       IN PRTMP_ADAPTER pAd);
+
+BOOLEAN ApCheckAccessControlList(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR        pAddr,
+       IN UCHAR         Apidx);
+
+VOID ApUpdateAccessControlList(
+    IN PRTMP_ADAPTER pAd,
+    IN UCHAR         Apidx);
+
+VOID ApEnqueueNullFrame(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR        pAddr,
+       IN UCHAR         TxRate,
+       IN UCHAR         PID,
+       IN UCHAR         apidx,
+    IN BOOLEAN       bQosNull,
+    IN BOOLEAN       bEOSP,
+    IN UCHAR         OldUP);
+
+VOID ApSendFrame(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PVOID           pBuffer,
+    IN  ULONG           Length,
+    IN  UCHAR           TxRate,
+    IN  UCHAR           PID);
+
+VOID ApEnqueueAckFrame(
+    IN PRTMP_ADAPTER pAd,
+    IN PUCHAR        pAddr,
+    IN UCHAR         TxRate,
+       IN UCHAR         apidx);
+
+UCHAR APAutoSelectChannel(
+       IN PRTMP_ADAPTER pAd,
+       IN BOOLEAN Optimal);
+
+// ap_sanity.c
+
+
+BOOLEAN PeerAssocReqCmmSanity(
+    IN PRTMP_ADAPTER pAd,
+       IN BOOLEAN isRessoc,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr2,
+    OUT USHORT *pCapabilityInfo,
+    OUT USHORT *pListenInterval,
+    OUT PUCHAR pApAddr,
+    OUT UCHAR *pSsidLen,
+    OUT char *Ssid,
+    OUT UCHAR *pRatesLen,
+    OUT UCHAR Rates[],
+    OUT UCHAR *RSN,
+    OUT UCHAR *pRSNLen,
+    OUT BOOLEAN *pbWmmCapable,
+#ifdef WSC_AP_SUPPORT
+    OUT BOOLEAN *pWscCapable,
+#endif // WSC_AP_SUPPORT //
+    OUT ULONG  *pRalinkIe,
+#ifdef DOT11N_DRAFT3
+    OUT EXT_CAP_INFO_ELEMENT   *pExtCapInfo,
+#endif // DOT11N_DRAFT3 //
+    OUT UCHAR           *pHtCapabilityLen,
+    OUT HT_CAPABILITY_IE *pHtCapability);
+
+BOOLEAN PeerDisassocReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr2,
+    OUT USHORT *Reason);
+
+BOOLEAN PeerDeauthReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr2,
+    OUT USHORT *Reason);
+
+BOOLEAN APPeerAuthSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+       OUT PUCHAR pAddr1,
+    OUT PUCHAR pAddr2,
+    OUT USHORT *Alg,
+    OUT USHORT *Seq,
+    OUT USHORT *Status,
+    CHAR *ChlgText);
+
+BOOLEAN APPeerProbeReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr2,
+    OUT CHAR Ssid[],
+    OUT UCHAR *SsidLen);
+
+BOOLEAN APPeerBeaconAndProbeRspSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr2,
+    OUT PUCHAR pBssid,
+    OUT CHAR Ssid[],
+    OUT UCHAR *SsidLen,
+    OUT UCHAR *BssType,
+    OUT USHORT *BeaconPeriod,
+    OUT UCHAR *Channel,
+    OUT LARGE_INTEGER *Timestamp,
+    OUT USHORT *CapabilityInfo,
+    OUT UCHAR Rate[],
+    OUT UCHAR *RateLen,
+    OUT BOOLEAN *ExtendedRateIeExist,
+    OUT UCHAR *Erp);
+
+// ap_info.c
+
+
+
+// ================== end of AP RTMP.h ========================
+
+
+#endif  // __AP_H__
+
diff --git a/drivers/staging/rt2870/chlist.h b/drivers/staging/rt2870/chlist.h
new file mode 100644 (file)
index 0000000..9e15b9d
--- /dev/null
@@ -0,0 +1,1296 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       chlist.c
+
+       Abstract:
+
+       Revision History:
+       Who         When          What
+       --------    ----------    ----------------------------------------------
+       Fonchi Wu   2007-12-19    created
+*/
+
+#ifndef __CHLIST_H__
+#define __CHLIST_H__
+
+#include "rtmp_type.h"
+#include "rtmp_def.h"
+
+
+#define ODOR                   0
+#define IDOR                   1
+#define BOTH                   2
+
+#define BAND_5G         0
+#define BAND_24G        1
+#define BAND_BOTH       2
+
+typedef struct _CH_DESP {
+       UCHAR FirstChannel;
+       UCHAR NumOfCh;
+       CHAR MaxTxPwr;                  // dBm
+       UCHAR Geography;                        // 0:out door, 1:in door, 2:both
+       BOOLEAN DfsReq;                 // Dfs require, 0: No, 1: yes.
+} CH_DESP, *PCH_DESP;
+
+typedef struct _CH_REGION {
+       UCHAR CountReg[3];
+       UCHAR DfsType;                  // 0: CE, 1: FCC, 2: JAP, 3:JAP_W53, JAP_W56
+       CH_DESP ChDesp[10];
+} CH_REGION, *PCH_REGION;
+
+static CH_REGION ChRegion[] =
+{
+               {       // Antigua and Berbuda
+                       "AG",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  23, BOTH, FALSE},    // 5G, ch 52~64
+                               { 100, 11, 30, BOTH, FALSE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Argentina
+                       "AR",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 52,  4,  24, BOTH, FALSE},    // 5G, ch 52~64
+                               { 149, 4,  30, BOTH, FALSE},    // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Aruba
+                       "AW",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  23, BOTH, FALSE},    // 5G, ch 52~64
+                               { 100, 11, 30, BOTH, FALSE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Australia
+                       "AU",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  24, BOTH, FALSE},    // 5G, ch 52~64
+                               { 149, 5,  30, BOTH, FALSE},    // 5G, ch 149~165
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Austria
+                       "AT",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, IDOR, TRUE},             // 5G, ch 36~48
+                               { 52,  4,  23, IDOR, TRUE},             // 5G, ch 52~64
+                               { 100, 11, 30, BOTH, TRUE},             // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Bahamas
+                       "BS",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  24, BOTH, FALSE},    // 5G, ch 52~64
+                               { 149, 5,  30, BOTH, FALSE},    // 5G, ch 149~165
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Barbados
+                       "BB",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  24, BOTH, FALSE},    // 5G, ch 52~64
+                               { 100, 11, 30, BOTH, FALSE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Bermuda
+                       "BM",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  24, BOTH, FALSE},    // 5G, ch 52~64
+                               { 100, 11, 30, BOTH, FALSE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Brazil
+                       "BR",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  24, BOTH, FALSE},    // 5G, ch 52~64
+                               { 100, 11, 24, BOTH, FALSE},    // 5G, ch 100~140
+                               { 149, 5,  30, BOTH, FALSE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Belgium
+                       "BE",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  18, IDOR, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  18, IDOR, FALSE},    // 5G, ch 52~64
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Bulgaria
+                       "BG",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, IDOR, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  23, IDOR, TRUE},     // 5G, ch 52~64
+                               { 100, 11, 30, ODOR, TRUE},     // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Canada
+                       "CA",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  23, BOTH, FALSE},    // 5G, ch 52~64
+                               { 149, 5,  30, BOTH, FALSE},    // 5G, ch 149~165
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Cayman IsLands
+                       "KY",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  24, BOTH, FALSE},    // 5G, ch 52~64
+                               { 100, 11, 30, BOTH, FALSE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Chile
+                       "CL",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  20, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  20, BOTH, FALSE},    // 5G, ch 52~64
+                               { 149, 5,  20, BOTH, FALSE},    // 5G, ch 149~165
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // China
+                       "CN",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 149, 4,  27, BOTH, FALSE},    // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Colombia
+                       "CO",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  17, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  24, BOTH, FALSE},    // 5G, ch 52~64
+                               { 100, 11, 30, BOTH, FALSE},    // 5G, ch 100~140
+                               { 149, 5,  30, BOTH, FALSE},    // 5G, ch 149~165
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Costa Rica
+                       "CR",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  17, BOTH, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  24, BOTH, FALSE},    // 5G, ch 52~64
+                               { 149, 4,  30, BOTH, FALSE},    // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Cyprus
+                       "CY",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, IDOR, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  24, IDOR, TRUE},             // 5G, ch 52~64
+                               { 100, 11, 30, BOTH, TRUE},             // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Czech_Republic
+                       "CZ",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, IDOR, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  23, IDOR, TRUE},             // 5G, ch 52~64
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Denmark
+                       "DK",
+                       CE,
+                       {
+                               { 1,   13, 20, BOTH, FALSE},    // 2.4 G, ch 1~13
+                               { 36,  4,  23, IDOR, FALSE},    // 5G, ch 36~48
+                               { 52,  4,  23, IDOR, TRUE},             // 5G, ch 52~64
+                               { 100, 11, 30, BOTH, TRUE},             // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Dominican Republic
+                       "DO",
+                       CE,
+                       {
+                               { 1,   0,  20, BOTH, FALSE},    // 2.4 G, ch 0
+                               { 149, 4,  20, BOTH, FALSE},    // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Equador
+                       "EC",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 100, 11,  27, BOTH, FALSE},   // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // El Salvador
+                       "SV",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,  4,   23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,  4,   30, BOTH, TRUE},    // 5G, ch 52~64
+                               { 149, 4,   36, BOTH, TRUE},    // 5G, ch 149~165
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Finland
+                       "FI",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,  4,   23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,  4,   23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // France
+                       "FR",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,  4,   23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,  4,   23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Germany
+                       "DE",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,  4,   23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,  4,   23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Greece
+                       "GR",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,  4,   23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,  4,   23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, ODOR, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Guam
+                       "GU",
+                       CE,
+                       {
+                               { 1,   11,  20, BOTH, FALSE},   // 2.4 G, ch 1~11
+                               { 36,  4,   17, BOTH, FALSE},   // 5G, ch 36~48
+                               { 52,  4,   24, BOTH, FALSE},   // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, FALSE},   // 5G, ch 100~140
+                               { 149,  5,  30, BOTH, FALSE},   // 5G, ch 149~165
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Guatemala
+                       "GT",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,  4,   17, BOTH, FALSE},   // 5G, ch 36~48
+                               { 52,  4,   24, BOTH, FALSE},   // 5G, ch 52~64
+                               { 149,  4,  30, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Haiti
+                       "HT",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,  4,   17, BOTH, FALSE},   // 5G, ch 36~48
+                               { 52,  4,   24, BOTH, FALSE},   // 5G, ch 52~64
+                               { 149,  4,  30, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Honduras
+                       "HN",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 149,  4,  27, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Hong Kong
+                       "HK",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, FALSE},   // 5G, ch 52~64
+                               { 149,  4,  30, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Hungary
+                       "HU",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Iceland
+                       "IS",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // India
+                       "IN",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 149,  4,  24, IDOR, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Indonesia
+                       "ID",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 149,  4,  27, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Ireland
+                       "IE",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, ODOR, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Israel
+                       "IL",
+                       CE,
+                       {
+                               { 1,    3,  20, IDOR, FALSE},   // 2.4 G, ch 1~3
+                               { 4,    6,  20, BOTH, FALSE},   // 2.4 G, ch 4~9
+                               { 10,   4,  20, IDOR, FALSE},   // 2.4 G, ch 10~13
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Italy
+                       "IT",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, ODOR, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Japan
+                       "JP",
+                       JAP,
+                       {
+                               { 1,   14,  20, BOTH, FALSE},   // 2.4 G, ch 1~14
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Jordan
+                       "JO",
+                       CE,
+                       {
+                               { 1,   13,  20, IDOR, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 149,  4,  23, IDOR, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Latvia
+                       "LV",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Liechtenstein
+                       "LI",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Lithuania
+                       "LT",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Luxemburg
+                       "LU",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Malaysia
+                       "MY",
+                       CE,
+                       {
+                               { 36,   4,  23, BOTH, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, BOTH, FALSE},   // 5G, ch 52~64
+                               { 149,  5,  20, BOTH, FALSE},   // 5G, ch 149~165
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Malta
+                       "MT",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Marocco
+                       "MA",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  24, IDOR, FALSE},   // 5G, ch 36~48
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Mexico
+                       "MX",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, BOTH, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  24, BOTH, FALSE},   // 5G, ch 52~64
+                               { 149,  5,  30, IDOR, FALSE},   // 5G, ch 149~165
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Netherlands
+                       "NL",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  24, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // New Zealand
+                       "NZ",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  24, BOTH, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  24, BOTH, FALSE},   // 5G, ch 52~64
+                               { 149,  4,  30, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Norway
+                       "NO",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  24, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  24, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Peru
+                       "PE",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 149,  4,  27, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Portugal
+                       "PT",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Poland
+                       "PL",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Romania
+                       "RO",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Russia
+                       "RU",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 149,  4,  20, IDOR, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Saudi Arabia
+                       "SA",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, BOTH, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, BOTH, FALSE},   // 5G, ch 52~64
+                               { 149,  4,  23, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Serbia_and_Montenegro
+                       "CS",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Singapore
+                       "SG",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, BOTH, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, BOTH, FALSE},   // 5G, ch 52~64
+                               { 149,  4,  20, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Slovakia
+                       "SK",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Slovenia
+                       "SI",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // South Africa
+                       "ZA",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, BOTH, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, FALSE},   // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 149,  4,  30, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // South Korea
+                       "KR",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  20, BOTH, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  20, BOTH, FALSE},   // 5G, ch 52~64
+                               { 100,  8,  20, BOTH, FALSE},   // 5G, ch 100~128
+                               { 149,  4,  20, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Spain
+                       "ES",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  17, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Sweden
+                       "SE",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Switzerland
+                       "CH",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~13
+                               { 36,   4,  23, IDOR, TRUE},    // 5G, ch 36~48
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Taiwan
+                       "TW",
+                       CE,
+                       {
+                               { 1,   11,  30, BOTH, FALSE},   // 2.4 G, ch 1~11
+                               { 52,   4,  23, IDOR, FALSE},   // 5G, ch 52~64
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Turkey
+                       "TR",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~11
+                               { 36,   4,  23, BOTH, FALSE},   // 5G, ch 36~48
+                               { 52,   4,  23, BOTH, FALSE},   // 5G, ch 52~64
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // UK
+                       "GB",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~11
+                               { 36,   4,  23, IDOR, FALSE},   // 5G, ch 52~64
+                               { 52,   4,  23, IDOR, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Ukraine
+                       "UA",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~11
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // United_Arab_Emirates
+                       "AE",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~11
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // United_States
+                       "US",
+                       CE,
+                       {
+                               { 1,   11,  30, BOTH, FALSE},   // 2.4 G, ch 1~11
+                               { 36,   4,  17, IDOR, FALSE},   // 5G, ch 52~64
+                               { 52,   4,  24, BOTH, TRUE},    // 5G, ch 52~64
+                               { 100, 11,  30, BOTH, TRUE},    // 5G, ch 100~140
+                               { 149,  5,  30, BOTH, FALSE},   // 5G, ch 149~165
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Venezuela
+                       "VE",
+                       CE,
+                       {
+                               { 1,   13,  20, BOTH, FALSE},   // 2.4 G, ch 1~11
+                               { 149,  4,  27, BOTH, FALSE},   // 5G, ch 149~161
+                               { 0},                                                   // end
+                       }
+               },
+
+               {       // Default
+                       "",
+                       CE,
+                       {
+                               { 1,   11,  20, BOTH, FALSE},   // 2.4 G, ch 1~11
+                               { 36,   4,  20, BOTH, FALSE},   // 5G, ch 52~64
+                               { 52,   4,  20, BOTH, FALSE},   // 5G, ch 52~64
+                               { 100, 11,  20, BOTH, FALSE},   // 5G, ch 100~140
+                               { 149,  5,  20, BOTH, FALSE},   // 5G, ch 149~165
+                               { 0},                                                   // end
+                       }
+               },
+};
+
+static inline PCH_REGION GetChRegion(
+       IN PUCHAR CntryCode)
+{
+       INT loop = 0;
+       PCH_REGION pChRegion = NULL;
+
+       while (strcmp(ChRegion[loop].CountReg, "") != 0)
+       {
+               if (strncmp(ChRegion[loop].CountReg, CntryCode, 2) == 0)
+               {
+                       pChRegion = &ChRegion[loop];
+                       break;
+               }
+               loop++;
+       }
+
+       if (pChRegion == NULL)
+               pChRegion = &ChRegion[loop];
+       return pChRegion;
+}
+
+static inline VOID ChBandCheck(
+       IN UCHAR PhyMode,
+       OUT PUCHAR pChType)
+{
+       switch(PhyMode)
+       {
+               case PHY_11A:
+#ifdef DOT11_N_SUPPORT
+               case PHY_11AN_MIXED:
+#endif // DOT11_N_SUPPORT //
+                       *pChType = BAND_5G;
+                       break;
+               case PHY_11ABG_MIXED:
+#ifdef DOT11_N_SUPPORT
+               case PHY_11AGN_MIXED:
+               case PHY_11ABGN_MIXED:
+#endif // DOT11_N_SUPPORT //
+                       *pChType = BAND_BOTH;
+                       break;
+
+               default:
+                       *pChType = BAND_24G;
+                       break;
+       }
+}
+
+static inline UCHAR FillChList(
+       IN PRTMP_ADAPTER pAd,
+       IN PCH_DESP pChDesp,
+       IN UCHAR Offset,
+       IN UCHAR increment)
+{
+       INT i, j, l;
+       UCHAR channel;
+
+       j = Offset;
+       for (i = 0; i < pChDesp->NumOfCh; i++)
+       {
+               channel = pChDesp->FirstChannel + i * increment;
+               for (l=0; l<MAX_NUM_OF_CHANNELS; l++)
+               {
+                       if (channel == pAd->TxPower[l].Channel)
+                       {
+                               pAd->ChannelList[j].Power = pAd->TxPower[l].Power;
+                               pAd->ChannelList[j].Power2 = pAd->TxPower[l].Power2;
+                               break;
+                       }
+               }
+               if (l == MAX_NUM_OF_CHANNELS)
+                       continue;
+
+               pAd->ChannelList[j].Channel = pChDesp->FirstChannel + i * increment;
+               pAd->ChannelList[j].MaxTxPwr = pChDesp->MaxTxPwr;
+               pAd->ChannelList[j].DfsReq = pChDesp->DfsReq;
+               j++;
+       }
+       pAd->ChannelListNum = j;
+
+       return j;
+}
+
+static inline VOID CreateChList(
+       IN PRTMP_ADAPTER pAd,
+       IN PCH_REGION pChRegion,
+       IN UCHAR Geography)
+{
+       INT i;
+       UCHAR offset = 0;
+       PCH_DESP pChDesp;
+       UCHAR ChType;
+       UCHAR increment;
+
+       if (pChRegion == NULL)
+               return;
+
+       ChBandCheck(pAd->CommonCfg.PhyMode, &ChType);
+
+       for (i=0; i<10; i++)
+       {
+               pChDesp = &pChRegion->ChDesp[i];
+               if (pChDesp->FirstChannel == 0)
+                       break;
+
+               if (ChType == BAND_5G)
+               {
+                       if (pChDesp->FirstChannel <= 14)
+                               continue;
+               }
+               else if (ChType == BAND_24G)
+               {
+                       if (pChDesp->FirstChannel > 14)
+                               continue;
+               }
+
+               if ((pChDesp->Geography == BOTH)
+                       || (pChDesp->Geography == Geography))
+        {
+                       if (pChDesp->FirstChannel > 14)
+                increment = 4;
+            else
+                increment = 1;
+                       offset = FillChList(pAd, pChDesp, offset, increment);
+        }
+       }
+}
+
+static inline VOID BuildChannelListEx(
+       IN PRTMP_ADAPTER pAd)
+{
+       PCH_REGION pChReg;
+
+       pChReg = GetChRegion(pAd->CommonCfg.CountryCode);
+       CreateChList(pAd, pChReg, pAd->CommonCfg.Geography);
+}
+
+static inline VOID BuildBeaconChList(
+       IN PRTMP_ADAPTER pAd,
+       OUT PUCHAR pBuf,
+       OUT     PULONG pBufLen)
+{
+       INT i;
+       ULONG TmpLen;
+       PCH_REGION pChRegion;
+       PCH_DESP pChDesp;
+       UCHAR ChType;
+
+       pChRegion = GetChRegion(pAd->CommonCfg.CountryCode);
+
+       if (pChRegion == NULL)
+               return;
+
+       ChBandCheck(pAd->CommonCfg.PhyMode, &ChType);
+       *pBufLen = 0;
+
+       for (i=0; i<10; i++)
+       {
+               pChDesp = &pChRegion->ChDesp[i];
+               if (pChDesp->FirstChannel == 0)
+                       break;
+
+               if (ChType == BAND_5G)
+               {
+                       if (pChDesp->FirstChannel <= 14)
+                               continue;
+               }
+               else if (ChType == BAND_24G)
+               {
+                       if (pChDesp->FirstChannel > 14)
+                               continue;
+               }
+
+               if ((pChDesp->Geography == BOTH)
+                       || (pChDesp->Geography == pAd->CommonCfg.Geography))
+               {
+                       MakeOutgoingFrame(pBuf + *pBufLen,              &TmpLen,
+                                                               1,                      &pChDesp->FirstChannel,
+                                                               1,                      &pChDesp->NumOfCh,
+                                                               1,                      &pChDesp->MaxTxPwr,
+                                                               END_OF_ARGS);
+                       *pBufLen += TmpLen;
+               }
+       }
+}
+
+
+#ifdef DOT11_N_SUPPORT
+static inline BOOLEAN IsValidChannel(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR channel)
+
+{
+       INT i;
+
+       for (i = 0; i < pAd->ChannelListNum; i++)
+       {
+               if (pAd->ChannelList[i].Channel == channel)
+                       break;
+       }
+
+       if (i == pAd->ChannelListNum)
+               return FALSE;
+       else
+               return TRUE;
+}
+
+
+static inline UCHAR GetExtCh(
+       IN UCHAR Channel,
+       IN UCHAR Direction)
+{
+       CHAR ExtCh;
+
+       if (Direction == EXTCHA_ABOVE)
+               ExtCh = Channel + 4;
+       else
+               ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0;
+
+       return ExtCh;
+}
+
+
+static inline VOID N_ChannelCheck(
+       IN PRTMP_ADAPTER pAd)
+{
+       //UCHAR ChannelNum = pAd->ChannelListNum;
+       UCHAR Channel = pAd->CommonCfg.Channel;
+
+       if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.RegTransmitSetting.field.BW  == BW_40))
+       {
+               if (Channel > 14)
+               {
+                       if ((Channel == 36) || (Channel == 44) || (Channel == 52) || (Channel == 60) || (Channel == 100) || (Channel == 108) ||
+                           (Channel == 116) || (Channel == 124) || (Channel == 132) || (Channel == 149) || (Channel == 157))
+                       {
+                               pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+                       }
+                       else if ((Channel == 40) || (Channel == 48) || (Channel == 56) || (Channel == 64) || (Channel == 104) || (Channel == 112) ||
+                                       (Channel == 120) || (Channel == 128) || (Channel == 136) || (Channel == 153) || (Channel == 161))
+                       {
+                               pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+                       }
+                       else
+                       {
+                               pAd->CommonCfg.RegTransmitSetting.field.BW  = BW_20;
+                       }
+               }
+               else
+               {
+                       do
+                       {
+                               UCHAR ExtCh;
+                               UCHAR Dir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA;
+                               ExtCh = GetExtCh(Channel, Dir);
+                               if (IsValidChannel(pAd, ExtCh))
+                                       break;
+
+                               Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE;
+                               ExtCh = GetExtCh(Channel, Dir);
+                               if (IsValidChannel(pAd, ExtCh))
+                               {
+                                       pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = Dir;
+                                       break;
+                               }
+                               pAd->CommonCfg.RegTransmitSetting.field.BW  = BW_20;
+                       } while(FALSE);
+
+                       if (Channel == 14)
+                       {
+                               pAd->CommonCfg.RegTransmitSetting.field.BW  = BW_20;
+                               //pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; // We didn't set the ExtCh as NONE due to it'll set in RTMPSetHT()
+                       }
+#if 0
+                       switch (pAd->CommonCfg.CountryRegion  & 0x7f)
+                       {
+                               case REGION_0_BG_BAND:  // 1 -11
+                               case REGION_1_BG_BAND:  // 1 - 13
+                               case REGION_5_BG_BAND:  // 1 - 14
+                                       if (Channel <= 4)
+                                       {
+                                               pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+                                       }
+                                       else if (Channel >= 8)
+                                       {
+                                               if ((ChannelNum - Channel) < 4)
+                                                       pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+                                       }
+                                       break;
+
+                               case REGION_2_BG_BAND:  // 10 - 11
+                               case REGION_3_BG_BAND:  // 10 - 13
+                               case REGION_4_BG_BAND:  // 14
+                                       pAd->CommonCfg.RegTransmitSetting.field.BW  = BW_20;
+                                       break;
+
+                               case REGION_6_BG_BAND:  // 3 - 9
+                                       if (Channel <= 5)
+                                               pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+                                       else if (Channel == 6)
+                                               pAd->CommonCfg.RegTransmitSetting.field.BW  = BW_20;
+                                       else if (Channel >= 7)
+                                               pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+                                       break;
+
+                               case REGION_7_BG_BAND:  // 5 - 13
+                                       if (Channel <= 8)
+                                               pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+                                       else if (Channel >= 10)
+                                               pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+                                       break;
+
+                               default:        // Error. should never happen
+                                       break;
+                       }
+#endif
+               }
+       }
+
+
+}
+
+
+static inline VOID N_SetCenCh(
+       IN PRTMP_ADAPTER pAd)
+{
+       if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
+       {
+               if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE)
+               {
+                       pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2;
+               }
+               else
+               {
+                       if (pAd->CommonCfg.Channel == 14)
+                               pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 1;
+                       else
+                               pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2;
+               }
+       }
+       else
+       {
+               pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
+       }
+}
+#endif // DOT11_N_SUPPORT //
+
+
+static inline UINT8 GetCuntryMaxTxPwr(
+       IN PRTMP_ADAPTER pAd,
+       IN UINT8 channel)
+{
+       int i;
+       for (i = 0; i < pAd->ChannelListNum; i++)
+       {
+               if (pAd->ChannelList[i].Channel == channel)
+                       break;
+       }
+
+       if (i == pAd->ChannelListNum)
+               return 0xff;
+       else
+               return pAd->ChannelList[i].MaxTxPwr;
+}
+#endif // __CHLIST_H__
+
diff --git a/drivers/staging/rt2870/common/2870_rtmp_init.c b/drivers/staging/rt2870/common/2870_rtmp_init.c
new file mode 100644 (file)
index 0000000..359c182
--- /dev/null
@@ -0,0 +1,1778 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       2870_rtmp_init.c
+
+       Abstract:
+       Miniport generic portion header file
+
+       Revision History:
+       Who         When          What
+       --------    ----------    ----------------------------------------------
+       Paul Lin    2002-08-01    created
+    John Chang  2004-08-20    RT2561/2661 use scatter-gather scheme
+    Jan Lee    2006-09-15    RT2860. Change for 802.11n , EEPROM, Led, BA, HT.
+       Sample Lin      2007-05-31    Merge RT2860 and RT2870 drivers.
+*/
+
+#include "../rt_config.h"
+
+
+static void rx_done_tasklet(unsigned long data);
+static void rt2870_hcca_dma_done_tasklet(unsigned long data);
+static void rt2870_ac3_dma_done_tasklet(unsigned long data);
+static void rt2870_ac2_dma_done_tasklet(unsigned long data);
+static void rt2870_ac1_dma_done_tasklet(unsigned long data);
+static void rt2870_ac0_dma_done_tasklet(unsigned long data);
+static void rt2870_mgmt_dma_done_tasklet(unsigned long data);
+static void rt2870_null_frame_complete_tasklet(unsigned long data);
+static void rt2870_rts_frame_complete_tasklet(unsigned long data);
+static void rt2870_pspoll_frame_complete_tasklet(unsigned long data);
+static void rt2870_dataout_complete_tasklet(unsigned long data);
+
+
+/*
+========================================================================
+Routine Description:
+    Initialize receive data structures.
+
+Arguments:
+    pAd                                        Pointer to our adapter
+
+Return Value:
+       NDIS_STATUS_SUCCESS
+       NDIS_STATUS_RESOURCES
+
+Note:
+       Initialize all receive releated private buffer, include those define
+       in RTMP_ADAPTER structure and all private data structures. The mahor
+       work is to allocate buffer for each packet and chain buffer to
+       NDIS packet descriptor.
+========================================================================
+*/
+NDIS_STATUS    NICInitRecv(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       UCHAR                           i;
+       NDIS_STATUS                     Status = NDIS_STATUS_SUCCESS;
+       POS_COOKIE                      pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitRecv\n"));
+       pObj = pObj;
+
+       //InterlockedExchange(&pAd->PendingRx, 0);
+       pAd->PendingRx = 0;
+       pAd->NextRxBulkInReadIndex      = 0;    // Next Rx Read index
+       pAd->NextRxBulkInIndex          = 0 ; //RX_RING_SIZE -1; // Rx Bulk pointer
+       pAd->NextRxBulkInPosition       = 0;
+
+       for (i = 0; i < (RX_RING_SIZE); i++)
+       {
+               PRX_CONTEXT  pRxContext = &(pAd->RxContext[i]);
+
+               //Allocate URB
+               pRxContext->pUrb = RTUSB_ALLOC_URB(0);
+               if (pRxContext->pUrb == NULL)
+               {
+                       Status = NDIS_STATUS_RESOURCES;
+                       goto out1;
+               }
+
+               // Allocate transfer buffer
+               pRxContext->TransferBuffer = RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, &pRxContext->data_dma);
+               if (pRxContext->TransferBuffer == NULL)
+               {
+                       Status = NDIS_STATUS_RESOURCES;
+                       goto out1;
+               }
+
+               NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE);
+
+               pRxContext->pAd = pAd;
+               pRxContext->pIrp = NULL;
+               pRxContext->InUse               = FALSE;
+               pRxContext->IRPPending  = FALSE;
+               pRxContext->Readable    = FALSE;
+               //pRxContext->ReorderInUse = FALSE;
+               pRxContext->bRxHandling = FALSE;
+               pRxContext->BulkInOffset = 0;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitRecv\n"));
+       return Status;
+
+out1:
+       for (i = 0; i < (RX_RING_SIZE); i++)
+       {
+               PRX_CONTEXT  pRxContext = &(pAd->RxContext[i]);
+
+               if (NULL != pRxContext->TransferBuffer)
+               {
+                       RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE,
+                                                               pRxContext->TransferBuffer, pRxContext->data_dma);
+                       pRxContext->TransferBuffer = NULL;
+               }
+
+               if (NULL != pRxContext->pUrb)
+               {
+                       RTUSB_UNLINK_URB(pRxContext->pUrb);
+                       RTUSB_FREE_URB(pRxContext->pUrb);
+                       pRxContext->pUrb = NULL;
+               }
+       }
+
+       return Status;
+}
+
+
+/*
+========================================================================
+Routine Description:
+    Initialize transmit data structures.
+
+Arguments:
+    pAd                                        Pointer to our adapter
+
+Return Value:
+       NDIS_STATUS_SUCCESS
+       NDIS_STATUS_RESOURCES
+
+Note:
+========================================================================
+*/
+NDIS_STATUS    NICInitTransmit(
+       IN      PRTMP_ADAPTER   pAd)
+{
+#define LM_USB_ALLOC(pObj, Context, TB_Type, BufferSize, Status, msg1, err1, msg2, err2)       \
+       Context->pUrb = RTUSB_ALLOC_URB(0);             \
+       if (Context->pUrb == NULL) {                    \
+               DBGPRINT(RT_DEBUG_ERROR, msg1);         \
+               Status = NDIS_STATUS_RESOURCES;         \
+               goto err1; }                                            \
+                                                                                       \
+       Context->TransferBuffer =                               \
+               (TB_Type)RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, BufferSize, &Context->data_dma);        \
+       if (Context->TransferBuffer == NULL) {  \
+               DBGPRINT(RT_DEBUG_ERROR, msg2);         \
+               Status = NDIS_STATUS_RESOURCES;         \
+               goto err2; }
+
+#define LM_URB_FREE(pObj, Context, BufferSize)                         \
+       if (NULL != Context->pUrb) {                                                    \
+               RTUSB_UNLINK_URB(Context->pUrb);                                        \
+               RTUSB_FREE_URB(Context->pUrb);                                          \
+               Context->pUrb = NULL; }                                                         \
+       if (NULL != Context->TransferBuffer) {                          \
+               RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize,       \
+                                                               Context->TransferBuffer,        \
+                                                               Context->data_dma);                     \
+               Context->TransferBuffer = NULL; }
+
+       UCHAR                   i, acidx;
+       NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
+       PTX_CONTEXT             pNullContext   = &(pAd->NullContext);
+       PTX_CONTEXT             pPsPollContext = &(pAd->PsPollContext);
+       PTX_CONTEXT             pRTSContext    = &(pAd->RTSContext);
+       PTX_CONTEXT             pMLMEContext = NULL;
+//     PHT_TX_CONTEXT  pHTTXContext = NULL;
+       POS_COOKIE              pObj = (POS_COOKIE) pAd->OS_Cookie;
+       PVOID                   RingBaseVa;
+//     RTMP_TX_RING    *pTxRing;
+       RTMP_MGMT_RING  *pMgmtRing;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTransmit\n"));
+       pObj = pObj;
+
+       // Init 4 set of Tx parameters
+       for(acidx = 0; acidx < NUM_OF_TX_RING; acidx++)
+       {
+               // Initialize all Transmit releated queues
+               InitializeQueueHeader(&pAd->TxSwQueue[acidx]);
+
+               // Next Local tx ring pointer waiting for buck out
+               pAd->NextBulkOutIndex[acidx] = acidx;
+               pAd->BulkOutPending[acidx] = FALSE; // Buck Out control flag
+               //pAd->DataBulkDoneIdx[acidx] = 0;
+       }
+
+       //pAd->NextMLMEIndex    = 0;
+       //pAd->PushMgmtIndex    = 0;
+       //pAd->PopMgmtIndex     = 0;
+       //InterlockedExchange(&pAd->MgmtQueueSize, 0);
+       //InterlockedExchange(&pAd->TxCount, 0);
+
+       //pAd->PrioRingFirstIndex       = 0;
+       //pAd->PrioRingTxCnt            = 0;
+
+       do
+       {
+               //
+               // TX_RING_SIZE, 4 ACs
+               //
+               for(acidx=0; acidx<4; acidx++)
+               {
+                       PHT_TX_CONTEXT  pHTTXContext = &(pAd->TxContext[acidx]);
+
+                       NdisZeroMemory(pHTTXContext, sizeof(HT_TX_CONTEXT));
+                       //Allocate URB
+                       LM_USB_ALLOC(pObj, pHTTXContext, PHTTX_BUFFER, sizeof(HTTX_BUFFER), Status,
+                                                       ("<-- ERROR in Alloc TX TxContext[%d] urb!! \n", acidx),
+                                                       done,
+                                                       ("<-- ERROR in Alloc TX TxContext[%d] HTTX_BUFFER !! \n", acidx),
+                                                       out1);
+
+                       NdisZeroMemory(pHTTXContext->TransferBuffer->Aggregation, 4);
+                       pHTTXContext->pAd = pAd;
+                       pHTTXContext->pIrp = NULL;
+                       pHTTXContext->IRPPending = FALSE;
+                       pHTTXContext->NextBulkOutPosition = 0;
+                       pHTTXContext->ENextBulkOutPosition = 0;
+                       pHTTXContext->CurWritePosition = 0;
+                       pHTTXContext->CurWriteRealPos = 0;
+                       pHTTXContext->BulkOutSize = 0;
+                       pHTTXContext->BulkOutPipeId = acidx;
+                       pHTTXContext->bRingEmpty = TRUE;
+                       pHTTXContext->bCopySavePad = FALSE;
+
+                       pAd->BulkOutPending[acidx] = FALSE;
+               }
+
+
+               //
+               // MGMT_RING_SIZE
+               //
+#if 0
+               for(i=0; i<MGMT_RING_SIZE; i++) // 8
+               {
+                       PTX_CONTEXT     pMLMEContext = &(pAd->MLMEContext[i]);
+
+
+                       NdisZeroMemory(pMLMEContext, sizeof(TX_CONTEXT));
+
+                       //Allocate URB
+                       LM_USB_ALLOC(pObj, pMLMEContext, PTX_BUFFER, sizeof(TX_BUFFER), Status,
+                                                       ("<-- ERROR in Alloc TX MLMEContext[%d] urb!! \n", i),
+                                                       out2,
+                                                       ("<-- ERROR in Alloc TX MLMEContext[%d] TX_BUFFER !! \n", i),
+                                                       out2);
+
+                       pMLMEContext->pAd = pAd;
+                       pMLMEContext->pIrp = NULL;
+                       pMLMEContext->InUse = FALSE;
+                       pMLMEContext->IRPPending = FALSE;
+               }
+#else
+               // Allocate MGMT ring descriptor's memory
+               pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * sizeof(TX_CONTEXT);
+               RTMPAllocateMemory(&pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize);
+               if (pAd->MgmtDescRing.AllocVa == NULL)
+               {
+                       DBGPRINT_ERR(("Failed to allocate a big buffer for MgmtDescRing!\n"));
+                       Status = NDIS_STATUS_RESOURCES;
+                       goto out1;
+               }
+               NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize);
+               RingBaseVa     = pAd->MgmtDescRing.AllocVa;
+
+               // Initialize MGMT Ring and associated buffer memory
+               pMgmtRing = &pAd->MgmtRing;
+               for (i = 0; i < MGMT_RING_SIZE; i++)
+               {
+                       // link the pre-allocated Mgmt buffer to MgmtRing.Cell
+                       pMgmtRing->Cell[i].AllocSize = sizeof(TX_CONTEXT);
+                       pMgmtRing->Cell[i].AllocVa = RingBaseVa;
+                       pMgmtRing->Cell[i].pNdisPacket = NULL;
+                       pMgmtRing->Cell[i].pNextNdisPacket = NULL;
+
+                       //Allocate URB for MLMEContext
+                       pMLMEContext = (PTX_CONTEXT) pAd->MgmtRing.Cell[i].AllocVa;
+                       pMLMEContext->pUrb = RTUSB_ALLOC_URB(0);
+                       if (pMLMEContext->pUrb == NULL)
+                       {
+                               DBGPRINT(RT_DEBUG_ERROR, ("<-- ERROR in Alloc TX MLMEContext[%d] urb!! \n", i));
+                               Status = NDIS_STATUS_RESOURCES;
+                               goto out2;
+                       }
+                       pMLMEContext->pAd = pAd;
+                       pMLMEContext->pIrp = NULL;
+                       pMLMEContext->TransferBuffer = NULL;
+                       pMLMEContext->InUse = FALSE;
+                       pMLMEContext->IRPPending = FALSE;
+                       pMLMEContext->bWaitingBulkOut = FALSE;
+                       pMLMEContext->BulkOutSize = 0;
+                       pMLMEContext->SelfIdx = i;
+
+                       // Offset to next ring descriptor address
+                       RingBaseVa = (PUCHAR) RingBaseVa + sizeof(TX_CONTEXT);
+               }
+               DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", i));
+
+               //pAd->MgmtRing.TxSwFreeIdx = (MGMT_RING_SIZE - 1);
+               pAd->MgmtRing.TxSwFreeIdx = MGMT_RING_SIZE;
+               pAd->MgmtRing.TxCpuIdx = 0;
+               pAd->MgmtRing.TxDmaIdx = 0;
+#endif
+
+               //
+               // BEACON_RING_SIZE
+               //
+               for(i=0; i<BEACON_RING_SIZE; i++) // 2
+               {
+                       PTX_CONTEXT     pBeaconContext = &(pAd->BeaconContext[i]);
+
+
+                       NdisZeroMemory(pBeaconContext, sizeof(TX_CONTEXT));
+
+                       //Allocate URB
+                       LM_USB_ALLOC(pObj, pBeaconContext, PTX_BUFFER, sizeof(TX_BUFFER), Status,
+                                                       ("<-- ERROR in Alloc TX BeaconContext[%d] urb!! \n", i),
+                                                       out2,
+                                                       ("<-- ERROR in Alloc TX BeaconContext[%d] TX_BUFFER !! \n", i),
+                                                       out3);
+
+                       pBeaconContext->pAd = pAd;
+                       pBeaconContext->pIrp = NULL;
+                       pBeaconContext->InUse = FALSE;
+                       pBeaconContext->IRPPending = FALSE;
+               }
+
+               //
+               // NullContext
+               //
+               NdisZeroMemory(pNullContext, sizeof(TX_CONTEXT));
+
+               //Allocate URB
+               LM_USB_ALLOC(pObj, pNullContext, PTX_BUFFER, sizeof(TX_BUFFER), Status,
+                                               ("<-- ERROR in Alloc TX NullContext urb!! \n"),
+                                               out3,
+                                               ("<-- ERROR in Alloc TX NullContext TX_BUFFER !! \n"),
+                                               out4);
+
+               pNullContext->pAd = pAd;
+               pNullContext->pIrp = NULL;
+               pNullContext->InUse = FALSE;
+               pNullContext->IRPPending = FALSE;
+
+               //
+               // RTSContext
+               //
+               NdisZeroMemory(pRTSContext, sizeof(TX_CONTEXT));
+
+               //Allocate URB
+               LM_USB_ALLOC(pObj, pRTSContext, PTX_BUFFER, sizeof(TX_BUFFER), Status,
+                                               ("<-- ERROR in Alloc TX RTSContext urb!! \n"),
+                                               out4,
+                                               ("<-- ERROR in Alloc TX RTSContext TX_BUFFER !! \n"),
+                                               out5);
+
+               pRTSContext->pAd = pAd;
+               pRTSContext->pIrp = NULL;
+               pRTSContext->InUse = FALSE;
+               pRTSContext->IRPPending = FALSE;
+
+               //
+               // PsPollContext
+               //
+               //NdisZeroMemory(pPsPollContext, sizeof(TX_CONTEXT));
+               //Allocate URB
+               LM_USB_ALLOC(pObj, pPsPollContext, PTX_BUFFER, sizeof(TX_BUFFER), Status,
+                                               ("<-- ERROR in Alloc TX PsPollContext urb!! \n"),
+                                               out5,
+                                               ("<-- ERROR in Alloc TX PsPollContext TX_BUFFER !! \n"),
+                                               out6);
+
+               pPsPollContext->pAd = pAd;
+               pPsPollContext->pIrp = NULL;
+               pPsPollContext->InUse = FALSE;
+               pPsPollContext->IRPPending = FALSE;
+               pPsPollContext->bAggregatible = FALSE;
+               pPsPollContext->LastOne = TRUE;
+
+       }   while (FALSE);
+
+
+done:
+       DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTransmit\n"));
+
+       return Status;
+
+       /* --------------------------- ERROR HANDLE --------------------------- */
+out6:
+       LM_URB_FREE(pObj, pPsPollContext, sizeof(TX_BUFFER));
+
+out5:
+       LM_URB_FREE(pObj, pRTSContext, sizeof(TX_BUFFER));
+
+out4:
+       LM_URB_FREE(pObj, pNullContext, sizeof(TX_BUFFER));
+
+out3:
+       for(i=0; i<BEACON_RING_SIZE; i++)
+       {
+               PTX_CONTEXT     pBeaconContext = &(pAd->BeaconContext[i]);
+               if (pBeaconContext)
+                       LM_URB_FREE(pObj, pBeaconContext, sizeof(TX_BUFFER));
+       }
+
+out2:
+       if (pAd->MgmtDescRing.AllocVa)
+       {
+               pMgmtRing = &pAd->MgmtRing;
+       for(i=0; i<MGMT_RING_SIZE; i++)
+       {
+               pMLMEContext = (PTX_CONTEXT) pAd->MgmtRing.Cell[i].AllocVa;
+               if (pMLMEContext)
+                       LM_URB_FREE(pObj, pMLMEContext, sizeof(TX_BUFFER));
+       }
+               NdisFreeMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize, 0);
+               pAd->MgmtDescRing.AllocVa = NULL;
+       }
+
+out1:
+       for (acidx = 0; acidx < 4; acidx++)
+       {
+               PHT_TX_CONTEXT pTxContext = &(pAd->TxContext[acidx]);
+               if (pTxContext)
+                       LM_URB_FREE(pObj, pTxContext, sizeof(HTTX_BUFFER));
+       }
+
+       // Here we didn't have any pre-allocated memory need to free.
+
+       return Status;
+}
+
+
+/*
+========================================================================
+Routine Description:
+    Allocate DMA memory blocks for send, receive.
+
+Arguments:
+    pAd                                        Pointer to our adapter
+
+Return Value:
+       NDIS_STATUS_SUCCESS
+       NDIS_STATUS_FAILURE
+       NDIS_STATUS_RESOURCES
+
+Note:
+========================================================================
+*/
+NDIS_STATUS    RTMPAllocTxRxRingMemory(
+       IN      PRTMP_ADAPTER   pAd)
+{
+//     COUNTER_802_11  pCounter = &pAd->WlanCounters;
+       NDIS_STATUS             Status;
+       INT                             num;
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n"));
+
+
+       do
+       {
+               // Init the CmdQ and CmdQLock
+               NdisAllocateSpinLock(&pAd->CmdQLock);
+               NdisAcquireSpinLock(&pAd->CmdQLock);
+               RTUSBInitializeCmdQ(&pAd->CmdQ);
+               NdisReleaseSpinLock(&pAd->CmdQLock);
+
+
+               NdisAllocateSpinLock(&pAd->MLMEBulkOutLock);
+               //NdisAllocateSpinLock(&pAd->MLMEWaitQueueLock);
+               NdisAllocateSpinLock(&pAd->BulkOutLock[0]);
+               NdisAllocateSpinLock(&pAd->BulkOutLock[1]);
+               NdisAllocateSpinLock(&pAd->BulkOutLock[2]);
+               NdisAllocateSpinLock(&pAd->BulkOutLock[3]);
+               NdisAllocateSpinLock(&pAd->BulkOutLock[4]);
+               NdisAllocateSpinLock(&pAd->BulkOutLock[5]);
+               NdisAllocateSpinLock(&pAd->BulkInLock);
+
+               for (num = 0; num < NUM_OF_TX_RING; num++)
+               {
+                       NdisAllocateSpinLock(&pAd->TxContextQueueLock[num]);
+               }
+
+#ifdef RALINK_ATE
+               NdisAllocateSpinLock(&pAd->GenericLock);
+#endif // RALINK_ATE //
+
+//             NdisAllocateSpinLock(&pAd->MemLock);    // Not used in RT28XX
+
+//             NdisAllocateSpinLock(&pAd->MacTabLock); // init it in UserCfgInit()
+//             NdisAllocateSpinLock(&pAd->BATabLock); // init it in BATableInit()
+
+//             for(num=0; num<MAX_LEN_OF_BA_REC_TABLE; num++)
+//             {
+//                     NdisAllocateSpinLock(&pAd->BATable.BARecEntry[num].RxReRingLock);
+//             }
+
+               //
+               // Init Mac Table
+               //
+//             MacTableInitialize(pAd);
+
+               //
+               // Init send data structures and related parameters
+               //
+               Status = NICInitTransmit(pAd);
+               if (Status != NDIS_STATUS_SUCCESS)
+                       break;
+
+               //
+               // Init receive data structures and related parameters
+               //
+               Status = NICInitRecv(pAd);
+               if (Status != NDIS_STATUS_SUCCESS)
+                       break;
+
+               pAd->PendingIoCount = 1;
+
+       } while (FALSE);
+
+       NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
+       pAd->FragFrame.pFragPacket =  RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
+
+       if (pAd->FragFrame.pFragPacket == NULL)
+       {
+               Status = NDIS_STATUS_RESOURCES;
+       }
+
+       DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status));
+       return Status;
+}
+
+
+/*
+========================================================================
+Routine Description:
+       Calls USB_InterfaceStop and frees memory allocated for the URBs
+    calls NdisMDeregisterDevice and frees the memory
+    allocated in VNetInitialize for the Adapter Object
+
+Arguments:
+       *pAd                            the raxx interface data pointer
+
+Return Value:
+       None
+
+Note:
+========================================================================
+*/
+VOID   RTMPFreeTxRxRingMemory(
+       IN      PRTMP_ADAPTER   pAd)
+{
+#define LM_URB_FREE(pObj, Context, BufferSize)                         \
+       if (NULL != Context->pUrb) {                                                    \
+               RTUSB_UNLINK_URB(Context->pUrb);                                        \
+               RTUSB_FREE_URB(Context->pUrb);                                          \
+               Context->pUrb = NULL; }                                                         \
+       if (NULL != Context->TransferBuffer) {                                  \
+               RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize,       \
+                                                               Context->TransferBuffer,        \
+                                                               Context->data_dma);                     \
+               Context->TransferBuffer = NULL; }
+
+
+       UINT                i, acidx;
+       PTX_CONTEXT                     pNullContext   = &pAd->NullContext;
+       PTX_CONTEXT                     pPsPollContext = &pAd->PsPollContext;
+       PTX_CONTEXT                     pRTSContext    = &pAd->RTSContext;
+//     PHT_TX_CONTEXT          pHTTXContext;
+       //PRTMP_REORDERBUF      pReorderBuf;
+       POS_COOKIE                      pObj = (POS_COOKIE) pAd->OS_Cookie;
+//     RTMP_TX_RING            *pTxRing;
+
+       DBGPRINT(RT_DEBUG_ERROR, ("---> RTMPFreeTxRxRingMemory\n"));
+       pObj = pObj;
+
+       // Free all resources for the RECEIVE buffer queue.
+       for(i=0; i<(RX_RING_SIZE); i++)
+       {
+               PRX_CONTEXT  pRxContext = &(pAd->RxContext[i]);
+               if (pRxContext)
+                       LM_URB_FREE(pObj, pRxContext, MAX_RXBULK_SIZE);
+       }
+
+       // Free PsPoll frame resource
+       LM_URB_FREE(pObj, pPsPollContext, sizeof(TX_BUFFER));
+
+       // Free NULL frame resource
+       LM_URB_FREE(pObj, pNullContext, sizeof(TX_BUFFER));
+
+       // Free RTS frame resource
+       LM_URB_FREE(pObj, pRTSContext, sizeof(TX_BUFFER));
+
+
+       // Free beacon frame resource
+       for(i=0; i<BEACON_RING_SIZE; i++)
+       {
+               PTX_CONTEXT     pBeaconContext = &(pAd->BeaconContext[i]);
+               if (pBeaconContext)
+                       LM_URB_FREE(pObj, pBeaconContext, sizeof(TX_BUFFER));
+       }
+
+
+       // Free mgmt frame resource
+       for(i = 0; i < MGMT_RING_SIZE; i++)
+       {
+               PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa;
+               //LM_URB_FREE(pObj, pMLMEContext, sizeof(TX_BUFFER));
+               if (NULL != pAd->MgmtRing.Cell[i].pNdisPacket)
+               {
+                       RTMPFreeNdisPacket(pAd, pAd->MgmtRing.Cell[i].pNdisPacket);
+                       pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
+                       pMLMEContext->TransferBuffer = NULL;
+               }
+
+               if (pMLMEContext)
+               {
+                       if (NULL != pMLMEContext->pUrb)
+                       {
+                               RTUSB_UNLINK_URB(pMLMEContext->pUrb);
+                               RTUSB_FREE_URB(pMLMEContext->pUrb);
+                               pMLMEContext->pUrb = NULL;
+                       }
+               }
+       }
+       if (pAd->MgmtDescRing.AllocVa)
+               NdisFreeMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize, 0);
+
+
+       // Free Tx frame resource
+       for (acidx = 0; acidx < 4; acidx++)
+               {
+               PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]);
+                       if (pHTTXContext)
+                               LM_URB_FREE(pObj, pHTTXContext, sizeof(HTTX_BUFFER));
+               }
+
+       if (pAd->FragFrame.pFragPacket)
+               RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS);
+
+       for(i=0; i<6; i++)
+       {
+               NdisFreeSpinLock(&pAd->BulkOutLock[i]);
+       }
+
+       NdisFreeSpinLock(&pAd->BulkInLock);
+       NdisFreeSpinLock(&pAd->MLMEBulkOutLock);
+
+       NdisFreeSpinLock(&pAd->CmdQLock);
+#ifdef RALINK_ATE
+       NdisFreeSpinLock(&pAd->GenericLock);
+#endif // RALINK_ATE //
+       // Clear all pending bulk-out request flags.
+       RTUSB_CLEAR_BULK_FLAG(pAd, 0xffffffff);
+
+//     NdisFreeSpinLock(&pAd->MacTabLock);
+
+//     for(i=0; i<MAX_LEN_OF_BA_REC_TABLE; i++)
+//     {
+//             NdisFreeSpinLock(&pAd->BATable.BARecEntry[i].RxReRingLock);
+//     }
+
+       DBGPRINT(RT_DEBUG_ERROR, ("<--- ReleaseAdapter\n"));
+}
+
+
+/*
+========================================================================
+Routine Description:
+    Allocate memory for adapter control block.
+
+Arguments:
+    pAd                                        Pointer to our adapter
+
+Return Value:
+       NDIS_STATUS_SUCCESS
+       NDIS_STATUS_FAILURE
+       NDIS_STATUS_RESOURCES
+
+Note:
+========================================================================
+*/
+NDIS_STATUS AdapterBlockAllocateMemory(
+       IN PVOID        handle,
+       OUT     PVOID   *ppAd)
+{
+       PUSB_DEV        usb_dev;
+       POS_COOKIE      pObj = (POS_COOKIE) handle;
+
+
+       usb_dev = pObj->pUsb_Dev;
+
+       pObj->MLMEThr_pid               = THREAD_PID_INIT_VALUE;
+       pObj->RTUSBCmdThr_pid   = THREAD_PID_INIT_VALUE;
+
+       *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER));
+
+       if (*ppAd)
+       {
+               NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER));
+               ((PRTMP_ADAPTER)*ppAd)->OS_Cookie = handle;
+               return (NDIS_STATUS_SUCCESS);
+       }
+       else
+       {
+               return (NDIS_STATUS_FAILURE);
+       }
+}
+
+
+/*
+========================================================================
+Routine Description:
+    Create kernel threads & tasklets.
+
+Arguments:
+    *net_dev                   Pointer to wireless net device interface
+
+Return Value:
+       NDIS_STATUS_SUCCESS
+       NDIS_STATUS_FAILURE
+
+Note:
+========================================================================
+*/
+NDIS_STATUS     CreateThreads(
+       IN      struct net_device *net_dev)
+{
+       PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) net_dev->priv;
+       POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+       pid_t pid_number = -1;
+
+       //init_MUTEX(&(pAd->usbdev_semaphore));
+
+       init_MUTEX_LOCKED(&(pAd->mlme_semaphore));
+       init_completion (&pAd->mlmeComplete);
+
+       init_MUTEX_LOCKED(&(pAd->RTUSBCmd_semaphore));
+       init_completion (&pAd->CmdQComplete);
+
+       init_MUTEX_LOCKED(&(pAd->RTUSBTimer_semaphore));
+       init_completion (&pAd->TimerQComplete);
+
+       // Creat MLME Thread
+       pObj->MLMEThr_pid= THREAD_PID_INIT_VALUE;
+       pid_number = kernel_thread(MlmeThread, pAd, CLONE_VM);
+       if (pid_number < 0)
+       {
+               printk (KERN_WARNING "%s: unable to start Mlme thread\n",pAd->net_dev->name);
+               return NDIS_STATUS_FAILURE;
+       }
+       pObj->MLMEThr_pid = GET_PID(pid_number);
+       // Wait for the thread to start
+       wait_for_completion(&(pAd->mlmeComplete));
+
+       // Creat Command Thread
+       pObj->RTUSBCmdThr_pid= THREAD_PID_INIT_VALUE;
+       pid_number = kernel_thread(RTUSBCmdThread, pAd, CLONE_VM);
+       if (pid_number < 0)
+       {
+               printk (KERN_WARNING "%s: unable to start RTUSBCmd thread\n",pAd->net_dev->name);
+               return NDIS_STATUS_FAILURE;
+       }
+       pObj->RTUSBCmdThr_pid = GET_PID(pid_number);
+       wait_for_completion(&(pAd->CmdQComplete));
+
+       pObj->TimerQThr_pid= THREAD_PID_INIT_VALUE;
+       pid_number = kernel_thread(TimerQThread, pAd, CLONE_VM);
+       if (pid_number < 0)
+       {
+               printk (KERN_WARNING "%s: unable to start TimerQThread\n",pAd->net_dev->name);
+               return NDIS_STATUS_FAILURE;
+       }
+       pObj->TimerQThr_pid = GET_PID(pid_number);
+       // Wait for the thread to start
+       wait_for_completion(&(pAd->TimerQComplete));
+
+       // Create receive tasklet
+       tasklet_init(&pObj->rx_done_task, rx_done_tasklet, (ULONG)pAd);
+       tasklet_init(&pObj->mgmt_dma_done_task, rt2870_mgmt_dma_done_tasklet, (unsigned long)pAd);
+       tasklet_init(&pObj->ac0_dma_done_task, rt2870_ac0_dma_done_tasklet, (unsigned long)pAd);
+       tasklet_init(&pObj->ac1_dma_done_task, rt2870_ac1_dma_done_tasklet, (unsigned long)pAd);
+       tasklet_init(&pObj->ac2_dma_done_task, rt2870_ac2_dma_done_tasklet, (unsigned long)pAd);
+       tasklet_init(&pObj->ac3_dma_done_task, rt2870_ac3_dma_done_tasklet, (unsigned long)pAd);
+       tasklet_init(&pObj->hcca_dma_done_task, rt2870_hcca_dma_done_tasklet, (unsigned long)pAd);
+       tasklet_init(&pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd);
+       tasklet_init(&pObj->null_frame_complete_task, rt2870_null_frame_complete_tasklet, (unsigned long)pAd);
+       tasklet_init(&pObj->rts_frame_complete_task, rt2870_rts_frame_complete_tasklet, (unsigned long)pAd);
+       tasklet_init(&pObj->pspoll_frame_complete_task, rt2870_pspoll_frame_complete_tasklet, (unsigned long)pAd);
+
+       return NDIS_STATUS_SUCCESS;
+}
+
+
+#ifdef CONFIG_STA_SUPPORT
+/*
+========================================================================
+Routine Description:
+       As STA's BSSID is a WC too, it uses shared key table.
+       This function write correct unicast TX key to ASIC WCID.
+       And we still make a copy in our MacTab.Content[BSSID_WCID].PairwiseKey.
+       Caller guarantee TKIP/AES always has keyidx = 0. (pairwise key)
+       Caller guarantee WEP calls this function when set Txkey,  default key index=0~3.
+
+Arguments:
+       pAd                                     Pointer to our adapter
+       pKey                                    Pointer to the where the key stored
+
+Return Value:
+       NDIS_SUCCESS                    Add key successfully
+
+Note:
+========================================================================
+*/
+VOID   RTMPAddBSSIDCipher(
+       IN      PRTMP_ADAPTER           pAd,
+       IN      UCHAR                           Aid,
+       IN      PNDIS_802_11_KEY        pKey,
+       IN  UCHAR                       CipherAlg)
+{
+       PUCHAR          pTxMic, pRxMic;
+       BOOLEAN         bKeyRSC, bAuthenticator; // indicate the receive SC set by KeyRSC value
+//     UCHAR           CipherAlg;
+       UCHAR           i;
+       ULONG           WCIDAttri;
+       USHORT          offset;
+       UCHAR           KeyIdx, IVEIV[8];
+       UINT32          Value;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddBSSIDCipher==> Aid = %d\n",Aid));
+
+       // Bit 29 of Add-key KeyRSC
+       bKeyRSC            = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE;
+
+       // Bit 28 of Add-key Authenticator
+       bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE;
+       KeyIdx = (UCHAR)pKey->KeyIndex&0xff;
+
+       if (KeyIdx > 4)
+               return;
+
+
+       if (pAd->MacTab.Content[Aid].PairwiseKey.CipherAlg == CIPHER_TKIP)
+       {       if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+               {
+                       // for WPA-None Tx, Rx MIC is the same
+                       pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
+                       pRxMic = pTxMic;
+               }
+               else if (bAuthenticator == TRUE)
+               {
+                       pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
+                       pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 24;
+               }
+               else
+               {
+                       pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
+                       pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 24;
+               }
+
+               offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE) + 0x10;
+               for (i=0; i<8; )
+               {
+                       Value = *(pTxMic+i);
+                       Value += (*(pTxMic+i+1)<<8);
+                       Value += (*(pTxMic+i+2)<<16);
+                       Value += (*(pTxMic+i+3)<<24);
+                       RTUSBWriteMACRegister(pAd, offset+i, Value);
+                       i+=4;
+               }
+
+               offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE) + 0x18;
+               for (i=0; i<8; )
+               {
+                       Value = *(pRxMic+i);
+                       Value += (*(pRxMic+i+1)<<8);
+                       Value += (*(pRxMic+i+2)<<16);
+                       Value += (*(pRxMic+i+3)<<24);
+                       RTUSBWriteMACRegister(pAd, offset+i, Value);
+                       i+=4;
+               }
+
+               // Only Key lenth equal to TKIP key have these
+               NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxMic, pRxMic, 8);
+               NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.TxMic, pTxMic, 8);
+
+               DBGPRINT(RT_DEBUG_TRACE,
+                               ("      TxMIC  = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n",
+                               pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],
+                               pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
+               DBGPRINT(RT_DEBUG_TRACE,
+                               ("      RxMIC  = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n",
+                               pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],
+                               pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
+       }
+
+       // 2. Record Security Key.
+       pAd->MacTab.Content[BSSID_WCID].PairwiseKey.KeyLen= (UCHAR)pKey->KeyLength;
+       NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength);
+
+       // 3. Check RxTsc. And used to init to ASIC IV.
+       if (bKeyRSC == TRUE)
+               NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxTsc, &pKey->KeyRSC, 6);
+       else
+               NdisZeroMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxTsc, 6);
+
+       // 4. Init TxTsc to one based on WiFi WPA specs
+       pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[0] = 1;
+       pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[1] = 0;
+       pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[2] = 0;
+       pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[3] = 0;
+       pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[4] = 0;
+       pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[5] = 0;
+
+       CipherAlg = pAd->MacTab.Content[Aid].PairwiseKey.CipherAlg;
+
+       offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE);
+       RTUSBMultiWrite(pAd, (USHORT) offset, pKey->KeyMaterial,
+                               ((pKey->KeyLength == LEN_TKIP_KEY) ? 16 : (USHORT)pKey->KeyLength));
+
+       offset = SHARED_KEY_TABLE_BASE + (KeyIdx * HW_KEY_ENTRY_SIZE);
+       RTUSBMultiWrite(pAd, (USHORT) offset, pKey->KeyMaterial, (USHORT)pKey->KeyLength);
+
+       offset = PAIRWISE_IVEIV_TABLE_BASE + (Aid * HW_IVEIV_ENTRY_SIZE);
+       NdisZeroMemory(IVEIV, 8);
+
+       // IV/EIV
+       if ((CipherAlg == CIPHER_TKIP) ||
+               (CipherAlg == CIPHER_TKIP_NO_MIC) ||
+               (CipherAlg == CIPHER_AES))
+       {
+               IVEIV[3] = 0x20; // Eiv bit on. keyid always 0 for pairwise key
+       }
+       // default key idx needs to set.
+       // in TKIP/AES KeyIdx = 0 , WEP KeyIdx is default tx key.
+       else
+       {
+               IVEIV[3] |= (KeyIdx<< 6);
+       }
+       RTUSBMultiWrite(pAd, (USHORT) offset, IVEIV, 8);
+
+       // WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:1=PAIRWISE KEY, BSSIdx is 0
+       if ((CipherAlg == CIPHER_TKIP) ||
+               (CipherAlg == CIPHER_TKIP_NO_MIC) ||
+               (CipherAlg == CIPHER_AES))
+       {
+               WCIDAttri = (CipherAlg<<1)|SHAREDKEYTABLE;
+       }
+       else
+               WCIDAttri = (CipherAlg<<1)|SHAREDKEYTABLE;
+
+       offset = MAC_WCID_ATTRIBUTE_BASE + (Aid* HW_WCID_ATTRI_SIZE);
+       RTUSBWriteMACRegister(pAd, offset, WCIDAttri);
+       RTUSBReadMACRegister(pAd, offset, &Value);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("BSSID_WCID : offset = %x, WCIDAttri = %lx\n",
+                       offset, WCIDAttri));
+
+       // pAddr
+       // Add Bssid mac address at linkup. not here.  check!
+       /*offset = MAC_WCID_BASE + (BSSID_WCID * HW_WCID_ENTRY_SIZE);
+       *for (i=0; i<MAC_ADDR_LEN; i++)
+       {
+               RTMP_IO_WRITE8(pAd, offset+i, pKey->BSSID[i]);
+       }
+       */
+
+       DBGPRINT(RT_DEBUG_ERROR, ("AddBSSIDasWCIDEntry: Alg=%s, KeyLength = %d\n",
+                       CipherName[CipherAlg], pKey->KeyLength));
+       DBGPRINT(RT_DEBUG_TRACE, ("Key [idx=%x] [KeyLen = %d]\n",
+                       pKey->KeyIndex, pKey->KeyLength));
+       for(i=0; i<pKey->KeyLength; i++)
+               DBGPRINT_RAW(RT_DEBUG_TRACE,(" %x:", pKey->KeyMaterial[i]));
+       DBGPRINT(RT_DEBUG_TRACE,("       \n"));
+}
+#endif // CONFIG_STA_SUPPORT //
+
+/*
+========================================================================
+Routine Description:
+    Get a received packet.
+
+Arguments:
+       pAd                                     device control block
+       pSaveRxD                        receive descriptor information
+       *pbReschedule           need reschedule flag
+       *pRxPending                     pending received packet flag
+
+Return Value:
+    the recieved packet
+
+Note:
+========================================================================
+*/
+#define RT2870_RXDMALEN_FIELD_SIZE                     4
+PNDIS_PACKET GetPacketFromRxRing(
+       IN              PRTMP_ADAPTER           pAd,
+       OUT             PRT28XX_RXD_STRUC       pSaveRxD,
+       OUT             BOOLEAN                         *pbReschedule,
+       IN OUT  UINT32                          *pRxPending)
+{
+       PRX_CONTEXT             pRxContext;
+       PNDIS_PACKET    pSkb;
+       PUCHAR                  pData;
+       ULONG                   ThisFrameLen;
+       ULONG                   RxBufferLength;
+       PRXWI_STRUC             pRxWI;
+
+       pRxContext = &pAd->RxContext[pAd->NextRxBulkInReadIndex];
+       if ((pRxContext->Readable == FALSE) || (pRxContext->InUse == TRUE))
+               return NULL;
+
+       RxBufferLength = pRxContext->BulkInOffset - pAd->ReadPosition;
+       if (RxBufferLength < (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXWI_STRUC) + sizeof(RXINFO_STRUC)))
+       {
+               goto label_null;
+       }
+
+       pData = &pRxContext->TransferBuffer[pAd->ReadPosition]; /* 4KB */
+       // The RXDMA field is 4 bytes, now just use the first 2 bytes. The Length including the (RXWI + MSDU + Padding)
+       ThisFrameLen = *pData + (*(pData+1)<<8);
+    if (ThisFrameLen == 0)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("BIRIdx(%d): RXDMALen is zero.[%ld], BulkInBufLen = %ld)\n",
+                                                               pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset));
+               goto label_null;
+       }
+       if ((ThisFrameLen&0x3) != 0)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("BIRIdx(%d): RXDMALen not multiple of 4.[%ld], BulkInBufLen = %ld)\n",
+                                                               pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset));
+               goto label_null;
+       }
+
+       if ((ThisFrameLen + 8)> RxBufferLength) // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC))
+       {
+               DBGPRINT(RT_DEBUG_TRACE,("BIRIdx(%d):FrameLen(0x%lx) outranges. BulkInLen=0x%lx, remaining RxBufLen=0x%lx, ReadPos=0x%lx\n",
+                                               pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset, RxBufferLength, pAd->ReadPosition));
+
+               // error frame. finish this loop
+               goto label_null;
+       }
+
+       // skip USB frame length field
+       pData += RT2870_RXDMALEN_FIELD_SIZE;
+       pRxWI = (PRXWI_STRUC)pData;
+#ifdef RT_BIG_ENDIAN
+       RTMPWIEndianChange(pData, TYPE_RXWI);
+#endif // RT_BIG_ENDIAN //
+       if (pRxWI->MPDUtotalByteCount > ThisFrameLen)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s():pRxWIMPDUtotalByteCount(%d) large than RxDMALen(%ld)\n",
+                                                                       __FUNCTION__, pRxWI->MPDUtotalByteCount, ThisFrameLen));
+               goto label_null;
+       }
+#ifdef RT_BIG_ENDIAN
+       RTMPWIEndianChange(pData, TYPE_RXWI);
+#endif // RT_BIG_ENDIAN //
+
+       // allocate a rx packet
+       pSkb = dev_alloc_skb(ThisFrameLen);
+       if (pSkb == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n", __FUNCTION__));
+               goto label_null;
+       }
+
+       // copy the rx packet
+       memcpy(skb_put(pSkb, ThisFrameLen), pData, ThisFrameLen);
+       RTPKT_TO_OSPKT(pSkb)->dev = get_netdev_from_bssid(pAd, BSS0);
+       RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pSkb), PKTSRC_NDIS);
+
+       // copy RxD
+       *pSaveRxD = *(PRXINFO_STRUC)(pData + ThisFrameLen);
+#ifdef RT_BIG_ENDIAN
+       RTMPDescriptorEndianChange((PUCHAR)pSaveRxD, TYPE_RXINFO);
+#endif // RT_BIG_ENDIAN //
+
+       // update next packet read position.
+       pAd->ReadPosition += (ThisFrameLen + RT2870_RXDMALEN_FIELD_SIZE + RXINFO_SIZE); // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC))
+
+       return pSkb;
+
+label_null:
+
+       return NULL;
+}
+
+
+/*
+========================================================================
+Routine Description:
+    Handle received packets.
+
+Arguments:
+       data                            - URB information pointer
+
+Return Value:
+    None
+
+Note:
+========================================================================
+*/
+static void rx_done_tasklet(unsigned long data)
+{
+       purbb_t                         pUrb;
+       PRX_CONTEXT                     pRxContext;
+       PRTMP_ADAPTER           pAd;
+       NTSTATUS                        Status;
+       unsigned int            IrqFlags;
+
+       pUrb            = (purbb_t)data;
+       pRxContext      = (PRX_CONTEXT)pUrb->context;
+       pAd             = pRxContext->pAd;
+       Status = pUrb->status;
+
+
+       RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+       pRxContext->InUse = FALSE;
+       pRxContext->IRPPending = FALSE;
+       pRxContext->BulkInOffset += pUrb->actual_length;
+       //NdisInterlockedDecrement(&pAd->PendingRx);
+       pAd->PendingRx--;
+
+       if (Status == USB_ST_NOERROR)
+       {
+               pAd->BulkInComplete++;
+               pAd->NextRxBulkInPosition = 0;
+               if (pRxContext->BulkInOffset)   // As jan's comment, it may bulk-in success but size is zero.
+               {
+                       pRxContext->Readable = TRUE;
+                       INC_RING_INDEX(pAd->NextRxBulkInIndex, RX_RING_SIZE);
+               }
+               RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+       }
+       else     // STATUS_OTHER
+       {
+               pAd->BulkInCompleteFail++;
+               // Still read this packet although it may comtain wrong bytes.
+               pRxContext->Readable = FALSE;
+               RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+               // Parsing all packets. because after reset, the index will reset to all zero.
+               if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                                       fRTMP_ADAPTER_BULKIN_RESET |
+                                                                       fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                                       fRTMP_ADAPTER_NIC_NOT_EXIST))))
+               {
+
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk In Failed. Status=%d, BIIdx=0x%x, BIRIdx=0x%x, actual_length= 0x%x\n",
+                                                       Status, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pRxContext->pUrb->actual_length));
+
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0);
+               }
+       }
+
+       ASSERT((pRxContext->InUse == pRxContext->IRPPending));
+
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+    {
+               // If the driver is in ATE mode and Rx frame is set into here.
+               if (pAd->ContinBulkIn == TRUE)
+               {
+                       RTUSBBulkReceive(pAd);
+               }
+       }
+       else
+#endif // RALINK_ATE //
+       RTUSBBulkReceive(pAd);
+
+       return;
+
+}
+
+
+static void rt2870_mgmt_dma_done_tasklet(unsigned long data)
+{
+       PRTMP_ADAPTER   pAd;
+       PTX_CONTEXT             pMLMEContext;
+       int                             index;
+       PNDIS_PACKET    pPacket;
+       purbb_t                 pUrb;
+       NTSTATUS                Status;
+       unsigned long   IrqFlags;
+
+
+       pUrb                    = (purbb_t)data;
+       pMLMEContext    = (PTX_CONTEXT)pUrb->context;
+       pAd                     = pMLMEContext->pAd;
+       Status                  = pUrb->status;
+       index                   = pMLMEContext->SelfIdx;
+
+       ASSERT((pAd->MgmtRing.TxDmaIdx == index));
+
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+
+
+       if (Status != USB_ST_NOERROR)
+       {
+               //Bulk-Out fail status handle
+               if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out MLME Failed, Status=%d!\n", Status));
+                       // TODO: How to handle about the MLMEBulkOut failed issue. Need to resend the mgmt pkt?
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG);
+               }
+       }
+
+       pAd->BulkOutPending[MGMTPIPEIDX] = FALSE;
+       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+
+       RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags);
+       // Reset MLME context flags
+       pMLMEContext->IRPPending = FALSE;
+       pMLMEContext->InUse = FALSE;
+       pMLMEContext->bWaitingBulkOut = FALSE;
+       pMLMEContext->BulkOutSize = 0;
+
+       pPacket = pAd->MgmtRing.Cell[index].pNdisPacket;
+       pAd->MgmtRing.Cell[index].pNdisPacket = NULL;
+
+       // Increase MgmtRing Index
+       INC_RING_INDEX(pAd->MgmtRing.TxDmaIdx, MGMT_RING_SIZE);
+       pAd->MgmtRing.TxSwFreeIdx++;
+       RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags);
+
+       // No-matter success or fail, we free the mgmt packet.
+       if (pPacket)
+               RTMPFreeNdisPacket(pAd, pPacket);
+
+       if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_NIC_NOT_EXIST))))
+       {
+               // do nothing and return directly.
+       }
+       else
+       {
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET) &&
+                       ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG))
+               {       // For Mgmt Bulk-Out failed, ignore it now.
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+               else
+               {
+
+                       // Always call Bulk routine, even reset bulk.
+                       // The protectioon of rest bulk should be in BulkOut routine
+                       if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */)
+                       {
+                               RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
+                       }
+                               RTUSBKickBulkOut(pAd);
+                       }
+               }
+
+}
+
+
+static void rt2870_hcca_dma_done_tasklet(unsigned long data)
+{
+       PRTMP_ADAPTER           pAd;
+       PHT_TX_CONTEXT          pHTTXContext;
+       UCHAR                           BulkOutPipeId = 4;
+       purbb_t                         pUrb;
+
+
+       DBGPRINT_RAW(RT_DEBUG_ERROR, ("--->hcca_dma_done_tasklet\n"));
+
+
+       pUrb                    = (purbb_t)data;
+       pHTTXContext    = (PHT_TX_CONTEXT)pUrb->context;
+       pAd                             = pHTTXContext->pAd;
+
+       rt2870_dataout_complete_tasklet((unsigned long)pUrb);
+
+       if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_NIC_NOT_EXIST))))
+       {
+               // do nothing and return directly.
+       }
+       else
+       {
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))
+               {
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+               else
+               {       pHTTXContext = &pAd->TxContext[BulkOutPipeId];
+                       if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) &&
+                               /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */
+                               (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) &&
+                               (pHTTXContext->bCurWriting == FALSE))
+                       {
+                               RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS);
+                       }
+
+                       RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL);
+                       RTUSBKickBulkOut(pAd);
+               }
+       }
+
+       DBGPRINT_RAW(RT_DEBUG_ERROR, ("<---hcca_dma_done_tasklet\n"));
+
+               return;
+}
+
+
+static void rt2870_ac3_dma_done_tasklet(unsigned long data)
+{
+       PRTMP_ADAPTER           pAd;
+       PHT_TX_CONTEXT          pHTTXContext;
+       UCHAR                           BulkOutPipeId = 3;
+       purbb_t                         pUrb;
+
+
+       pUrb                    = (purbb_t)data;
+       pHTTXContext    = (PHT_TX_CONTEXT)pUrb->context;
+       pAd                             = pHTTXContext->pAd;
+
+       rt2870_dataout_complete_tasklet((unsigned long)pUrb);
+
+       if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_NIC_NOT_EXIST))))
+       {
+               // do nothing and return directly.
+       }
+       else
+       {
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))
+               {
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+               else
+               {       pHTTXContext = &pAd->TxContext[BulkOutPipeId];
+                       if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) &&
+                               /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */
+                               (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) &&
+                               (pHTTXContext->bCurWriting == FALSE))
+                       {
+                               RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS);
+                       }
+
+                       RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<3);
+                       RTUSBKickBulkOut(pAd);
+               }
+       }
+
+
+               return;
+}
+
+
+static void rt2870_ac2_dma_done_tasklet(unsigned long data)
+{
+       PRTMP_ADAPTER           pAd;
+       PHT_TX_CONTEXT          pHTTXContext;
+       UCHAR                           BulkOutPipeId = 2;
+       purbb_t                         pUrb;
+
+
+       pUrb                    = (purbb_t)data;
+       pHTTXContext    = (PHT_TX_CONTEXT)pUrb->context;
+       pAd                             = pHTTXContext->pAd;
+
+       rt2870_dataout_complete_tasklet((unsigned long)pUrb);
+
+       if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_NIC_NOT_EXIST))))
+       {
+               // do nothing and return directly.
+       }
+       else
+       {
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))
+               {
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+               else
+               {       pHTTXContext = &pAd->TxContext[BulkOutPipeId];
+                       if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) &&
+                               /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */
+                               (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) &&
+                               (pHTTXContext->bCurWriting == FALSE))
+                       {
+                               RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS);
+                       }
+
+                       RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<2);
+                       RTUSBKickBulkOut(pAd);
+               }
+       }
+
+               return;
+}
+
+
+static void rt2870_ac1_dma_done_tasklet(unsigned long data)
+{
+       PRTMP_ADAPTER           pAd;
+       PHT_TX_CONTEXT          pHTTXContext;
+       UCHAR                           BulkOutPipeId = 1;
+       purbb_t                         pUrb;
+
+
+       pUrb                    = (purbb_t)data;
+       pHTTXContext    = (PHT_TX_CONTEXT)pUrb->context;
+       pAd                             = pHTTXContext->pAd;
+
+       rt2870_dataout_complete_tasklet((unsigned long)pUrb);
+
+       if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_NIC_NOT_EXIST))))
+       {
+               // do nothing and return directly.
+       }
+       else
+       {
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))
+               {
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+               else
+               {       pHTTXContext = &pAd->TxContext[BulkOutPipeId];
+                       if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) &&
+                               /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */
+                               (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) &&
+                               (pHTTXContext->bCurWriting == FALSE))
+                       {
+                               RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS);
+                       }
+
+                       RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<1);
+                       RTUSBKickBulkOut(pAd);
+               }
+       }
+
+
+       return;
+}
+
+
+static void rt2870_ac0_dma_done_tasklet(unsigned long data)
+{
+       PRTMP_ADAPTER           pAd;
+       PHT_TX_CONTEXT          pHTTXContext;
+       UCHAR                           BulkOutPipeId = 0;
+       purbb_t                         pUrb;
+
+
+       pUrb                    = (purbb_t)data;
+       pHTTXContext    = (PHT_TX_CONTEXT)pUrb->context;
+       pAd                             = pHTTXContext->pAd;
+
+       rt2870_dataout_complete_tasklet((unsigned long)pUrb);
+
+       if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_NIC_NOT_EXIST))))
+       {
+               // do nothing and return directly.
+       }
+       else
+       {
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))
+               {
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+               else
+               {       pHTTXContext = &pAd->TxContext[BulkOutPipeId];
+                       if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) &&
+                               /*  ((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */
+                               (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) &&
+                               (pHTTXContext->bCurWriting == FALSE))
+                       {
+                               RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS);
+                       }
+
+                       RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL);
+                       RTUSBKickBulkOut(pAd);
+               }
+       }
+
+
+       return;
+
+}
+
+
+static void rt2870_null_frame_complete_tasklet(unsigned long data)
+{
+       PRTMP_ADAPTER   pAd;
+       PTX_CONTEXT             pNullContext;
+       purbb_t                 pUrb;
+       NTSTATUS                Status;
+       unsigned long   irqFlag;
+
+
+       pUrb                    = (purbb_t)data;
+       pNullContext    = (PTX_CONTEXT)pUrb->context;
+       pAd                     = pNullContext->pAd;
+       Status                  = pUrb->status;
+
+       // Reset Null frame context flags
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag);
+       pNullContext->IRPPending        = FALSE;
+       pNullContext->InUse             = FALSE;
+       pAd->BulkOutPending[0] = FALSE;
+       pAd->watchDogTxPendingCnt[0] = 0;
+
+       if (Status == USB_ST_NOERROR)
+       {
+               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag);
+
+               RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+       }
+       else    // STATUS_OTHER
+       {
+               if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out Null Frame Failed, ReasonCode=%d!\n", Status));
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG);
+                       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag);
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+               else
+               {
+                       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag);
+               }
+       }
+
+       // Always call Bulk routine, even reset bulk.
+       // The protectioon of rest bulk should be in BulkOut routine
+       RTUSBKickBulkOut(pAd);
+
+}
+
+
+static void rt2870_rts_frame_complete_tasklet(unsigned long data)
+{
+       PRTMP_ADAPTER   pAd;
+       PTX_CONTEXT             pRTSContext;
+       purbb_t                 pUrb;
+       NTSTATUS                Status;
+       unsigned long   irqFlag;
+
+
+       pUrb            = (purbb_t)data;
+       pRTSContext     = (PTX_CONTEXT)pUrb->context;
+       pAd                     = pRTSContext->pAd;
+       Status          = pUrb->status;
+
+       // Reset RTS frame context flags
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag);
+       pRTSContext->IRPPending = FALSE;
+       pRTSContext->InUse              = FALSE;
+
+       if (Status == USB_ST_NOERROR)
+       {
+               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag);
+               RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+       }
+       else    // STATUS_OTHER
+       {
+               if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out RTS Frame Failed\n"));
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG);
+                       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag);
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+               else
+               {
+                       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag);
+               }
+       }
+
+       RTMP_SEM_LOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]);
+       pAd->BulkOutPending[pRTSContext->BulkOutPipeId] = FALSE;
+       RTMP_SEM_UNLOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]);
+
+       // Always call Bulk routine, even reset bulk.
+       // The protectioon of rest bulk should be in BulkOut routine
+       RTUSBKickBulkOut(pAd);
+
+}
+
+
+static void rt2870_pspoll_frame_complete_tasklet(unsigned long data)
+{
+       PRTMP_ADAPTER   pAd;
+       PTX_CONTEXT             pPsPollContext;
+       purbb_t                 pUrb;
+       NTSTATUS                Status;
+
+
+       pUrb                    = (purbb_t)data;
+       pPsPollContext  = (PTX_CONTEXT)pUrb->context;
+       pAd                             = pPsPollContext->pAd;
+       Status                  = pUrb->status;
+
+       // Reset PsPoll context flags
+       pPsPollContext->IRPPending      = FALSE;
+       pPsPollContext->InUse           = FALSE;
+       pAd->watchDogTxPendingCnt[0] = 0;
+
+       if (Status == USB_ST_NOERROR)
+       {
+               RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+       }
+       else // STATUS_OTHER
+       {
+               if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out PSPoll Failed\n"));
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG);
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+       }
+
+       RTMP_SEM_LOCK(&pAd->BulkOutLock[0]);
+       pAd->BulkOutPending[0] = FALSE;
+       RTMP_SEM_UNLOCK(&pAd->BulkOutLock[0]);
+
+       // Always call Bulk routine, even reset bulk.
+       // The protectioon of rest bulk should be in BulkOut routine
+       RTUSBKickBulkOut(pAd);
+
+}
+
+
+static void rt2870_dataout_complete_tasklet(unsigned long data)
+{
+       PRTMP_ADAPTER           pAd;
+       purbb_t                         pUrb;
+       POS_COOKIE                      pObj;
+       PHT_TX_CONTEXT          pHTTXContext;
+       UCHAR                           BulkOutPipeId;
+       NTSTATUS                        Status;
+       unsigned long           IrqFlags;
+
+
+       pUrb                    = (purbb_t)data;
+       pHTTXContext    = (PHT_TX_CONTEXT)pUrb->context;
+       pAd                             = pHTTXContext->pAd;
+       pObj                    = (POS_COOKIE) pAd->OS_Cookie;
+       Status                  = pUrb->status;
+
+       // Store BulkOut PipeId
+       BulkOutPipeId = pHTTXContext->BulkOutPipeId;
+       pAd->BulkOutDataOneSecCount++;
+
+       //DBGPRINT(RT_DEBUG_LOUD, ("Done-B(%d):I=0x%lx, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", BulkOutPipeId, in_interrupt(), pHTTXContext->CurWritePosition,
+       //              pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad));
+
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+       pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+       pHTTXContext->IRPPending = FALSE;
+       pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0;
+
+       if (Status == USB_ST_NOERROR)
+       {
+               pAd->BulkOutComplete++;
+
+               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+
+               pAd->Counters8023.GoodTransmits++;
+               //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+               FREE_HTTX_RING(pAd, BulkOutPipeId, pHTTXContext);
+               //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+
+
+       }
+       else    // STATUS_OTHER
+       {
+               PUCHAR  pBuf;
+
+               pAd->BulkOutCompleteOther++;
+
+               pBuf = &pHTTXContext->TransferBuffer->field.WirelessPacket[pHTTXContext->NextBulkOutPosition];
+
+               if (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                                       fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                                       fRTMP_ADAPTER_NIC_NOT_EXIST |
+                                                                       fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       pAd->bulkResetPipeid = BulkOutPipeId;
+                       pAd->bulkResetReq[BulkOutPipeId] = pAd->BulkOutReq;
+               }
+               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkOutDataPacket failed: ReasonCode=%d!\n", Status));
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>BulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther));
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>BulkOut Header:%x %x %x %x %x %x %x %x\n", pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5], pBuf[6], pBuf[7]));
+               //DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOutCompleteCancel=0x%x, BulkOutCompleteOther=0x%x\n", pAd->BulkOutCompleteCancel, pAd->BulkOutCompleteOther));
+
+       }
+
+       //
+       // bInUse = TRUE, means some process are filling TX data, after that must turn on bWaitingBulkOut
+       // bWaitingBulkOut = TRUE, means the TX data are waiting for bulk out.
+       //
+       //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+       if ((pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition) &&
+               (pHTTXContext->ENextBulkOutPosition != (pHTTXContext->CurWritePosition+8)) &&
+               !RTUSB_TEST_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId)))
+       {
+               // Indicate There is data avaliable
+               RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+       }
+       //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+
+       // Always call Bulk routine, even reset bulk.
+       // The protection of rest bulk should be in BulkOut routine
+       RTUSBKickBulkOut(pAd);
+}
+
+/* End of 2870_rtmp_init.c */
diff --git a/drivers/staging/rt2870/common/action.c b/drivers/staging/rt2870/common/action.c
new file mode 100644 (file)
index 0000000..3a48a7f
--- /dev/null
@@ -0,0 +1,1046 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+       action.c
+
+    Abstract:
+    Handle association related requests either from WSTA or from local MLME
+
+    Revision History:
+    Who         When          What
+    --------    ----------    ----------------------------------------------
+       Jan Lee         2006            created for rt2860
+ */
+
+#include "../rt_config.h"
+#include "action.h"
+
+
+static VOID ReservedAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+/*
+    ==========================================================================
+    Description:
+        association state machine init, including state transition and timer init
+    Parameters:
+        S - pointer to the association state machine
+    Note:
+        The state machine looks like the following
+
+                                    ASSOC_IDLE
+        MT2_MLME_DISASSOC_REQ    mlme_disassoc_req_action
+        MT2_PEER_DISASSOC_REQ    peer_disassoc_action
+        MT2_PEER_ASSOC_REQ       drop
+        MT2_PEER_REASSOC_REQ     drop
+        MT2_CLS3ERR              cls3err_action
+    ==========================================================================
+ */
+VOID ActionStateMachineInit(
+    IN PRTMP_ADAPTER   pAd,
+    IN  STATE_MACHINE *S,
+    OUT STATE_MACHINE_FUNC Trans[])
+{
+       StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE);
+
+       StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction);
+       StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction);
+
+       StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction);
+#ifdef QOS_DLS_SUPPORT
+               StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)PeerDLSAction);
+#endif // QOS_DLS_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+       StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction);
+       StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction);
+       StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction);
+       StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction);
+       StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction);
+#endif // DOT11_N_SUPPORT //
+
+       StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction);
+       StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction);
+
+       StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction);
+       StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction);
+       StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction);
+}
+
+#ifdef DOT11_N_SUPPORT
+VOID MlmeADDBAAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+
+{
+       MLME_ADDBA_REQ_STRUCT *pInfo;
+       UCHAR           Addr[6];
+       PUCHAR         pOutBuffer = NULL;
+       NDIS_STATUS     NStatus;
+       ULONG           Idx;
+       FRAME_ADDBA_REQ  Frame;
+       ULONG           FrameLen;
+       BA_ORI_ENTRY                    *pBAEntry = NULL;
+
+       pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg;
+       NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ));
+
+       if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr))
+       {
+               NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+               if(NStatus != NDIS_STATUS_SUCCESS)
+               {
+                       DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n"));
+                       return;
+               }
+               // 1. find entry
+               Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
+               if (Idx == 0)
+               {
+                       MlmeFreeMemory(pAd, pOutBuffer);
+                       DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n"));
+                       return;
+               }
+               else
+               {
+                       pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+               }
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       if (ADHOC_ON(pAd))
+                               ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+                       else
+#ifdef QOS_DLS_SUPPORT
+                       if (pAd->MacTab.Content[pInfo->Wcid].ValidAsDls)
+                               ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+                       else
+#endif // QOS_DLS_SUPPORT //
+                               ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pInfo->pAddr);
+
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+               Frame.Category = CATEGORY_BA;
+               Frame.Action = ADDBA_REQ;
+               Frame.BaParm.AMSDUSupported = 0;
+               Frame.BaParm.BAPolicy = IMMED_BA;
+               Frame.BaParm.TID = pInfo->TID;
+               Frame.BaParm.BufSize = pInfo->BaBufSize;
+               Frame.Token = pInfo->Token;
+               Frame.TimeOutValue = pInfo->TimeOutValue;
+               Frame.BaStartSeq.field.FragNum = 0;
+               Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID];
+
+               *(USHORT *)(&Frame.BaParm) = cpu2le16(*(USHORT *)(&Frame.BaParm));
+               Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue);
+               Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word);
+
+               MakeOutgoingFrame(pOutBuffer,              &FrameLen,
+                             sizeof(FRAME_ADDBA_REQ), &Frame,
+                             END_OF_ARGS);
+               MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+               MlmeFreeMemory(pAd, pOutBuffer);
+
+               DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x,  FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize));
+    }
+}
+
+/*
+    ==========================================================================
+    Description:
+        send DELBA and delete BaEntry if any
+    Parametrs:
+        Elem - MLME message MLME_DELBA_REQ_STRUCT
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID MlmeDELBAAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+       MLME_DELBA_REQ_STRUCT *pInfo;
+       PUCHAR         pOutBuffer = NULL;
+       PUCHAR             pOutBuffer2 = NULL;
+       NDIS_STATUS     NStatus;
+       ULONG           Idx;
+       FRAME_DELBA_REQ  Frame;
+       ULONG           FrameLen;
+       FRAME_BAR       FrameBar;
+
+       pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg;
+       // must send back DELBA
+       NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ));
+       DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator));
+
+       if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen))
+       {
+               NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+               if(NStatus != NDIS_STATUS_SUCCESS)
+               {
+                       DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n"));
+                       return;
+               }
+
+               NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2);  //Get an unused nonpaged memory
+               if(NStatus != NDIS_STATUS_SUCCESS)
+               {
+                       MlmeFreeMemory(pAd, pOutBuffer);
+                       DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n"));
+                       return;
+               }
+
+               // SEND BAR (Send BAR to refresh peer reordering buffer.)
+               Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress);
+#endif // CONFIG_STA_SUPPORT //
+
+               FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL funciton.
+               FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; // make sure sequence not clear in DEL funciton.
+               FrameBar.BarControl.TID = pInfo->TID; // make sure sequence not clear in DEL funciton.
+               FrameBar.BarControl.ACKPolicy = IMMED_BA; // make sure sequence not clear in DEL funciton.
+               FrameBar.BarControl.Compressed = 1; // make sure sequence not clear in DEL funciton.
+               FrameBar.BarControl.MTID = 0; // make sure sequence not clear in DEL funciton.
+
+               MakeOutgoingFrame(pOutBuffer2,                          &FrameLen,
+                                         sizeof(FRAME_BAR),      &FrameBar,
+                                         END_OF_ARGS);
+               MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
+               MlmeFreeMemory(pAd, pOutBuffer2);
+               DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n"));
+
+               // SEND DELBA FRAME
+               FrameLen = 0;
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       if (ADHOC_ON(pAd))
+                               ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+                       else
+#ifdef QOS_DLS_SUPPORT
+                       if (pAd->MacTab.Content[pInfo->Wcid].ValidAsDls)
+                               ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+                       else
+#endif // QOS_DLS_SUPPORT //
+                               ActHeaderInit(pAd, &Frame.Hdr,  pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr);
+               }
+#endif // CONFIG_STA_SUPPORT //
+               Frame.Category = CATEGORY_BA;
+               Frame.Action = DELBA;
+               Frame.DelbaParm.Initiator = pInfo->Initiator;
+               Frame.DelbaParm.TID = pInfo->TID;
+               Frame.ReasonCode = 39; // Time Out
+               *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm));
+               Frame.ReasonCode = cpu2le16(Frame.ReasonCode);
+
+               MakeOutgoingFrame(pOutBuffer,               &FrameLen,
+                             sizeof(FRAME_DELBA_REQ),    &Frame,
+                             END_OF_ARGS);
+               MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+               MlmeFreeMemory(pAd, pOutBuffer);
+               DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator));
+       }
+}
+#endif // DOT11_N_SUPPORT //
+
+VOID MlmeQOSAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+VOID MlmeDLSAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+VOID MlmeInvalidAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+       //PUCHAR                   pOutBuffer = NULL;
+       //Return the receiving frame except the MSB of category filed set to 1.  7.3.1.11
+}
+
+VOID PeerQOSAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+#ifdef QOS_DLS_SUPPORT
+VOID PeerDLSAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR   Action = Elem->Msg[LENGTH_802_11+1];
+
+       switch(Action)
+       {
+               case ACTION_DLS_REQUEST:
+#ifdef CONFIG_STA_SUPPORT
+                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       PeerDlsReqAction(pAd, Elem);
+#endif // CONFIG_STA_SUPPORT //
+                       break;
+
+               case ACTION_DLS_RESPONSE:
+#ifdef CONFIG_STA_SUPPORT
+                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       PeerDlsRspAction(pAd, Elem);
+#endif // CONFIG_STA_SUPPORT //
+                       break;
+
+               case ACTION_DLS_TEARDOWN:
+#ifdef CONFIG_STA_SUPPORT
+                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       PeerDlsTearDownAction(pAd, Elem);
+#endif // CONFIG_STA_SUPPORT //
+                       break;
+       }
+}
+#endif // QOS_DLS_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+VOID PeerBAAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR   Action = Elem->Msg[LENGTH_802_11+1];
+
+       switch(Action)
+       {
+               case ADDBA_REQ:
+                       PeerAddBAReqAction(pAd,Elem);
+                       break;
+               case ADDBA_RESP:
+                       PeerAddBARspAction(pAd,Elem);
+                       break;
+               case DELBA:
+                       PeerDelBAAction(pAd,Elem);
+                       break;
+       }
+}
+
+
+#ifdef DOT11N_DRAFT3
+
+#ifdef CONFIG_STA_SUPPORT
+VOID StaPublicAction(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR Bss2040Coexist)
+{
+       BSS_2040_COEXIST_IE             BssCoexist;
+       MLME_SCAN_REQ_STRUCT                    ScanReq;
+
+       BssCoexist.word = Bss2040Coexist;
+       // AP asks Station to return a 20/40 BSS Coexistence mgmt frame.  So we first starts a scan, then send back 20/40 BSS Coexistence mgmt frame
+       if ((BssCoexist.field.InfoReq == 1) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040)))
+       {
+               // Clear record first.  After scan , will update those bit and send back to transmiter.
+               pAd->CommonCfg.BSSCoexist2040.field.InfoReq = 1;
+               pAd->CommonCfg.BSSCoexist2040.field.Intolerant40 = 0;
+               pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 0;
+               // Fill out stuff for scan request
+               ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_2040_BSS_COEXIST);
+               MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+               pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+       }
+}
+
+
+/*
+Description : Build Intolerant Channel Rerpot from Trigger event table.
+return : how many bytes copied.
+*/
+ULONG BuildIntolerantChannelRep(
+       IN      PRTMP_ADAPTER   pAd,
+       IN    PUCHAR  pDest)
+{
+       ULONG                   FrameLen = 0;
+       ULONG                   ReadOffset = 0;
+       UCHAR                   i;
+       UCHAR                   LastRegClass = 0xff;
+       PUCHAR                  pLen;
+
+       for ( i = 0;i < MAX_TRIGGER_EVENT;i++)
+       {
+               if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid == TRUE)
+               {
+                       if (pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass == LastRegClass)
+                       {
+                               *(pDest + ReadOffset) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel;
+                               *pLen++;
+                               ReadOffset++;
+                               FrameLen++;
+                       }
+                       else
+                       {
+                               *(pDest + ReadOffset) = IE_2040_BSS_INTOLERANT_REPORT;  // IE
+                               *(pDest + ReadOffset + 1) = 2;  // Len = RegClass byte + channel byte.
+                               pLen = pDest + ReadOffset + 1;
+                               LastRegClass = pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass;
+                               *(pDest + ReadOffset + 2) = LastRegClass;       // Len = RegClass byte + channel byte.
+                               *(pDest + ReadOffset + 3) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel;
+                               FrameLen += 4;
+                               ReadOffset += 4;
+                       }
+
+               }
+       }
+       return FrameLen;
+}
+
+
+/*
+Description : Send 20/40 BSS Coexistence Action frame If one trigger event is triggered.
+*/
+VOID Send2040CoexistAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN    UCHAR  Wcid,
+       IN      BOOLEAN bAddIntolerantCha)
+{
+       PUCHAR                  pOutBuffer = NULL;
+       NDIS_STATUS     NStatus;
+       FRAME_ACTION_HDR        Frame;
+       ULONG                   FrameLen;
+       ULONG                   IntolerantChaRepLen;
+
+       IntolerantChaRepLen = 0;
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if(NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction() allocate memory failed \n"));
+               return;
+       }
+       ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->CommonCfg.Bssid);
+       Frame.Category = CATEGORY_PUBLIC;
+       Frame.Action = ACTION_BSS_2040_COEXIST;
+
+       MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
+                                 sizeof(FRAME_ACTION_HDR),       &Frame,
+                                 END_OF_ARGS);
+
+       *(pOutBuffer + FrameLen) = pAd->CommonCfg.BSSCoexist2040.word;
+       FrameLen++;
+
+       if (bAddIntolerantCha == TRUE)
+               IntolerantChaRepLen = BuildIntolerantChannelRep(pAd, pOutBuffer + FrameLen);
+
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen + IntolerantChaRepLen);
+       DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction( BSSCoexist2040 = 0x%x )  \n", pAd->CommonCfg.BSSCoexist2040.word));
+
+}
+
+
+/*
+       ==========================================================================
+       Description:
+       After scan, Update 20/40 BSS Coexistence IE and send out.
+       According to 802.11n D3.03 11.14.10
+
+       Parameters:
+       ==========================================================================
+ */
+VOID Update2040CoexistFrameAndNotify(
+       IN      PRTMP_ADAPTER   pAd,
+       IN    UCHAR  Wcid,
+       IN      BOOLEAN bAddIntolerantCha)
+{
+       BSS_2040_COEXIST_IE     OldValue;
+
+       OldValue.word = pAd->CommonCfg.BSSCoexist2040.word;
+       if ((pAd->CommonCfg.TriggerEventTab.EventANo > 0) || (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0))
+               pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 1;
+
+       // Need to check !!!!
+       // How STA will set Intolerant40 if implementation dependent. Now we don't set this bit first.!!!!!
+       // So Only check BSS20WidthReq change.
+       if (OldValue.field.BSS20WidthReq != pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq)
+       {
+               Send2040CoexistAction(pAd, Wcid, bAddIntolerantCha);
+       }
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+BOOLEAN ChannelSwitchSanityCheck(
+       IN      PRTMP_ADAPTER   pAd,
+       IN    UCHAR  Wcid,
+       IN    UCHAR  NewChannel,
+       IN    UCHAR  Secondary)
+{
+       UCHAR           i;
+
+       if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+               return FALSE;
+
+       if ((NewChannel > 7) && (Secondary == 1))
+               return FALSE;
+
+       if ((NewChannel < 5) && (Secondary == 3))
+               return FALSE;
+
+       // 0. Check if new channel is in the channellist.
+       for (i = 0;i < pAd->ChannelListNum;i++)
+       {
+               if (pAd->ChannelList[i].Channel == NewChannel)
+               {
+                       break;
+               }
+       }
+
+       if (i == pAd->ChannelListNum)
+               return FALSE;
+
+       return TRUE;
+}
+
+
+VOID ChannelSwitchAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN    UCHAR  Wcid,
+       IN    UCHAR  NewChannel,
+       IN    UCHAR  Secondary)
+{
+       UCHAR           BBPValue = 0;
+       ULONG           MACValue;
+
+       DBGPRINT(RT_DEBUG_TRACE,("SPECTRUM - ChannelSwitchAction(NewChannel = %d , Secondary = %d)  \n", NewChannel, Secondary));
+
+       if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE)
+               return;
+
+       // 1.  Switches to BW = 20.
+       if (Secondary == 0)
+       {
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+               BBPValue&= (~0x18);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+               if (pAd->MACVersion == 0x28600100)
+               {
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11);
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
+               }
+               pAd->CommonCfg.BBPCurrentBW = BW_20;
+               pAd->CommonCfg.Channel = NewChannel;
+               pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
+               AsicSwitchChannel(pAd, pAd->CommonCfg.Channel,FALSE);
+               AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+               pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0;
+               DBGPRINT(RT_DEBUG_TRACE, ("!!!20MHz   !!! \n" ));
+       }
+       // 1.  Switches to BW = 40 And Station supports BW = 40.
+       else if (((Secondary == 1) || (Secondary == 3)) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1))
+       {
+               pAd->CommonCfg.Channel = NewChannel;
+
+               if (Secondary == 1)
+               {
+                       // Secondary above.
+                       pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2;
+                       RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue);
+                       MACValue &= 0xfe;
+                       RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue);
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+                       BBPValue&= (~0x18);
+                       BBPValue|= (0x10);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue);
+                       BBPValue&= (~0x20);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue);
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel ));
+               }
+               else
+               {
+                       // Secondary below.
+                       pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2;
+                       RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue);
+                       MACValue &= 0xfe;
+                       MACValue |= 0x1;
+                       RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue);
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+                       BBPValue&= (~0x18);
+                       BBPValue|= (0x10);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue);
+                       BBPValue&= (~0x20);
+                       BBPValue|= (0x20);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue);
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel ));
+               }
+               pAd->CommonCfg.BBPCurrentBW = BW_40;
+               AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+               AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+               pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1;
+       }
+}
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+VOID PeerPublicAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+#ifdef DOT11N_DRAFT3
+       UCHAR   Action = Elem->Msg[LENGTH_802_11+1];
+#endif // DOT11N_DRAFT3 //
+
+       if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+               return;
+
+#ifdef DOT11N_DRAFT3
+       switch(Action)
+       {
+               case ACTION_BSS_2040_COEXIST:   // Format defined in IEEE 7.4.7a.1 in 11n Draf3.03
+                       {
+                               //UCHAR BssCoexist;
+                               BSS_2040_COEXIST_ELEMENT                *pCoexistInfo;
+                               BSS_2040_COEXIST_IE                     *pBssCoexistIe;
+                               BSS_2040_INTOLERANT_CH_REPORT   *pIntolerantReport = NULL;
+
+                               if (Elem->MsgLen <= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT)) )
+                               {
+                                       DBGPRINT(RT_DEBUG_ERROR, ("ACTION - 20/40 BSS Coexistence Management Frame length too short! len = %ld!\n", Elem->MsgLen));
+                                       break;
+                               }
+                               DBGPRINT(RT_DEBUG_TRACE, ("ACTION - 20/40 BSS Coexistence Management action----> \n"));
+                               hex_dump("CoexistenceMgmtFrame", Elem->Msg, Elem->MsgLen);
+
+
+                               pCoexistInfo = (BSS_2040_COEXIST_ELEMENT *) &Elem->Msg[LENGTH_802_11+2];
+                               //hex_dump("CoexistInfo", (PUCHAR)pCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT));
+                               if (Elem->MsgLen >= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT) + sizeof(BSS_2040_INTOLERANT_CH_REPORT)))
+                               {
+                                       pIntolerantReport = (BSS_2040_INTOLERANT_CH_REPORT *)((PUCHAR)pCoexistInfo + sizeof(BSS_2040_COEXIST_ELEMENT));
+                               }
+                               //hex_dump("IntolerantReport ", (PUCHAR)pIntolerantReport, sizeof(BSS_2040_INTOLERANT_CH_REPORT));
+
+                               pBssCoexistIe = (BSS_2040_COEXIST_IE *)(&pCoexistInfo->BssCoexistIe);
+
+#ifdef CONFIG_STA_SUPPORT
+                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               {
+                                       if (INFRA_ON(pAd))
+                                       {
+                                               StaPublicAction(pAd, pCoexistInfo);
+                                       }
+                               }
+#endif // CONFIG_STA_SUPPORT //
+
+                       }
+                       break;
+       }
+
+#endif // DOT11N_DRAFT3 //
+
+}
+
+
+static VOID ReservedAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR Category;
+
+       if (Elem->MsgLen <= LENGTH_802_11)
+       {
+               return;
+       }
+
+       Category = Elem->Msg[LENGTH_802_11];
+       DBGPRINT(RT_DEBUG_TRACE,("Rcv reserved category(%d) Action Frame\n", Category));
+       hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen);
+}
+
+VOID PeerRMAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+
+{
+       return;
+}
+
+#ifdef DOT11_N_SUPPORT
+static VOID respond_ht_information_exchange_action(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       PUCHAR                  pOutBuffer = NULL;
+       NDIS_STATUS             NStatus;
+       ULONG                   FrameLen;
+       FRAME_HT_INFO   HTINFOframe, *pFrame;
+       UCHAR                   *pAddr;
+
+
+       // 2. Always send back ADDBA Response
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+
+       if (NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_TRACE,("ACTION - respond_ht_information_exchange_action() allocate memory failed \n"));
+               return;
+       }
+
+       // get RA
+       pFrame = (FRAME_HT_INFO *) &Elem->Msg[0];
+       pAddr = pFrame->Hdr.Addr2;
+
+       NdisZeroMemory(&HTINFOframe, sizeof(FRAME_HT_INFO));
+       // 2-1. Prepare ADDBA Response frame.
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               if (ADHOC_ON(pAd))
+                       ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+               else
+                       ActHeaderInit(pAd, &HTINFOframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       HTINFOframe.Category = CATEGORY_HT;
+       HTINFOframe.Action = HT_INFO_EXCHANGE;
+       HTINFOframe.HT_Info.Request = 0;
+       HTINFOframe.HT_Info.Forty_MHz_Intolerant = pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant;
+       HTINFOframe.HT_Info.STA_Channel_Width    = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
+
+       MakeOutgoingFrame(pOutBuffer,                                   &FrameLen,
+                                         sizeof(FRAME_HT_INFO),        &HTINFOframe,
+                                         END_OF_ARGS);
+
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+}
+
+
+#ifdef DOT11N_DRAFT3
+VOID SendNotifyBWActionFrame(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR  Wcid,
+       IN UCHAR apidx)
+{
+       PUCHAR                  pOutBuffer = NULL;
+       NDIS_STATUS     NStatus;
+       FRAME_ACTION_HDR        Frame;
+       ULONG                   FrameLen;
+       PUCHAR                  pAddr1;
+
+
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if(NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("ACT - SendNotifyBWAction() allocate memory failed \n"));
+               return;
+       }
+
+       if (Wcid == MCAST_WCID)
+               pAddr1 = &BROADCAST_ADDR[0];
+       else
+               pAddr1 = pAd->MacTab.Content[Wcid].Addr;
+       ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
+
+       Frame.Category = CATEGORY_HT;
+       Frame.Action = NOTIFY_BW_ACTION;
+
+       MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
+                                 sizeof(FRAME_ACTION_HDR),       &Frame,
+                                 END_OF_ARGS);
+
+       *(pOutBuffer + FrameLen) = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
+       FrameLen++;
+
+
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       DBGPRINT(RT_DEBUG_TRACE,("ACT - SendNotifyBWAction(NotifyBW= %d)!\n", pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth));
+
+}
+#endif // DOT11N_DRAFT3 //
+
+
+VOID PeerHTAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR   Action = Elem->Msg[LENGTH_802_11+1];
+
+       if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+               return;
+
+       switch(Action)
+       {
+               case NOTIFY_BW_ACTION:
+                       DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Notify Channel bandwidth action----> \n"));
+#ifdef CONFIG_STA_SUPPORT
+                       if(pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
+                       {
+                               // Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps
+                               // sending BW_Notify Action frame, and cause us to linkup and linkdown.
+                               // In legacy mode, don't need to parse HT action frame.
+                               DBGPRINT(RT_DEBUG_TRACE,("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n",
+                                                               Elem->Msg[LENGTH_802_11+2] ));
+                               break;
+                       }
+#endif // CONFIG_STA_SUPPORT //
+
+                       if (Elem->Msg[LENGTH_802_11+2] == 0)    // 7.4.8.2. if value is 1, keep the same as supported channel bandwidth.
+                               pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0;
+
+                       break;
+
+               case SMPS_ACTION:
+                       // 7.3.1.25
+                       DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n"));
+                       if (((Elem->Msg[LENGTH_802_11+2]&0x1) == 0))
+                       {
+                               pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE;
+                       }
+                       else if (((Elem->Msg[LENGTH_802_11+2]&0x2) == 0))
+                       {
+                               pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC;
+                       }
+                       else
+                       {
+                               pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC;
+                       }
+
+                       DBGPRINT(RT_DEBUG_TRACE,("Aid(%d) MIMO PS = %d\n", Elem->Wcid, pAd->MacTab.Content[Elem->Wcid].MmpsMode));
+                       // rt2860c : add something for smps change.
+                       break;
+
+               case SETPCO_ACTION:
+                       break;
+
+               case MIMO_CHA_MEASURE_ACTION:
+                       break;
+
+               case HT_INFO_EXCHANGE:
+                       {
+                               HT_INFORMATION_OCTET    *pHT_info;
+
+                               pHT_info = (HT_INFORMATION_OCTET *) &Elem->Msg[LENGTH_802_11+2];
+                               // 7.4.8.10
+                               DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Information Exchange action----> \n"));
+                               if (pHT_info->Request)
+                               {
+                                       respond_ht_information_exchange_action(pAd, Elem);
+                               }
+                       }
+                       break;
+       }
+}
+
+
+/*
+       ==========================================================================
+       Description:
+               Retry sending ADDBA Reqest.
+
+       IRQL = DISPATCH_LEVEL
+
+       Parametrs:
+       p8023Header: if this is already 802.3 format, p8023Header is NULL
+
+       Return  : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
+                               FALSE , then continue indicaterx at this moment.
+       ==========================================================================
+ */
+VOID ORIBATimerTimeout(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       MAC_TABLE_ENTRY *pEntry;
+       INT                     i, total;
+//     FRAME_BAR                       FrameBar;
+//     ULONG                   FrameLen;
+//     NDIS_STATUS     NStatus;
+//     PUCHAR                  pOutBuffer = NULL;
+//     USHORT                  Sequence;
+       UCHAR                   TID;
+
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+       total = pAd->MacTab.Size * NUM_OF_TID;
+
+       for (i = 1; ((i <MAX_LEN_OF_BA_ORI_TABLE) && (total > 0)) ; i++)
+       {
+               if  (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done)
+               {
+                       pEntry = &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].Wcid];
+                       TID = pAd->BATable.BAOriEntry[i].TID;
+
+                       ASSERT(pAd->BATable.BAOriEntry[i].Wcid < MAX_LEN_OF_MAC_TABLE);
+               }
+               total --;
+       }
+}
+
+
+VOID SendRefreshBAR(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MAC_TABLE_ENTRY *pEntry)
+{
+       FRAME_BAR               FrameBar;
+       ULONG                   FrameLen;
+       NDIS_STATUS     NStatus;
+       PUCHAR                  pOutBuffer = NULL;
+       USHORT                  Sequence;
+       UCHAR                   i, TID;
+       USHORT                  idx;
+       BA_ORI_ENTRY    *pBAEntry;
+
+       for (i = 0; i <NUM_OF_TID; i++)
+       {
+               idx = pEntry->BAOriWcidArray[i];
+               if (idx == 0)
+               {
+                       continue;
+               }
+               pBAEntry = &pAd->BATable.BAOriEntry[idx];
+
+               if  (pBAEntry->ORI_BA_Status == Originator_Done)
+               {
+                       TID = pBAEntry->TID;
+
+                       ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE);
+
+                       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+                       if(NStatus != NDIS_STATUS_SUCCESS)
+                       {
+                               DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
+                               return;
+                       }
+
+                       Sequence = pEntry->TxSeq[TID];
+
+
+#ifdef CONFIG_STA_SUPPORT
+                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->CurrentAddress);
+#endif // CONFIG_STA_SUPPORT //
+
+                       FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function.
+                       FrameBar.StartingSeq.field.StartSeq = Sequence; // make sure sequence not clear in DEL funciton.
+                       FrameBar.BarControl.TID = TID; // make sure sequence not clear in DEL funciton.
+
+                       MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
+                                                         sizeof(FRAME_BAR),      &FrameBar,
+                                                         END_OF_ARGS);
+                       //if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET)))
+                       if (1)  // Now we always send BAR.
+                       {
+                               //MiniportMMRequestUnlock(pAd, 0, pOutBuffer, FrameLen);
+                               MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+                       }
+                       MlmeFreeMemory(pAd, pOutBuffer);
+               }
+       }
+}
+#endif // DOT11_N_SUPPORT //
+
+VOID ActHeaderInit(
+    IN PRTMP_ADAPTER   pAd,
+    IN OUT PHEADER_802_11 pHdr80211,
+    IN PUCHAR Addr1,
+    IN PUCHAR Addr2,
+    IN PUCHAR Addr3)
+{
+    NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
+    pHdr80211->FC.Type = BTYPE_MGMT;
+    pHdr80211->FC.SubType = SUBTYPE_ACTION;
+
+    COPY_MAC_ADDR(pHdr80211->Addr1, Addr1);
+       COPY_MAC_ADDR(pHdr80211->Addr2, Addr2);
+    COPY_MAC_ADDR(pHdr80211->Addr3, Addr3);
+}
+
+VOID BarHeaderInit(
+       IN      PRTMP_ADAPTER   pAd,
+       IN OUT PFRAME_BAR pCntlBar,
+       IN PUCHAR pDA,
+       IN PUCHAR pSA)
+{
+//     USHORT  Duration;
+
+       NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR));
+       pCntlBar->FC.Type = BTYPE_CNTL;
+       pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ;
+       pCntlBar->BarControl.MTID = 0;
+       pCntlBar->BarControl.Compressed = 1;
+       pCntlBar->BarControl.ACKPolicy = 0;
+
+
+       pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA));
+
+       COPY_MAC_ADDR(pCntlBar->Addr1, pDA);
+       COPY_MAC_ADDR(pCntlBar->Addr2, pSA);
+}
+
+
+/*
+       ==========================================================================
+       Description:
+               Insert Category and action code into the action frame.
+
+       Parametrs:
+               1. frame buffer pointer.
+               2. frame length.
+               3. category code of the frame.
+               4. action code of the frame.
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID InsertActField(
+       IN PRTMP_ADAPTER pAd,
+       OUT PUCHAR pFrameBuf,
+       OUT PULONG pFrameLen,
+       IN UINT8 Category,
+       IN UINT8 ActCode)
+{
+       ULONG TempLen;
+
+       MakeOutgoingFrame(      pFrameBuf,              &TempLen,
+                                               1,                              &Category,
+                                               1,                              &ActCode,
+                                               END_OF_ARGS);
+
+       *pFrameLen = *pFrameLen + TempLen;
+
+       return;
+}
diff --git a/drivers/staging/rt2870/common/action.h b/drivers/staging/rt2870/common/action.h
new file mode 100644 (file)
index 0000000..ce3877d
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       aironet.h
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Name            Date                    Modification logs
+       Paul Lin        04-06-15                Initial
+*/
+
+#ifndef        __ACTION_H__
+#define        __ACTION_H__
+
+typedef struct PACKED __HT_INFO_OCTET
+{
+#ifdef RT_BIG_ENDIAN
+       UCHAR   Reserved:5;
+       UCHAR   STA_Channel_Width:1;
+       UCHAR   Forty_MHz_Intolerant:1;
+       UCHAR   Request:1;
+#else
+       UCHAR   Request:1;
+       UCHAR   Forty_MHz_Intolerant:1;
+       UCHAR   STA_Channel_Width:1;
+       UCHAR   Reserved:5;
+#endif
+} HT_INFORMATION_OCTET;
+
+
+typedef struct PACKED __FRAME_HT_INFO
+{
+       HEADER_802_11                   Hdr;
+       UCHAR                                   Category;
+       UCHAR                                   Action;
+       HT_INFORMATION_OCTET    HT_Info;
+}   FRAME_HT_INFO, *PFRAME_HT_INFO;
+
+#endif /* __ACTION_H__ */
+
+
diff --git a/drivers/staging/rt2870/common/ba_action.c b/drivers/staging/rt2870/common/ba_action.c
new file mode 100644 (file)
index 0000000..95addb2
--- /dev/null
@@ -0,0 +1,1798 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+
+#ifdef DOT11_N_SUPPORT
+
+#include "../rt_config.h"
+
+
+
+#define BA_ORI_INIT_SEQ                (pEntry->TxSeq[TID]) //1                        // inital sequence number of BA session
+
+#define ORI_SESSION_MAX_RETRY  8
+#define ORI_BA_SESSION_TIMEOUT (2000)  // ms
+#define REC_BA_SESSION_IDLE_TIMEOUT    (1000)  // ms
+
+#define REORDERING_PACKET_TIMEOUT              ((100 * HZ)/1000)       // system ticks -- 100 ms
+#define MAX_REORDERING_PACKET_TIMEOUT  ((3000 * HZ)/1000)      // system ticks -- 100 ms
+
+#define RESET_RCV_SEQ          (0xFFFF)
+
+static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk);
+
+
+BA_ORI_ENTRY *BATableAllocOriEntry(
+                                                                 IN  PRTMP_ADAPTER   pAd,
+                                                                 OUT USHORT          *Idx);
+
+BA_REC_ENTRY *BATableAllocRecEntry(
+                                                                 IN  PRTMP_ADAPTER   pAd,
+                                                                 OUT USHORT          *Idx);
+
+VOID BAOriSessionSetupTimeout(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3);
+
+VOID BARecSessionIdleTimeout(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3);
+
+
+BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout);
+BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout);
+
+#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk)    \
+                       Announce_Reordering_Packet(_pAd, _mpdu_blk);
+
+VOID BA_MaxWinSizeReasign(
+       IN PRTMP_ADAPTER        pAd,
+       IN MAC_TABLE_ENTRY  *pEntryPeer,
+       OUT UCHAR                       *pWinSize)
+{
+       UCHAR MaxSize;
+
+
+       if (pAd->MACVersion >= RALINK_2883_VERSION) // 3*3
+       {
+               if (pAd->MACVersion >= RALINK_3070_VERSION)
+               {
+                       if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
+                               MaxSize = 7; // for non-open mode
+                       else
+                               MaxSize = 13;
+               }
+               else
+                       MaxSize = 31;
+       }
+       else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e
+       {
+               if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
+                       MaxSize = 7; // for non-open mode
+               else
+                       MaxSize = 13;
+       }
+       else
+               MaxSize = 7;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n",
+                       *pWinSize, MaxSize));
+
+       if ((*pWinSize) > MaxSize)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n",
+                               *pWinSize, MaxSize));
+
+               *pWinSize = MaxSize;
+       }
+}
+
+void Announce_Reordering_Packet(IN PRTMP_ADAPTER                       pAd,
+                                                               IN struct reordering_mpdu       *mpdu)
+{
+       PNDIS_PACKET    pPacket;
+
+       pPacket = mpdu->pPacket;
+
+       if (mpdu->bAMSDU)
+       {
+               ASSERT(0);
+               BA_Reorder_AMSDU_Annnounce(pAd, pPacket);
+       }
+       else
+       {
+               //
+               // pass this 802.3 packet to upper layer or forward this packet to WM directly
+               //
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket));
+#endif // CONFIG_STA_SUPPORT //
+       }
+}
+
+/*
+ * Insert a reordering mpdu into sorted linked list by sequence no.
+ */
+BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu)
+{
+
+       struct reordering_mpdu **ppScan = &list->next;
+
+       while (*ppScan != NULL)
+       {
+               if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ))
+               {
+                       ppScan = &(*ppScan)->next;
+               }
+               else if ((*ppScan)->Sequence == mpdu->Sequence)
+               {
+                       /* give up this duplicated frame */
+                       return(FALSE);
+               }
+               else
+               {
+                       /* find position */
+                       break;
+               }
+       }
+
+       mpdu->next = *ppScan;
+       *ppScan = mpdu;
+       list->qlen++;
+       return TRUE;
+}
+
+
+/*
+ * caller lock critical section if necessary
+ */
+static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk)
+{
+       list->qlen++;
+       mpdu_blk->next = list->next;
+       list->next = mpdu_blk;
+}
+
+/*
+ * caller lock critical section if necessary
+ */
+static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list)
+{
+       struct reordering_mpdu *mpdu_blk = NULL;
+
+       ASSERT(list);
+
+               if (list->qlen)
+               {
+                       list->qlen--;
+                       mpdu_blk = list->next;
+                       if (mpdu_blk)
+                       {
+                               list->next = mpdu_blk->next;
+                               mpdu_blk->next = NULL;
+                       }
+               }
+       return mpdu_blk;
+}
+
+
+static inline struct reordering_mpdu  *ba_reordering_mpdu_dequeue(struct reordering_list *list)
+{
+       return(ba_dequeue(list));
+}
+
+
+static inline struct reordering_mpdu  *ba_reordering_mpdu_probe(struct reordering_list *list)
+       {
+       ASSERT(list);
+
+               return(list->next);
+       }
+
+
+/*
+ * free all resource for reordering mechanism
+ */
+void ba_reordering_resource_release(PRTMP_ADAPTER pAd)
+{
+       BA_TABLE        *Tab;
+       PBA_REC_ENTRY   pBAEntry;
+       struct reordering_mpdu *mpdu_blk;
+       int i;
+
+       Tab = &pAd->BATable;
+
+       /* I.  release all pending reordering packet */
+       NdisAcquireSpinLock(&pAd->BATabLock);
+       for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
+       {
+               pBAEntry = &Tab->BARecEntry[i];
+               if (pBAEntry->REC_BA_Status != Recipient_NONE)
+               {
+                       while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
+                       {
+                               ASSERT(mpdu_blk->pPacket);
+                               RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE);
+                               ba_mpdu_blk_free(pAd, mpdu_blk);
+                       }
+               }
+       }
+       NdisReleaseSpinLock(&pAd->BATabLock);
+
+       ASSERT(pBAEntry->list.qlen == 0);
+       /* II. free memory of reordering mpdu table */
+       NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
+       os_free_mem(pAd, pAd->mpdu_blk_pool.mem);
+       NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
+}
+
+
+
+/*
+ * Allocate all resource for reordering mechanism
+ */
+BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num)
+{
+       int     i;
+       PUCHAR  mem;
+       struct reordering_mpdu *mpdu_blk;
+       struct reordering_list *freelist;
+
+       /* allocate spinlock */
+       NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock);
+
+       /* initialize freelist */
+       freelist = &pAd->mpdu_blk_pool.freelist;
+       freelist->next = NULL;
+       freelist->qlen = 0;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu))));
+
+       /* allocate number of mpdu_blk memory */
+       os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu)));
+
+       pAd->mpdu_blk_pool.mem = mem;
+
+       if (mem == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n"));
+               return(FALSE);
+       }
+
+       /* build mpdu_blk free list */
+       for (i=0; i<num; i++)
+       {
+               /* get mpdu_blk */
+               mpdu_blk = (struct reordering_mpdu *) mem;
+               /* initial mpdu_blk */
+               NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
+               /* next mpdu_blk */
+               mem += sizeof(struct reordering_mpdu);
+               /* insert mpdu_blk into freelist */
+               ba_enqueue(freelist, mpdu_blk);
+       }
+
+       return(TRUE);
+}
+
+//static int blk_count=0; // sample take off, no use
+
+static struct reordering_mpdu *ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd)
+{
+       struct reordering_mpdu *mpdu_blk;
+
+       NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
+       mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist);
+       if (mpdu_blk)
+       {
+//             blk_count++;
+               /* reset mpdu_blk */
+               NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
+       }
+       NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
+       return mpdu_blk;
+}
+
+static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk)
+{
+       ASSERT(mpdu_blk);
+
+       NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
+//     blk_count--;
+       ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk);
+       NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
+}
+
+
+static USHORT ba_indicate_reordering_mpdus_in_order(
+                                                                                                  IN PRTMP_ADAPTER    pAd,
+                                                                                                  IN PBA_REC_ENTRY    pBAEntry,
+                                                                                                  IN USHORT           StartSeq)
+{
+       struct reordering_mpdu *mpdu_blk;
+       USHORT  LastIndSeq = RESET_RCV_SEQ;
+
+       NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+
+       while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
+               {
+                       /* find in-order frame */
+               if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ))
+                       {
+                               break;
+                       }
+                       /* dequeue in-order frame from reodering list */
+                       mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
+                       /* pass this frame up */
+               ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
+               /* move to next sequence */
+                       StartSeq = mpdu_blk->Sequence;
+               LastIndSeq = StartSeq;
+               /* free mpdu_blk */
+                       ba_mpdu_blk_free(pAd, mpdu_blk);
+       }
+
+       NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+
+       /* update last indicated sequence */
+       return LastIndSeq;
+}
+
+static void ba_indicate_reordering_mpdus_le_seq(
+                                                                                          IN PRTMP_ADAPTER    pAd,
+                                                                                          IN PBA_REC_ENTRY    pBAEntry,
+                                                                                          IN USHORT           Sequence)
+{
+       struct reordering_mpdu *mpdu_blk;
+
+       NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+       while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
+               {
+                       /* find in-order frame */
+               if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ))
+               {
+                       /* dequeue in-order frame from reodering list */
+                       mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
+                       /* pass this frame up */
+                       ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
+                       /* free mpdu_blk */
+                       ba_mpdu_blk_free(pAd, mpdu_blk);
+               }
+               else
+                       {
+                               break;
+                       }
+       }
+       NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+}
+
+
+static void ba_refresh_reordering_mpdus(
+                                                                          IN PRTMP_ADAPTER    pAd,
+                                                                          PBA_REC_ENTRY       pBAEntry)
+{
+       struct reordering_mpdu *mpdu_blk;
+
+       NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+
+                       /* dequeue in-order frame from reodering list */
+       while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
+       {
+                       /* pass this frame up */
+               ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
+
+               pBAEntry->LastIndSeq = mpdu_blk->Sequence;
+                       ba_mpdu_blk_free(pAd, mpdu_blk);
+
+               /* update last indicated sequence */
+       }
+       ASSERT(pBAEntry->list.qlen == 0);
+       pBAEntry->LastIndSeq = RESET_RCV_SEQ;
+       NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+}
+
+
+//static
+void ba_flush_reordering_timeout_mpdus(
+                                                                       IN PRTMP_ADAPTER    pAd,
+                                                                       IN PBA_REC_ENTRY    pBAEntry,
+                                                                       IN ULONG            Now32)
+
+{
+       USHORT Sequence;
+
+//     if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&
+//              (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //||
+//             (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&
+//              (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))
+       if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6)))
+                &&(pBAEntry->list.qlen > 1)
+               )
+       {
+               DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
+                          (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT,
+                          pBAEntry->LastIndSeq));
+               ba_refresh_reordering_mpdus(pAd, pBAEntry);
+               pBAEntry->LastIndSeqAtTimer = Now32;
+       }
+       else
+       if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
+               && (pBAEntry->list.qlen > 0)
+          )
+               {
+               //
+               // force LastIndSeq to shift to LastIndSeq+1
+               //
+               Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ;
+               ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
+               pBAEntry->LastIndSeqAtTimer = Now32;
+                       pBAEntry->LastIndSeq = Sequence;
+               //
+               // indicate in-order mpdus
+               //
+               Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence);
+               if (Sequence != RESET_RCV_SEQ)
+               {
+                       pBAEntry->LastIndSeq = Sequence;
+               }
+
+       }
+#if 0
+       else if (
+                        (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT))) &&
+                         (pBAEntry->list.qlen > 1))
+                       )
+               {
+               DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%lx-%lx = %d > %d): %x\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
+                          (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT,
+                          pBAEntry->LastIndSeq));
+               ba_refresh_reordering_mpdus(pAd, pBAEntry);
+                       pBAEntry->LastIndSeqAtTimer = Now32;
+                               }
+#endif
+}
+
+
+/*
+ * generate ADDBA request to
+ * set up BA agreement
+ */
+VOID BAOriSessionSetUp(
+                                         IN PRTMP_ADAPTER    pAd,
+                                         IN MAC_TABLE_ENTRY  *pEntry,
+                                         IN UCHAR            TID,
+                                         IN USHORT           TimeOut,
+                                         IN ULONG            DelayTime,
+                                         IN BOOLEAN          isForced)
+
+{
+       //MLME_ADDBA_REQ_STRUCT AddbaReq;
+       BA_ORI_ENTRY            *pBAEntry = NULL;
+       USHORT                  Idx;
+       BOOLEAN                 Cancelled;
+
+       if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE)  &&  (isForced == FALSE))
+               return;
+
+       // if this entry is limited to use legacy tx mode, it doesn't generate BA.
+       if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
+               return;
+
+       if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))
+       {
+               // try again after 3 secs
+               DelayTime = 3000;
+//             printk("DeCline BA from Peer\n");
+//             return;
+       }
+
+
+       Idx = pEntry->BAOriWcidArray[TID];
+       if (Idx == 0)
+       {
+               // allocate a BA session
+               pBAEntry = BATableAllocOriEntry(pAd, &Idx);
+               if (pBAEntry == NULL)
+               {
+                       DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
+                       return;
+               }
+       }
+       else
+       {
+               pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+       }
+
+       if (pBAEntry->ORI_BA_Status >= Originator_WaitRes)
+       {
+               return;
+       }
+
+       pEntry->BAOriWcidArray[TID] = Idx;
+
+       // Initialize BA session
+       pBAEntry->ORI_BA_Status = Originator_WaitRes;
+       pBAEntry->Wcid = pEntry->Aid;
+       pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
+       pBAEntry->Sequence = BA_ORI_INIT_SEQ;
+       pBAEntry->Token = 1;    // (2008-01-21) Jan Lee recommends it - this token can't be 0
+       pBAEntry->TID = TID;
+       pBAEntry->TimeOutValue = TimeOut;
+       pBAEntry->pAdapter = pAd;
+
+       if (!(pEntry->TXBAbitmap & (1<<TID)))
+       {
+               RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE);
+       }
+       else
+               RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
+
+       // set timer to send ADDBA request
+       RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
+}
+
+VOID BAOriSessionAdd(
+                       IN PRTMP_ADAPTER    pAd,
+                                       IN MAC_TABLE_ENTRY  *pEntry,
+                       IN PFRAME_ADDBA_RSP pFrame)
+{
+       BA_ORI_ENTRY  *pBAEntry = NULL;
+       BOOLEAN       Cancelled;
+       UCHAR         TID;
+       USHORT        Idx;
+       PUCHAR          pOutBuffer2 = NULL;
+       NDIS_STATUS     NStatus;
+       ULONG           FrameLen;
+       FRAME_BAR       FrameBar;
+
+       TID = pFrame->BaParm.TID;
+       Idx = pEntry->BAOriWcidArray[TID];
+       pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+
+       // Start fill in parameters.
+       if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes))
+       {
+               pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize));
+               BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
+
+               pBAEntry->TimeOutValue = pFrame->TimeOutValue;
+               pBAEntry->ORI_BA_Status = Originator_Done;
+               // reset sequence number
+               pBAEntry->Sequence = BA_ORI_INIT_SEQ;
+               // Set Bitmap flag.
+               pEntry->TXBAbitmap |= (1<<TID);
+                               RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
+
+               pBAEntry->ORIBATimer.TimerValue = 0;    //pFrame->TimeOutValue;
+
+               DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __FUNCTION__, pEntry->TXBAbitmap,
+                                                                pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue));
+
+               // SEND BAR ;
+               NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2);  //Get an unused nonpaged memory
+               if (NStatus != NDIS_STATUS_SUCCESS)
+               {
+                       DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n"));
+                       return;
+               }
+
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress);
+#endif // CONFIG_STA_SUPPORT //
+
+               FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function.
+               FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton.
+               FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton.
+               MakeOutgoingFrame(pOutBuffer2,              &FrameLen,
+                                                 sizeof(FRAME_BAR),      &FrameBar,
+                                         END_OF_ARGS);
+               MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
+               MlmeFreeMemory(pAd, pOutBuffer2);
+
+
+               if (pBAEntry->ORIBATimer.TimerValue)
+                       RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec
+       }
+}
+
+BOOLEAN BARecSessionAdd(
+                                          IN PRTMP_ADAPTER    pAd,
+                                          IN MAC_TABLE_ENTRY  *pEntry,
+                                          IN PFRAME_ADDBA_REQ pFrame)
+{
+       BA_REC_ENTRY            *pBAEntry = NULL;
+       BOOLEAN                 Status = TRUE;
+       BOOLEAN                 Cancelled;
+       USHORT                  Idx;
+       UCHAR                   TID;
+       UCHAR                   BAWinSize;
+       //UINT32                  Value;
+       //UINT                    offset;
+
+
+       ASSERT(pEntry);
+
+       // find TID
+       TID = pFrame->BaParm.TID;
+
+       BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
+
+       // Intel patch
+       if (BAWinSize == 0)
+       {
+               BAWinSize = 64;
+       }
+
+       Idx = pEntry->BARecWcidArray[TID];
+
+
+       if (Idx == 0)
+       {
+               pBAEntry = BATableAllocRecEntry(pAd, &Idx);
+       }
+       else
+       {
+               pBAEntry = &pAd->BATable.BARecEntry[Idx];
+               // flush all pending reordering mpdus
+               ba_refresh_reordering_mpdus(pAd, pBAEntry);
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __FUNCTION__, pAd->BATable.numAsRecipient, Idx,
+                                                        pFrame->BaParm.BufSize, BAWinSize));
+
+       // Start fill in parameters.
+       if (pBAEntry != NULL)
+       {
+               ASSERT(pBAEntry->list.qlen == 0);
+
+               pBAEntry->REC_BA_Status = Recipient_HandleRes;
+               pBAEntry->BAWinSize = BAWinSize;
+               pBAEntry->Wcid = pEntry->Aid;
+               pBAEntry->TID = TID;
+               pBAEntry->TimeOutValue = pFrame->TimeOutValue;
+               pBAEntry->REC_BA_Status = Recipient_Accept;
+               // initial sequence number
+               pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq;
+
+               printk("Start Seq = %08x\n",  pFrame->BaStartSeq.field.StartSeq);
+
+               if (pEntry->RXBAbitmap & (1<<TID))
+               {
+                       RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
+               }
+               else
+               {
+                       RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE);
+               }
+
+#if 0  // for debugging
+               RTMPSetTimer(&pBAEntry->RECBATimer, REC_BA_SESSION_IDLE_TIMEOUT);
+#endif
+
+               // Set Bitmap flag.
+               pEntry->RXBAbitmap |= (1<<TID);
+               pEntry->BARecWcidArray[TID] = Idx;
+
+               pEntry->BADeclineBitmap &= ~(1<<TID);
+
+               // Set BA session mask in WCID table.
+               RT28XX_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
+
+               DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
+                               pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID]));
+       }
+       else
+       {
+               Status = FALSE;
+               DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
+                               PRINT_MAC(pEntry->Addr), TID));
+       }
+       return(Status);
+}
+
+
+BA_REC_ENTRY *BATableAllocRecEntry(
+                                                                 IN  PRTMP_ADAPTER   pAd,
+                                                                 OUT USHORT          *Idx)
+{
+       int             i;
+       BA_REC_ENTRY    *pBAEntry = NULL;
+
+
+       NdisAcquireSpinLock(&pAd->BATabLock);
+
+       if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION)
+       {
+               printk("BA Recipeint Session (%ld) > %d\n", pAd->BATable.numAsRecipient,
+                       MAX_BARECI_SESSION);
+               goto done;
+       }
+
+       // reserve idx 0 to identify BAWcidArray[TID] as empty
+       for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++)
+       {
+               pBAEntry =&pAd->BATable.BARecEntry[i];
+               if ((pBAEntry->REC_BA_Status == Recipient_NONE))
+               {
+                       // get one
+                       pAd->BATable.numAsRecipient++;
+                       pBAEntry->REC_BA_Status = Recipient_USED;
+                       *Idx = i;
+                       break;
+               }
+       }
+
+done:
+       NdisReleaseSpinLock(&pAd->BATabLock);
+       return pBAEntry;
+}
+
+BA_ORI_ENTRY *BATableAllocOriEntry(
+                                                                 IN  PRTMP_ADAPTER   pAd,
+                                                                 OUT USHORT          *Idx)
+{
+       int             i;
+       BA_ORI_ENTRY    *pBAEntry = NULL;
+
+       NdisAcquireSpinLock(&pAd->BATabLock);
+
+       if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE))
+       {
+               goto done;
+       }
+
+       // reserve idx 0 to identify BAWcidArray[TID] as empty
+       for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++)
+       {
+               pBAEntry =&pAd->BATable.BAOriEntry[i];
+               if ((pBAEntry->ORI_BA_Status == Originator_NONE))
+               {
+                       // get one
+                       pAd->BATable.numAsOriginator++;
+                       pBAEntry->ORI_BA_Status = Originator_USED;
+                       pBAEntry->pAdapter = pAd;
+                       *Idx = i;
+                       break;
+               }
+       }
+
+done:
+       NdisReleaseSpinLock(&pAd->BATabLock);
+       return pBAEntry;
+}
+
+
+VOID BATableFreeOriEntry(
+                                               IN  PRTMP_ADAPTER   pAd,
+                                               IN  ULONG           Idx)
+{
+       BA_ORI_ENTRY    *pBAEntry = NULL;
+       MAC_TABLE_ENTRY *pEntry;
+
+
+       if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
+               return;
+
+       pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+
+       if (pBAEntry->ORI_BA_Status != Originator_NONE)
+       {
+               pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
+               pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
+
+
+               NdisAcquireSpinLock(&pAd->BATabLock);
+               if (pBAEntry->ORI_BA_Status == Originator_Done)
+               {
+                       pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) ));
+                       DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
+                       // Erase Bitmap flag.
+               }
+
+               ASSERT(pAd->BATable.numAsOriginator != 0);
+
+               pAd->BATable.numAsOriginator -= 1;
+
+               pBAEntry->ORI_BA_Status = Originator_NONE;
+               pBAEntry->Token = 0;
+               NdisReleaseSpinLock(&pAd->BATabLock);
+       }
+}
+
+
+VOID BATableFreeRecEntry(
+                                               IN  PRTMP_ADAPTER   pAd,
+                                               IN  ULONG           Idx)
+{
+       BA_REC_ENTRY    *pBAEntry = NULL;
+       MAC_TABLE_ENTRY *pEntry;
+
+
+       if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
+               return;
+
+       pBAEntry =&pAd->BATable.BARecEntry[Idx];
+
+       if (pBAEntry->REC_BA_Status != Recipient_NONE)
+       {
+               pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
+               pEntry->BARecWcidArray[pBAEntry->TID] = 0;
+
+               NdisAcquireSpinLock(&pAd->BATabLock);
+
+               ASSERT(pAd->BATable.numAsRecipient != 0);
+
+               pAd->BATable.numAsRecipient -= 1;
+
+               pBAEntry->REC_BA_Status = Recipient_NONE;
+               NdisReleaseSpinLock(&pAd->BATabLock);
+       }
+}
+
+
+VOID BAOriSessionTearDown(
+                                                IN OUT  PRTMP_ADAPTER   pAd,
+                                                IN      UCHAR           Wcid,
+                                                IN      UCHAR           TID,
+                                                IN      BOOLEAN         bPassive,
+                                                IN      BOOLEAN         bForceSend)
+{
+       ULONG           Idx = 0;
+       BA_ORI_ENTRY    *pBAEntry;
+       BOOLEAN         Cancelled;
+
+       if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+       {
+               return;
+       }
+
+       //
+       // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
+       //
+       Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
+       if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
+       {
+               if (bForceSend == TRUE)
+               {
+                       // force send specified TID DelBA
+                       MLME_DELBA_REQ_STRUCT   DelbaReq;
+                       MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+
+                       NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
+                       NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
+
+                       COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
+                       DelbaReq.Wcid = Wcid;
+                       DelbaReq.TID = TID;
+                       DelbaReq.Initiator = ORIGINATOR;
+#if 1
+                       Elem->MsgLen  = sizeof(DelbaReq);
+                       NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
+                       MlmeDELBAAction(pAd, Elem);
+                       kfree(Elem);
+#else
+                       MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
+                       RT28XX_MLME_HANDLER(pAd);
+#endif
+               }
+
+               return;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
+
+       pBAEntry = &pAd->BATable.BAOriEntry[Idx];
+       DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status));
+       //
+       // Prepare DelBA action frame and send to the peer.
+       //
+       if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done))
+       {
+               MLME_DELBA_REQ_STRUCT   DelbaReq;
+               MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+
+               NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
+               NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
+
+               COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
+               DelbaReq.Wcid = Wcid;
+               DelbaReq.TID = pBAEntry->TID;
+               DelbaReq.Initiator = ORIGINATOR;
+#if 1
+               Elem->MsgLen  = sizeof(DelbaReq);
+               NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
+               MlmeDELBAAction(pAd, Elem);
+               kfree(Elem);
+#else
+               MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
+               RT28XX_MLME_HANDLER(pAd);
+#endif
+       }
+       RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
+       BATableFreeOriEntry(pAd, Idx);
+
+       if (bPassive)
+       {
+               //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
+       }
+}
+
+VOID BARecSessionTearDown(
+                                                IN OUT  PRTMP_ADAPTER   pAd,
+                                                IN      UCHAR           Wcid,
+                                                IN      UCHAR           TID,
+                                                IN      BOOLEAN         bPassive)
+{
+       ULONG           Idx = 0;
+       BA_REC_ENTRY    *pBAEntry;
+
+       if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+       {
+               return;
+       }
+
+       //
+       //  Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
+       //
+       Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+       if (Idx == 0)
+               return;
+
+       DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
+
+
+       pBAEntry = &pAd->BATable.BARecEntry[Idx];
+       DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status));
+       //
+       // Prepare DelBA action frame and send to the peer.
+       //
+       if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept))
+       {
+               MLME_DELBA_REQ_STRUCT   DelbaReq;
+               BOOLEAN                                 Cancelled;
+               MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+               //ULONG   offset;
+               //UINT32  VALUE;
+
+               RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
+
+               //
+               // 1. Send DELBA Action Frame
+               //
+               if (bPassive == FALSE)
+               {
+                       NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
+                       NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
+
+                       COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
+                       DelbaReq.Wcid = Wcid;
+                       DelbaReq.TID = TID;
+                       DelbaReq.Initiator = RECIPIENT;
+#if 1
+                       Elem->MsgLen  = sizeof(DelbaReq);
+                       NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
+                       MlmeDELBAAction(pAd, Elem);
+                       kfree(Elem);
+#else
+                       MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
+                       RT28XX_MLME_HANDLER(pAd);
+#endif
+               }
+
+
+               //
+               // 2. Free resource of BA session
+               //
+               // flush all pending reordering mpdus
+               ba_refresh_reordering_mpdus(pAd, pBAEntry);
+
+               NdisAcquireSpinLock(&pAd->BATabLock);
+
+               // Erase Bitmap flag.
+               pBAEntry->LastIndSeq = RESET_RCV_SEQ;
+               pBAEntry->BAWinSize = 0;
+               // Erase Bitmap flag at software mactable
+               pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID)));
+               pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0;
+
+               RT28XX_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
+
+               NdisReleaseSpinLock(&pAd->BATabLock);
+
+       }
+
+       BATableFreeRecEntry(pAd, Idx);
+}
+
+VOID BASessionTearDownALL(
+                                                IN OUT  PRTMP_ADAPTER pAd,
+                                                IN      UCHAR Wcid)
+{
+       int i;
+
+       for (i=0; i<NUM_OF_TID; i++)
+       {
+               BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
+               BARecSessionTearDown(pAd, Wcid, i, FALSE);
+       }
+}
+
+
+/*
+       ==========================================================================
+       Description:
+               Retry sending ADDBA Reqest.
+
+       IRQL = DISPATCH_LEVEL
+
+       Parametrs:
+       p8023Header: if this is already 802.3 format, p8023Header is NULL
+
+       Return  : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
+                               FALSE , then continue indicaterx at this moment.
+       ==========================================================================
+ */
+VOID BAOriSessionSetupTimeout(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3)
+{
+       BA_ORI_ENTRY    *pBAEntry = (BA_ORI_ENTRY *)FunctionContext;
+       MAC_TABLE_ENTRY *pEntry;
+       PRTMP_ADAPTER   pAd;
+
+       if (pBAEntry == NULL)
+               return;
+
+       pAd = pBAEntry->pAdapter;
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // Do nothing if monitor mode is on
+               if (MONITOR_ON(pAd))
+                       return;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef RALINK_ATE
+       // Nothing to do in ATE mode.
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+       pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
+
+       if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY))
+       {
+               MLME_ADDBA_REQ_STRUCT    AddbaReq;
+
+               NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
+               COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
+               AddbaReq.Wcid = (UCHAR)(pEntry->Aid);
+               AddbaReq.TID = pBAEntry->TID;
+               AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
+               AddbaReq.TimeOutValue = 0;
+               AddbaReq.Token = pBAEntry->Token;
+               MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq);
+               RT28XX_MLME_HANDLER(pAd);
+               DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token));
+
+               pBAEntry->Token++;
+               RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
+       }
+       else
+       {
+               BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+               Retry sending ADDBA Reqest.
+
+       IRQL = DISPATCH_LEVEL
+
+       Parametrs:
+       p8023Header: if this is already 802.3 format, p8023Header is NULL
+
+       Return  : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
+                               FALSE , then continue indicaterx at this moment.
+       ==========================================================================
+ */
+VOID BARecSessionIdleTimeout(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3)
+{
+
+       BA_REC_ENTRY    *pBAEntry = (BA_REC_ENTRY *)FunctionContext;
+       PRTMP_ADAPTER   pAd;
+       ULONG           Now32;
+
+       if (pBAEntry == NULL)
+               return;
+
+       if ((pBAEntry->REC_BA_Status == Recipient_Accept))
+       {
+               NdisGetSystemUpTime(&Now32);
+
+               if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT)))
+               {
+                       pAd = pBAEntry->pAdapter;
+                       // flush all pending reordering mpdus
+                       ba_refresh_reordering_mpdus(pAd, pBAEntry);
+                       printk("%ld: REC BA session Timeout\n", Now32);
+               }
+       }
+}
+
+
+VOID PeerAddBAReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+
+{
+       //      7.4.4.1
+       //ULONG Idx;
+       UCHAR   Status = 1;
+       UCHAR   pAddr[6];
+       FRAME_ADDBA_RSP ADDframe;
+       PUCHAR         pOutBuffer = NULL;
+       NDIS_STATUS     NStatus;
+       PFRAME_ADDBA_REQ  pAddreqFrame = NULL;
+       //UCHAR         BufSize;
+       ULONG       FrameLen;
+       PULONG      ptemp;
+       PMAC_TABLE_ENTRY        pMacEntry;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid));
+
+       //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);
+
+       //ADDBA Request from unknown peer, ignore this.
+       if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+               return;
+
+       pMacEntry = &pAd->MacTab.Content[Elem->Wcid];
+       DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n"));
+       ptemp = (PULONG)Elem->Msg;
+       //DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8)));
+
+       if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr))
+       {
+
+               if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry))
+               {
+                       pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
+                       printk("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid);
+                       if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame))
+                               Status = 0;
+                       else
+                               Status = 38; // more parameters have invalid values
+               }
+               else
+               {
+                       Status = 37; // the request has been declined.
+               }
+       }
+
+       if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI)
+               ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
+
+       pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
+       // 2. Always send back ADDBA Response
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if (NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n"));
+               return;
+       }
+
+       NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP));
+       // 2-1. Prepare ADDBA Response frame.
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               if (ADHOC_ON(pAd))
+                       ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+               else
+#ifdef QOS_DLS_SUPPORT
+               if (pAd->MacTab.Content[Elem->Wcid].ValidAsDls)
+                       ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+               else
+#endif // QOS_DLS_SUPPORT //
+                       ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
+       }
+#endif // CONFIG_STA_SUPPORT //
+       ADDframe.Category = CATEGORY_BA;
+       ADDframe.Action = ADDBA_RESP;
+       ADDframe.Token = pAddreqFrame->Token;
+       // What is the Status code??  need to check.
+       ADDframe.StatusCode = Status;
+       ADDframe.BaParm.BAPolicy = IMMED_BA;
+       ADDframe.BaParm.AMSDUSupported = 0;
+       ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID;
+       ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
+       if (ADDframe.BaParm.BufSize == 0)
+       {
+               ADDframe.BaParm.BufSize = 64;
+       }
+       ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue;
+
+       *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm));
+       ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
+       ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
+
+       MakeOutgoingFrame(pOutBuffer,               &FrameLen,
+                                         sizeof(FRAME_ADDBA_RSP),  &ADDframe,
+                         END_OF_ARGS);
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID,
+                                                         ADDframe.BaParm.BufSize));
+}
+
+
+VOID PeerAddBARspAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+
+{
+       //UCHAR         Idx, i;
+       //PUCHAR                   pOutBuffer = NULL;
+       PFRAME_ADDBA_RSP    pFrame = NULL;
+       //PBA_ORI_ENTRY         pBAEntry;
+
+       //ADDBA Response from unknown peer, ignore this.
+       if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+               return;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid));
+
+       //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);
+
+       if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen))
+       {
+               pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]);
+
+               DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode));
+               switch (pFrame->StatusCode)
+               {
+                       case 0:
+                               // I want a BAsession with this peer as an originator.
+                               BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame);
+                               break;
+                       default:
+                               // check status == USED ???
+                               BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE);
+                               break;
+               }
+               // Rcv Decline StatusCode
+               if ((pFrame->StatusCode == 37)
+#ifdef CONFIG_STA_SUPPORT
+            || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0))
+#endif // CONFIG_STA_SUPPORT //
+            )
+               {
+                       pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID;
+               }
+       }
+}
+
+VOID PeerDelBAAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+
+{
+       //UCHAR                         Idx;
+       //PUCHAR                                pOutBuffer = NULL;
+       PFRAME_DELBA_REQ    pDelFrame = NULL;
+
+       DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__));
+       //DELBA Request from unknown peer, ignore this.
+       if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen))
+       {
+               pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]);
+               if (pDelFrame->DelbaParm.Initiator == ORIGINATOR)
+               {
+                       DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n"));
+                       BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE);
+               }
+               else
+               {
+                       DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n",  pDelFrame->ReasonCode));
+                       //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);
+                       BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE);
+               }
+       }
+}
+
+
+BOOLEAN CntlEnqueueForRecv(
+                                                 IN PRTMP_ADAPTER              pAd,
+                                                 IN ULONG                              Wcid,
+                                                 IN ULONG                              MsgLen,
+                                                 IN PFRAME_BA_REQ              pMsg)
+{
+       PFRAME_BA_REQ   pFrame = pMsg;
+       //PRTMP_REORDERBUF      pBuffer;
+       //PRTMP_REORDERBUF      pDmaBuf;
+       PBA_REC_ENTRY pBAEntry;
+       //BOOLEAN       Result;
+       ULONG   Idx;
+       //UCHAR NumRxPkt;
+       UCHAR   TID;//, i;
+
+       TID = (UCHAR)pFrame->BARControl.TID;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID));
+       //hex_dump("BAR", (PCHAR) pFrame, MsgLen);
+       // Do nothing if the driver is starting halt state.
+       // This might happen when timer already been fired before cancel timer with mlmehalt
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+               return FALSE;
+
+       // First check the size, it MUST not exceed the mlme queue size
+       if (MsgLen > MGMT_DMA_BUFFER_SIZE)
+       {
+               DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
+               return FALSE;
+       }
+       else if (MsgLen != sizeof(FRAME_BA_REQ))
+       {
+               DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
+               return FALSE;
+       }
+       else if (MsgLen != sizeof(FRAME_BA_REQ))
+       {
+               DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
+               return FALSE;
+       }
+
+       if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8))
+               {
+               // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.
+               Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+               pBAEntry = &pAd->BATable.BARecEntry[Idx];
+               }
+               else
+               {
+               return FALSE;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq ));
+
+       if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ))
+       {
+               //printk("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq);
+               ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq);
+               pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1);
+       }
+       //ba_refresh_reordering_mpdus(pAd, pBAEntry);
+       return TRUE;
+}
+
+/*
+Description : Send PSMP Action frame If PSMP mode switches.
+*/
+VOID SendPSMPAction(
+                                  IN PRTMP_ADAPTER             pAd,
+                                  IN UCHAR                             Wcid,
+                                  IN UCHAR                             Psmp)
+{
+       PUCHAR          pOutBuffer = NULL;
+       NDIS_STATUS     NStatus;
+       //ULONG           Idx;
+       FRAME_PSMP_ACTION   Frame;
+       ULONG           FrameLen;
+
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if (NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
+               return;
+       }
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
+#endif // CONFIG_STA_SUPPORT //
+
+       Frame.Category = CATEGORY_HT;
+       Frame.Action = SMPS_ACTION;
+       switch (Psmp)
+       {
+               case MMPS_ENABLE:
+                       Frame.Psmp = 0;
+                       break;
+               case MMPS_DYNAMIC:
+                       Frame.Psmp = 3;
+                       break;
+               case MMPS_STATIC:
+                       Frame.Psmp = 1;
+                       break;
+       }
+       MakeOutgoingFrame(pOutBuffer,               &FrameLen,
+                                         sizeof(FRAME_PSMP_ACTION),      &Frame,
+                                         END_OF_ARGS);
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+       DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d )  \n", Frame.Psmp));
+}
+
+
+#define RADIO_MEASUREMENT_REQUEST_ACTION       0
+
+typedef struct PACKED
+{
+       UCHAR   RegulatoryClass;
+       UCHAR   ChannelNumber;
+       USHORT  RandomInterval;
+       USHORT  MeasurementDuration;
+       UCHAR   MeasurementMode;
+       UCHAR   BSSID[MAC_ADDR_LEN];
+       UCHAR   ReportingCondition;
+       UCHAR   Threshold;
+       UCHAR   SSIDIE[2];                      // 2 byte
+} BEACON_REQUEST;
+
+typedef struct PACKED
+{
+       UCHAR   ID;
+       UCHAR   Length;
+       UCHAR   Token;
+       UCHAR   RequestMode;
+       UCHAR   Type;
+} MEASUREMENT_REQ;
+
+
+
+
+void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN  UCHAR                       FromWhichBSSID)
+{
+       PNDIS_PACKET    pRxPkt;
+       UCHAR                   Header802_3[LENGTH_802_3];
+
+       // 1. get 802.3 Header
+       // 2. remove LLC
+       //              a. pointer pRxBlk->pData to payload
+       //      b. modify pRxBlk->DataSize
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
+#endif // CONFIG_STA_SUPPORT //
+
+       ASSERT(pRxBlk->pRxPacket);
+       pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
+
+       RTPKT_TO_OSPKT(pRxPkt)->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+       RTPKT_TO_OSPKT(pRxPkt)->data = pRxBlk->pData;
+       RTPKT_TO_OSPKT(pRxPkt)->len = pRxBlk->DataSize;
+       RTPKT_TO_OSPKT(pRxPkt)->tail = RTPKT_TO_OSPKT(pRxPkt)->data + RTPKT_TO_OSPKT(pRxPkt)->len;
+
+       //
+       // copy 802.3 header, if necessary
+       //
+       if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
+       {
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+#ifdef LINUX
+                       NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
+#endif
+#ifdef UCOS
+                       NdisMoveMemory(net_pkt_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
+#endif
+               }
+#endif // CONFIG_STA_SUPPORT //
+       }
+}
+
+
+#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID)               \
+       do                                                                                                                                      \
+       {                                                                                                                                       \
+       if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU))                                               \
+       {                                                                                                                               \
+               Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID);          \
+       }                                                                                                                               \
+               else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP))                                    \
+               {                                                                                                                               \
+                       Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID);          \
+               }                                                                                                                               \
+       else                                                                                                                    \
+       {                                                                                                                               \
+               Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID);         \
+       }                                                                                                                               \
+       } while (0);
+
+
+
+static VOID ba_enqueue_reordering_packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PBA_REC_ENTRY   pBAEntry,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID)
+{
+       struct reordering_mpdu *mpdu_blk;
+       UINT16  Sequence = (UINT16) pRxBlk->pHeader->Sequence;
+
+       mpdu_blk = ba_mpdu_blk_alloc(pAd);
+       if (mpdu_blk != NULL)
+       {
+               // Write RxD buffer address & allocated buffer length
+               NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+
+               mpdu_blk->Sequence = Sequence;
+
+               mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
+
+               convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
+
+               STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
+
+        //
+               // it is necessary for reordering packet to record
+               // which BSS it come from
+               //
+               RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
+
+               mpdu_blk->pPacket = pRxBlk->pRxPacket;
+
+               if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE)
+               {
+                       // had been already within reordering list
+                       // don't indicate
+                       RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS);
+                       ba_mpdu_blk_free(pAd, mpdu_blk);
+               }
+
+               ASSERT((0<= pBAEntry->list.qlen)  && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
+               NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+       }
+       else
+       {
+#if 0
+               DBGPRINT(RT_DEBUG_ERROR,  ("!!! (%d:%d) Can't allocate reordering mpdu blk\n",
+                                                                  blk_count, pBAEntry->list.qlen));
+#else
+               DBGPRINT(RT_DEBUG_ERROR,  ("!!! (%d) Can't allocate reordering mpdu blk\n",
+                                                                  pBAEntry->list.qlen));
+#endif
+               /*
+                * flush all pending reordering mpdus
+                * and receving mpdu to upper layer
+                * make tcp/ip to take care reordering mechanism
+                */
+               //ba_refresh_reordering_mpdus(pAd, pBAEntry);
+               ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
+
+               pBAEntry->LastIndSeq = Sequence;
+               INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+       }
+}
+
+
+/*
+       ==========================================================================
+       Description:
+               Indicate this packet to upper layer or put it into reordering buffer
+
+       Parametrs:
+               pRxBlk         : carry necessary packet info 802.11 format
+               FromWhichBSSID : the packet received from which BSS
+
+       Return  :
+                         none
+
+       Note    :
+                 the packet queued into reordering buffer need to cover to 802.3 format
+                         or pre_AMSDU format
+       ==========================================================================
+ */
+
+VOID Indicate_AMPDU_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID)
+{
+       USHORT                          Idx;
+       PBA_REC_ENTRY           pBAEntry = NULL;
+       UINT16                          Sequence = pRxBlk->pHeader->Sequence;
+       ULONG                           Now32;
+       UCHAR                           Wcid = pRxBlk->pRxWI->WirelessCliID;
+       UCHAR                           TID = pRxBlk->pRxWI->TID;
+
+
+       if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) &&  (pRxBlk->DataSize > MAX_RX_PKT_LEN))
+       {
+#if 0 // sample take off, no use
+               static int err_size;
+
+               err_size++;
+               if (err_size > 20) {
+                        printk("AMPDU DataSize = %d\n", pRxBlk->DataSize);
+                        hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24);
+                        hex_dump("Payload", pRxBlk->pData, 64);
+                        err_size = 0;
+               }
+#endif
+               // release packet
+               RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+               return;
+       }
+
+
+#if 0 // test
+       /* Rec BA Session had been torn down */
+       INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+       return;
+#endif
+
+       if (Wcid < MAX_LEN_OF_MAC_TABLE)
+       {
+               Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+               if (Idx == 0)
+               {
+                       /* Rec BA Session had been torn down */
+                       INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+                       return;
+               }
+               pBAEntry = &pAd->BATable.BARecEntry[Idx];
+       }
+       else
+       {
+               // impossible !!!
+               ASSERT(0);
+               // release packet
+               RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+               return;
+       }
+
+       ASSERT(pBAEntry);
+
+       // update last rx time
+       NdisGetSystemUpTime(&Now32);
+
+       pBAEntry->rcvSeq = Sequence;
+
+
+       ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
+       pBAEntry->LastIndSeqAtTimer = Now32;
+
+       //
+       // Reset Last Indicate Sequence
+       //
+       if (pBAEntry->LastIndSeq == RESET_RCV_SEQ)
+       {
+               ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL));
+
+               // reset rcv sequence of BA session
+               pBAEntry->LastIndSeq = Sequence;
+               pBAEntry->LastIndSeqAtTimer = Now32;
+               INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+               return;
+       }
+
+
+       //
+       // I. Check if in order.
+       //
+       if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
+       {
+               USHORT  LastIndSeq;
+
+               pBAEntry->LastIndSeq = Sequence;
+               INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+               LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
+               if (LastIndSeq != RESET_RCV_SEQ)
+               {
+                       pBAEntry->LastIndSeq = LastIndSeq;
+               }
+               pBAEntry->LastIndSeqAtTimer = Now32;
+       }
+       //
+       // II. Drop Duplicated Packet
+       //
+       else if (Sequence == pBAEntry->LastIndSeq)
+       {
+
+               // drop and release packet
+               pBAEntry->nDropPacket++;
+               RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+       }
+       //
+       // III. Drop Old Received Packet
+       //
+       else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
+       {
+
+               // drop and release packet
+               pBAEntry->nDropPacket++;
+               RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+       }
+       //
+       // IV. Receive Sequence within Window Size
+       //
+       else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ))
+       {
+               ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
+       }
+       //
+       // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer
+       //
+       else
+       {
+#if 0
+               ba_refresh_reordering_mpdus(pAd, pBAEntry);
+               INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+#else
+               LONG WinStartSeq, TmpSeq;
+
+
+               TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
+               if (TmpSeq < 0)
+               {
+                       TmpSeq = (MAXSEQ+1) + TmpSeq;
+               }
+               WinStartSeq = (TmpSeq+1) & MAXSEQ;
+               ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
+               pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq;
+
+               pBAEntry->LastIndSeqAtTimer = Now32;
+
+               ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
+
+               TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
+               if (TmpSeq != RESET_RCV_SEQ)
+               {
+                       pBAEntry->LastIndSeq = TmpSeq;
+               }
+#endif
+       }
+}
+
+#endif // DOT11_N_SUPPORT //
+
diff --git a/drivers/staging/rt2870/common/cmm_data.c b/drivers/staging/rt2870/common/cmm_data.c
new file mode 100644 (file)
index 0000000..4477a8e
--- /dev/null
@@ -0,0 +1,2734 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+*/
+
+#include "../rt_config.h"
+
+#define MAX_TX_IN_TBTT         (16)
+
+
+UCHAR  SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
+UCHAR  SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
+// Add Cisco Aironet SNAP heade for CCX2 support
+UCHAR  SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
+UCHAR  CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
+UCHAR  EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};
+UCHAR  EAPOL[] = {0x88, 0x8e};
+UCHAR   TPID[] = {0x81, 0x00}; /* VLAN related */
+
+UCHAR  IPX[] = {0x81, 0x37};
+UCHAR  APPLE_TALK[] = {0x80, 0xf3};
+UCHAR  RateIdToPlcpSignal[12] = {
+        0, /* RATE_1 */        1, /* RATE_2 */         2, /* RATE_5_5 */       3, /* RATE_11 */        // see BBP spec
+       11, /* RATE_6 */   15, /* RATE_9 */    10, /* RATE_12 */   14, /* RATE_18 */    // see IEEE802.11a-1999 p.14
+        9, /* RATE_24 */  13, /* RATE_36 */    8, /* RATE_48 */   12  /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
+
+UCHAR   OfdmSignalToRateId[16] = {
+       RATE_54,  RATE_54,      RATE_54,  RATE_54,      // OFDM PLCP Signal = 0,  1,  2,  3 respectively
+       RATE_54,  RATE_54,      RATE_54,  RATE_54,      // OFDM PLCP Signal = 4,  5,  6,  7 respectively
+       RATE_48,  RATE_24,      RATE_12,  RATE_6,       // OFDM PLCP Signal = 8,  9,  10, 11 respectively
+       RATE_54,  RATE_36,      RATE_18,  RATE_9,       // OFDM PLCP Signal = 12, 13, 14, 15 respectively
+};
+
+UCHAR   OfdmRateToRxwiMCS[12] = {
+       0,  0,  0,  0,
+       0,  1,  2,  3,  // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
+       4,  5,  6,  7,  // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
+};
+UCHAR   RxwiMCSToOfdmRate[12] = {
+       RATE_6,  RATE_9,        RATE_12,  RATE_18,
+       RATE_24,  RATE_36,      RATE_48,  RATE_54,      // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
+       4,  5,  6,  7,  // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
+};
+
+char*   MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"};
+
+UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
+//UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1};
+UCHAR default_sta_aifsn[]={3,7,2,2};
+
+UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               API for MLME to transmit management frame to AP (BSS Mode)
+       or station (IBSS Mode)
+
+       Arguments:
+               pAd Pointer to our adapter
+               pData           Pointer to the outgoing 802.11 frame
+               Length          Size of outgoing management frame
+
+       Return Value:
+               NDIS_STATUS_FAILURE
+               NDIS_STATUS_PENDING
+               NDIS_STATUS_SUCCESS
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+NDIS_STATUS MiniportMMRequest(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   QueIdx,
+       IN      PUCHAR                  pData,
+       IN      UINT                    Length)
+{
+       PNDIS_PACKET    pPacket;
+       NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
+       ULONG                   FreeNum;
+       UCHAR                   IrqState;
+       UCHAR                   rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
+
+       ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
+
+       QueIdx=3;
+
+       // 2860C use Tx Ring
+
+       IrqState = pAd->irq_disabled;
+
+       do
+       {
+               // Reset is in progress, stop immediately
+               if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
+                        RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
+                        !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
+               {
+                       Status = NDIS_STATUS_FAILURE;
+                       break;
+               }
+
+               // Check Free priority queue
+               // Since we use PBF Queue2 for management frame.  Its corresponding DMA ring should be using TxRing.
+
+               // 2860C use Tx Ring
+               if (pAd->MACVersion == 0x28600100)
+               {
+                       FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
+               }
+               else
+               {
+                       FreeNum = GET_MGMTRING_FREENO(pAd);
+               }
+
+               if ((FreeNum > 0))
+               {
+                       // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
+                       NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
+                       Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
+                       if (Status != NDIS_STATUS_SUCCESS)
+                       {
+                               DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
+                               break;
+                       }
+
+                       //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
+                       //pAd->CommonCfg.MlmeRate = RATE_2;
+
+
+                       Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
+                       if (Status != NDIS_STATUS_SUCCESS)
+                               RTMPFreeNdisPacket(pAd, pPacket);
+               }
+               else
+               {
+                       pAd->RalinkCounters.MgmtRingFullCount++;
+                       DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
+                                                                               QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
+               }
+
+       } while (FALSE);
+
+
+       return Status;
+}
+
+
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Copy frame from waiting queue into relative ring buffer and set
+       appropriate ASIC register to kick hardware transmit function
+
+       Arguments:
+               pAd Pointer to our adapter
+               pBuffer         Pointer to      memory of outgoing frame
+               Length          Size of outgoing management frame
+
+       Return Value:
+               NDIS_STATUS_FAILURE
+               NDIS_STATUS_PENDING
+               NDIS_STATUS_SUCCESS
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+NDIS_STATUS MlmeHardTransmit(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   QueIdx,
+       IN      PNDIS_PACKET    pPacket)
+{
+       if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
+#ifdef CARRIER_DETECTION_SUPPORT
+#endif // CARRIER_DETECTION_SUPPORT //
+               )
+       {
+               return NDIS_STATUS_FAILURE;
+       }
+
+               return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
+
+}
+
+
+
+NDIS_STATUS MlmeHardTransmitMgmtRing(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR   QueIdx,
+       IN      PNDIS_PACKET    pPacket)
+{
+       PACKET_INFO     PacketInfo;
+       PUCHAR                  pSrcBufVA;
+       UINT                    SrcBufLen;
+       PHEADER_802_11  pHeader_802_11;
+       BOOLEAN                 bAckRequired, bInsertTimestamp;
+       UCHAR                   MlmeRate;
+       PTXWI_STRUC     pFirstTxWI;
+       MAC_TABLE_ENTRY *pMacEntry = NULL;
+
+       RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+
+       // Make sure MGMT ring resource won't be used by other threads
+// sample, for IRQ LOCK -> SEM LOCK
+//     IrqState = pAd->irq_disabled;
+//     if (!IrqState)
+               RTMP_SEM_LOCK(&pAd->MgmtRingLock);
+
+
+       if (pSrcBufVA == NULL)
+       {
+               // The buffer shouldn't be NULL
+//             if (!IrqState)
+                       RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+               return NDIS_STATUS_FAILURE;
+       }
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // outgoing frame always wakeup PHY to prevent frame lost
+               if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+                       AsicForceWakeup(pAd, TRUE);
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA +  TXINFO_SIZE);
+       pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
+
+       if (pHeader_802_11->Addr1[0] & 0x01)
+       {
+               MlmeRate = pAd->CommonCfg.BasicMlmeRate;
+       }
+       else
+       {
+               MlmeRate = pAd->CommonCfg.MlmeRate;
+       }
+
+       // Verify Mlme rate for a / g bands.
+       if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
+               MlmeRate = RATE_6;
+
+       if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
+               (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
+       {
+               pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
+       }
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
+               if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
+#ifdef DOT11_N_SUPPORT
+                       || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
+#endif // DOT11_N_SUPPORT //
+               )
+               {
+                       if (pAd->LatchRfRegs.Channel > 14)
+                               pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
+                       else
+                               pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       //
+       // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
+       // Snice it's been set to 0 while on MgtMacHeaderInit
+       // By the way this will cause frame to be send on PWR_SAVE failed.
+       //
+       // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
+       //
+       // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
+#ifdef CONFIG_STA_SUPPORT
+    // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
+       if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
+       {
+               if ((pAd->StaCfg.Psm == PWR_SAVE) &&
+                       (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
+                       pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
+               else
+                       pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       bInsertTimestamp = FALSE;
+       if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
+       {
+#ifdef CONFIG_STA_SUPPORT
+               //Set PM bit in ps-poll, to fix WLK 1.2  PowerSaveMode_ext failure issue.
+               if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
+               {
+                       pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
+               }
+#endif // CONFIG_STA_SUPPORT //
+               bAckRequired = FALSE;
+       }
+       else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
+       {
+               //pAd->Sequence++;
+               //pHeader_802_11->Sequence = pAd->Sequence;
+
+               if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
+               {
+                       bAckRequired = FALSE;
+                       pHeader_802_11->Duration = 0;
+               }
+               else
+               {
+                       bAckRequired = TRUE;
+                       pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
+                       if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
+                       {
+                               bInsertTimestamp = TRUE;
+                       }
+               }
+       }
+
+       pHeader_802_11->Sequence = pAd->Sequence++;
+       if (pAd->Sequence >0xfff)
+               pAd->Sequence = 0;
+
+       // Before radar detection done, mgmt frame can not be sent but probe req
+       // Because we need to use probe req to trigger driver to send probe req in passive scan
+       if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
+               && (pAd->CommonCfg.bIEEE80211H == 1)
+               && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
+//             if (!IrqState)
+                       RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+               return (NDIS_STATUS_FAILURE);
+       }
+
+#ifdef RT_BIG_ENDIAN
+       RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
+#endif
+
+       //
+       // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
+       // should always has only one ohysical buffer, and the whole frame size equals
+       // to the first scatter buffer size
+       //
+
+       // Initialize TX Descriptor
+       // For inter-frame gap, the number is for this frame and next frame
+       // For MLME rate, we will fix as 2Mb to match other vendor's implement
+//     pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
+
+// management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
+       if (pMacEntry == NULL)
+       {
+               RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
+               0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0,  (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
+       }
+       else
+       {
+               RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
+                                       bInsertTimestamp, FALSE, bAckRequired, FALSE,
+                                       0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
+                                       pMacEntry->MaxHTPhyMode.field.MCS, 0,
+                                       (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
+                                       IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
+       }
+
+#ifdef RT_BIG_ENDIAN
+       RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
+#endif
+
+       // Now do hardware-depened kick out.
+       HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
+
+       // Make sure to release MGMT ring resource
+//     if (!IrqState)
+               RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+       return NDIS_STATUS_SUCCESS;
+}
+
+
+/********************************************************************************
+
+       New DeQueue Procedures.
+
+ ********************************************************************************/
+
+#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags)                              \
+                       do{                                                                                                     \
+                               if (bIntContext == FALSE)                                               \
+                               RTMP_IRQ_LOCK((lock), IrqFlags);                \
+                       }while(0)
+
+#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags)                            \
+                       do{                                                                                                     \
+                               if (bIntContext == FALSE)                                               \
+                                       RTMP_IRQ_UNLOCK((lock), IrqFlags);      \
+                       }while(0)
+
+
+#if 0
+static VOID dumpTxBlk(TX_BLK *pTxBlk)
+{
+       NDIS_PACKET *pPacket;
+       int i, frameNum;
+       PQUEUE_ENTRY    pQEntry;
+
+       printk("Dump TX_BLK Structure:\n");
+       printk("\tTxFrameType=%d!\n", pTxBlk->TxFrameType);
+       printk("\tTotalFrameLen=%d\n", pTxBlk->TotalFrameLen);
+       printk("\tTotalFrameNum=%ld!\n", pTxBlk->TxPacketList.Number);
+       printk("\tTotalFragNum=%d!\n", pTxBlk->TotalFragNum);
+       printk("\tpPacketList=\n");
+
+       frameNum = pTxBlk->TxPacketList.Number;
+
+       for(i=0; i < frameNum; i++)
+       {       int j;
+               UCHAR   *pBuf;
+
+               pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+               pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+               if (pPacket)
+               {
+                       pBuf = GET_OS_PKT_DATAPTR(pPacket);
+                       printk("\t\t[%d]:ptr=0x%x, Len=%d!\n", i, (UINT32)(GET_OS_PKT_DATAPTR(pPacket)), GET_OS_PKT_LEN(pPacket));
+                       printk("\t\t");
+                       for (j =0 ; j < GET_OS_PKT_LEN(pPacket); j++)
+                       {
+                               printk("%02x ", (pBuf[j] & 0xff));
+                               if (j == 16)
+                                       break;
+                       }
+                       InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
+               }
+       }
+       printk("\tWcid=%d!\n", pTxBlk->Wcid);
+       printk("\tapidx=%d!\n", pTxBlk->apidx);
+       printk("----EndOfDump\n");
+
+}
+#endif
+
+
+/*
+       ========================================================================
+       Tx Path design algorithm:
+               Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
+               Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
+                               Classification Rule=>
+                                       Multicast: (*addr1 & 0x01) == 0x01
+                                       Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
+                                       11N Rate : If peer support HT
+                                                               (1).AMPDU  -- If TXBA is negotiated.
+                                                               (2).AMSDU  -- If AMSDU is capable for both peer and ourself.
+                                                                                       *). AMSDU can embedded in a AMPDU, but now we didn't support it.
+                                                               (3).Normal -- Other packets which send as 11n rate.
+
+                                       B/G Rate : If peer is b/g only.
+                                                               (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
+                                                               (2).Normal -- Other packets which send as b/g rate.
+                                       Fragment:
+                                                               The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
+
+                               Classified Packet Handle Rule=>
+                                       Multicast:
+                                                               No ACK,                 //pTxBlk->bAckRequired = FALSE;
+                                                               No WMM,                 //pTxBlk->bWMM = FALSE;
+                                                               No piggyback,   //pTxBlk->bPiggyBack = FALSE;
+                                                               Force LowRate,  //pTxBlk->bForceLowRate = TRUE;
+                                       Specific :      Basically, for specific packet, we should handle it specifically, but now all specific packets are use
+                                                                       the same policy to handle it.
+                                                               Force LowRate,  //pTxBlk->bForceLowRate = TRUE;
+
+                                       11N Rate :
+                                                               No piggyback,   //pTxBlk->bPiggyBack = FALSE;
+
+                                                               (1).AMSDU
+                                                                       pTxBlk->bWMM = TRUE;
+                                                               (2).AMPDU
+                                                                       pTxBlk->bWMM = TRUE;
+                                                               (3).Normal
+
+                                       B/G Rate :
+                                                               (1).ARALINK
+
+                                                               (2).Normal
+       ========================================================================
+*/
+static UCHAR TxPktClassification(
+       IN RTMP_ADAPTER *pAd,
+       IN PNDIS_PACKET  pPacket)
+{
+       UCHAR                   TxFrameType = TX_UNKOWN_FRAME;
+       UCHAR                   Wcid;
+       MAC_TABLE_ENTRY *pMacEntry = NULL;
+#ifdef DOT11_N_SUPPORT
+       BOOLEAN                 bHTRate = FALSE;
+#endif // DOT11_N_SUPPORT //
+
+       Wcid = RTMP_GET_PACKET_WCID(pPacket);
+       if (Wcid == MCAST_WCID)
+       {       // Handle for RA is Broadcast/Multicast Address.
+               return TX_MCAST_FRAME;
+       }
+
+       // Handle for unicast packets
+       pMacEntry = &pAd->MacTab.Content[Wcid];
+       if (RTMP_GET_PACKET_LOWRATE(pPacket))
+       {       // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
+               TxFrameType = TX_LEGACY_FRAME;
+       }
+#ifdef DOT11_N_SUPPORT
+       else if (IS_HT_RATE(pMacEntry))
+       {       // it's a 11n capable packet
+
+               // Depends on HTPhyMode to check if the peer support the HTRate transmission.
+               //      Currently didn't support A-MSDU embedded in A-MPDU
+               bHTRate = TRUE;
+               if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
+                       TxFrameType = TX_LEGACY_FRAME;
+#ifdef UAPSD_AP_SUPPORT
+               else if (RTMP_GET_PACKET_EOSP(pPacket))
+                       TxFrameType = TX_LEGACY_FRAME;
+#endif // UAPSD_AP_SUPPORT //
+               else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
+                       return TX_AMPDU_FRAME;
+               else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
+                       return TX_AMSDU_FRAME;
+               else
+                       TxFrameType = TX_LEGACY_FRAME;
+       }
+#endif // DOT11_N_SUPPORT //
+       else
+       {       // it's a legacy b/g packet.
+               if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
+                       (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
+                       (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
+               {       // if peer support Ralink Aggregation, we use it.
+                       TxFrameType = TX_RALINK_FRAME;
+               }
+               else
+               {
+                       TxFrameType = TX_LEGACY_FRAME;
+               }
+       }
+
+       // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
+       if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
+               TxFrameType = TX_FRAG_FRAME;
+
+       return TxFrameType;
+}
+
+
+BOOLEAN RTMP_FillTxBlkInfo(
+       IN RTMP_ADAPTER *pAd,
+       IN TX_BLK *pTxBlk)
+{
+       PACKET_INFO                     PacketInfo;
+       PNDIS_PACKET            pPacket;
+       PMAC_TABLE_ENTRY        pMacEntry = NULL;
+
+       pPacket = pTxBlk->pPacket;
+       RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
+
+       pTxBlk->Wcid                            = RTMP_GET_PACKET_WCID(pPacket);
+       pTxBlk->apidx                           = RTMP_GET_PACKET_IF(pPacket);
+       pTxBlk->UserPriority            = RTMP_GET_PACKET_UP(pPacket);
+       pTxBlk->FrameGap = IFS_HTTXOP;          // ASIC determine Frame Gap
+
+       if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
+               TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
+       else
+               TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
+
+       // Default to clear this flag
+       TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
+
+
+       if (pTxBlk->Wcid == MCAST_WCID)
+       {
+               pTxBlk->pMacEntry = NULL;
+               {
+#ifdef MCAST_RATE_SPECIFIC
+                       PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
+                       if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
+                               pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
+                       else
+#endif // MCAST_RATE_SPECIFIC //
+                               pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
+               }
+
+               TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);    // AckRequired = FALSE, when broadcast packet in Adhoc mode.
+               //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
+               TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
+               TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
+               if (RTMP_GET_PACKET_MOREDATA(pPacket))
+               {
+                       TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
+               }
+
+       }
+       else
+       {
+               pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
+               pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
+
+               pMacEntry = pTxBlk->pMacEntry;
+
+
+               // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
+               if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
+                       TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
+               else
+                       TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
+
+               {
+
+#ifdef CONFIG_STA_SUPPORT
+                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       {
+
+                               // If support WMM, enable it.
+                               if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
+                                       CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
+                                       TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
+                       }
+#endif // CONFIG_STA_SUPPORT //
+               }
+
+               if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
+               {
+                       if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
+                ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
+                       {       // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
+                               pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
+#ifdef DOT11_N_SUPPORT
+                               // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
+                               if (IS_HT_STA(pTxBlk->pMacEntry) &&
+                                       (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
+                                       ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
+                               {
+                                       TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
+                                       TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
+                               }
+#endif // DOT11_N_SUPPORT //
+                       }
+
+#ifdef DOT11_N_SUPPORT
+                       if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
+                               (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
+                       {       // Currently piggy-back only support when peer is operate in b/g mode.
+                               TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
+                       }
+#endif // DOT11_N_SUPPORT //
+
+                       if (RTMP_GET_PACKET_MOREDATA(pPacket))
+                       {
+                               TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
+                       }
+#ifdef UAPSD_AP_SUPPORT
+                       if (RTMP_GET_PACKET_EOSP(pPacket))
+                       {
+                               TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
+                       }
+#endif // UAPSD_AP_SUPPORT //
+               }
+               else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
+               {
+                       TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
+               }
+
+               pMacEntry->DebugTxCount++;
+       }
+
+       return TRUE;
+
+FillTxBlkErr:
+       return FALSE;
+}
+
+
+BOOLEAN CanDoAggregateTransmit(
+       IN RTMP_ADAPTER *pAd,
+       IN NDIS_PACKET *pPacket,
+       IN TX_BLK               *pTxBlk)
+{
+
+       //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
+
+       if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
+               return FALSE;
+
+       if (RTMP_GET_PACKET_DHCP(pPacket) ||
+               RTMP_GET_PACKET_EAPOL(pPacket) ||
+               RTMP_GET_PACKET_WAI(pPacket))
+               return FALSE;
+
+       if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
+               ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
+       {       // For AMSDU, allow the packets with total length < max-amsdu size
+               return FALSE;
+       }
+
+       if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
+               (pTxBlk->TxPacketList.Number == 2))
+       {       // For RALINK-Aggregation, allow two frames in one batch.
+               return FALSE;
+       }
+
+#ifdef CONFIG_STA_SUPPORT
+       if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
+               return TRUE;
+       else
+#endif // CONFIG_STA_SUPPORT //
+               return FALSE;
+
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               To do the enqueue operation and extract the first item of waiting
+               list. If a number of available shared memory segments could meet
+               the request of extracted item, the extracted item will be fragmented
+               into shared memory segments.
+
+       Arguments:
+               pAd Pointer to our adapter
+               pQueue          Pointer to Waiting Queue
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID RTMPDeQueuePacket(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  BOOLEAN         bIntContext,
+       IN  UCHAR                       QIdx, /* BulkOutPipeId */
+       IN  UCHAR           Max_Tx_Packets)
+{
+       PQUEUE_ENTRY    pEntry = NULL;
+       PNDIS_PACKET    pPacket;
+       NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
+       UCHAR           Count=0;
+       PQUEUE_HEADER   pQueue;
+       ULONG           FreeNumber[NUM_OF_TX_RING];
+       UCHAR                   QueIdx, sQIdx, eQIdx;
+       unsigned long   IrqFlags = 0;
+       BOOLEAN                 hasTxDesc = FALSE;
+       TX_BLK                  TxBlk;
+       TX_BLK                  *pTxBlk;
+
+#ifdef DBG_DIAGNOSE
+       BOOLEAN                 firstRound;
+       RtmpDiagStruct  *pDiagStruct = &pAd->DiagStruct;
+#endif
+
+
+       if (QIdx == NUM_OF_TX_RING)
+       {
+               sQIdx = 0;
+               eQIdx = 3;      // 4 ACs, start from 0.
+       }
+       else
+       {
+               sQIdx = eQIdx = QIdx;
+       }
+
+       for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
+       {
+               Count=0;
+
+               RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
+
+#ifdef DBG_DIAGNOSE
+               firstRound = ((QueIdx == 0) ? TRUE : FALSE);
+#endif // DBG_DIAGNOSE //
+
+               while (1)
+               {
+                       if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
+                                                                               fRTMP_ADAPTER_RADIO_OFF |
+                                                                               fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                                               fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                                               fRTMP_ADAPTER_NIC_NOT_EXIST))))
+                       {
+                               RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
+                               return;
+                       }
+
+                       if (Count >= Max_Tx_Packets)
+                               break;
+
+                       DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+                       if (&pAd->TxSwQueue[QueIdx] == NULL)
+                       {
+#ifdef DBG_DIAGNOSE
+                               if (firstRound == TRUE)
+                                       pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
+#endif // DBG_DIAGNOSE //
+                               DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+                               break;
+                       }
+
+
+                       // probe the Queue Head
+                       pQueue = &pAd->TxSwQueue[QueIdx];
+                       if ((pEntry = pQueue->Head) == NULL)
+                       {
+                               DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+                               break;
+                       }
+
+                       pTxBlk = &TxBlk;
+                       NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
+                       //InitializeQueueHeader(&pTxBlk->TxPacketList);         // Didn't need it because we already memzero it.
+                       pTxBlk->QueIdx = QueIdx;
+
+                       pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
+
+                       // Early check to make sure we have enoguh Tx Resource.
+                       hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
+                       if (!hasTxDesc)
+                       {
+                               pAd->PrivateInfo.TxRingFullCnt++;
+
+                               DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+
+                               break;
+                       }
+
+                       pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
+                       pEntry = RemoveHeadQueue(pQueue);
+                       pTxBlk->TotalFrameNum++;
+                       pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);     // The real fragment number maybe vary
+                       pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
+                       pTxBlk->pPacket = pPacket;
+                       InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
+
+                       if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
+                       {
+                               // Enhance SW Aggregation Mechanism
+                               if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
+                               {
+                                       InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
+                                       DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+                                       break;
+                               }
+
+                               do{
+                                       if((pEntry = pQueue->Head) == NULL)
+                                               break;
+
+                                       // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
+                                       pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
+                                       FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
+                                       hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
+                                       if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
+                                               break;
+
+                                       //Remove the packet from the TxSwQueue and insert into pTxBlk
+                                       pEntry = RemoveHeadQueue(pQueue);
+                                       ASSERT(pEntry);
+                                       pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
+                                       pTxBlk->TotalFrameNum++;
+                                       pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);     // The real fragment number maybe vary
+                                       pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
+                                       InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
+                               }while(1);
+
+                               if (pTxBlk->TxPacketList.Number == 1)
+                                       pTxBlk->TxFrameType = TX_LEGACY_FRAME;
+                       }
+
+#ifdef RT2870
+                       DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+#endif // RT2870 //
+
+                       Count += pTxBlk->TxPacketList.Number;
+
+                               // Do HardTransmit now.
+#ifdef CONFIG_STA_SUPPORT
+                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
+#endif // CONFIG_STA_SUPPORT //
+
+
+#if 0  // We should not break if HardTransmit failed. Well, at least now we should not!
+                       if (Status != NDIS_STATUS_SUCCESS)
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE /*RT_DEBUG_INFO*/,("RTMPHardTransmit return failed!!!\n"));
+                               break;
+                       }
+#endif
+               }
+
+               RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
+
+#ifdef RT2870
+               if (!hasTxDesc)
+                       RTUSBKickBulkOut(pAd);
+#endif // RT2870 //
+
+#ifdef BLOCK_NET_IF
+               if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE)
+                       && (pAd->TxSwQueue[QueIdx].Number < 1))
+               {
+                       releaseNetIf(&pAd->blockQueueTab[QueIdx]);
+               }
+#endif // BLOCK_NET_IF //
+
+       }
+
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Calculates the duration which is required to transmit out frames
+       with given size and specified rate.
+
+       Arguments:
+               pAd     Pointer to our adapter
+               Rate                    Transmit rate
+               Size                    Frame size in units of byte
+
+       Return Value:
+               Duration number in units of usec
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+USHORT RTMPCalcDuration(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Rate,
+       IN      ULONG                   Size)
+{
+       ULONG   Duration = 0;
+
+       if (Rate < RATE_FIRST_OFDM_RATE) // CCK
+       {
+               if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
+                       Duration = 96;  // 72+24 preamble+plcp
+               else
+                       Duration = 192; // 144+48 preamble+plcp
+
+               Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
+               if ((Size << 4) % RateIdTo500Kbps[Rate])
+                       Duration ++;
+       }
+       else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
+       {
+               Duration = 20 + 6;              // 16+4 preamble+plcp + Signal Extension
+               Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
+               if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
+                       Duration += 4;
+       }
+       else    //mimo rate
+       {
+               Duration = 20 + 6;              // 16+4 preamble+plcp + Signal Extension
+       }
+
+       return (USHORT)Duration;
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Calculates the duration which is required to transmit out frames
+       with given size and specified rate.
+
+       Arguments:
+               pTxWI           Pointer to head of each MPDU to HW.
+               Ack             Setting for Ack requirement bit
+               Fragment        Setting for Fragment bit
+               RetryMode       Setting for retry mode
+               Ifs             Setting for IFS gap
+               Rate            Setting for transmit rate
+               Service         Setting for service
+               Length          Frame length
+               TxPreamble      Short or Long preamble when using CCK rates
+               QueIdx - 0-3, according to 802.11e/d4.4 June/2003
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+    See also : BASmartHardTransmit()    !!!
+
+       ========================================================================
+*/
+VOID RTMPWriteTxWI(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTXWI_STRUC     pOutTxWI,
+       IN      BOOLEAN                 FRAG,
+       IN      BOOLEAN                 CFACK,
+       IN      BOOLEAN                 InsTimestamp,
+       IN      BOOLEAN                 AMPDU,
+       IN      BOOLEAN                 Ack,
+       IN      BOOLEAN                 NSeq,           // HW new a sequence.
+       IN      UCHAR                   BASize,
+       IN      UCHAR                   WCID,
+       IN      ULONG                   Length,
+       IN      UCHAR                   PID,
+       IN      UCHAR                   TID,
+       IN      UCHAR                   TxRate,
+       IN      UCHAR                   Txopmode,
+       IN      BOOLEAN                 CfAck,
+       IN      HTTRANSMIT_SETTING      *pTransmit)
+{
+       PMAC_TABLE_ENTRY        pMac = NULL;
+       TXWI_STRUC              TxWI;
+       PTXWI_STRUC     pTxWI;
+
+       if (WCID < MAX_LEN_OF_MAC_TABLE)
+               pMac = &pAd->MacTab.Content[WCID];
+
+       //
+       // Always use Long preamble before verifiation short preamble functionality works well.
+       // Todo: remove the following line if short preamble functionality works
+       //
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+       NdisZeroMemory(&TxWI, TXWI_SIZE);
+       pTxWI = &TxWI;
+
+       pTxWI->FRAG= FRAG;
+
+       pTxWI->CFACK = CFACK;
+       pTxWI->TS= InsTimestamp;
+       pTxWI->AMPDU = AMPDU;
+       pTxWI->ACK = Ack;
+       pTxWI->txop= Txopmode;
+
+       pTxWI->NSEQ = NSeq;
+       // John tune the performace with Intel Client in 20 MHz performance
+#ifdef DOT11_N_SUPPORT
+       BASize = pAd->CommonCfg.TxBASize;
+
+       if( BASize >7 )
+               BASize =7;
+       pTxWI->BAWinSize = BASize;
+       pTxWI->ShortGI = pTransmit->field.ShortGI;
+       pTxWI->STBC = pTransmit->field.STBC;
+#endif // DOT11_N_SUPPORT //
+
+       pTxWI->WirelessCliID = WCID;
+       pTxWI->MPDUtotalByteCount = Length;
+       pTxWI->PacketId = PID;
+
+       // If CCK or OFDM, BW must be 20
+       pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
+#ifdef DOT11N_DRAFT3
+       if (pTxWI->BW)
+               pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
+#endif // DOT11N_DRAFT3 //
+
+       pTxWI->MCS = pTransmit->field.MCS;
+       pTxWI->PHYMODE = pTransmit->field.MODE;
+       pTxWI->CFACK = CfAck;
+
+#ifdef DOT11_N_SUPPORT
+       if (pMac)
+       {
+               if (pAd->CommonCfg.bMIMOPSEnable)
+               {
+                       if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
+                       {
+                               // Dynamic MIMO Power Save Mode
+                               pTxWI->MIMOps = 1;
+                       }
+                       else if (pMac->MmpsMode == MMPS_STATIC)
+                       {
+                               // Static MIMO Power Save Mode
+                               if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
+                               {
+                                       pTxWI->MCS = 7;
+                                       pTxWI->MIMOps = 0;
+                               }
+                       }
+               }
+               //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
+               if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
+               {
+                       pTxWI->MpduDensity = 7;
+               }
+               else
+               {
+                       pTxWI->MpduDensity = pMac->MpduDensity;
+               }
+       }
+#endif // DOT11_N_SUPPORT //
+
+       pTxWI->PacketId = pTxWI->MCS;
+       NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
+}
+
+
+VOID RTMPWriteTxWI_Data(
+       IN      PRTMP_ADAPTER           pAd,
+       IN      OUT PTXWI_STRUC         pTxWI,
+       IN      TX_BLK                          *pTxBlk)
+{
+       HTTRANSMIT_SETTING      *pTransmit;
+       PMAC_TABLE_ENTRY        pMacEntry;
+#ifdef DOT11_N_SUPPORT
+       UCHAR                           BASize;
+#endif // DOT11_N_SUPPORT //
+
+
+       ASSERT(pTxWI);
+
+       pTransmit = pTxBlk->pTransmit;
+       pMacEntry = pTxBlk->pMacEntry;
+
+
+       //
+       // Always use Long preamble before verifiation short preamble functionality works well.
+       // Todo: remove the following line if short preamble functionality works
+       //
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+       NdisZeroMemory(pTxWI, TXWI_SIZE);
+
+       pTxWI->FRAG             = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
+       pTxWI->ACK              = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
+       pTxWI->txop             = pTxBlk->FrameGap;
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+       if (pMacEntry &&
+               (pAd->StaCfg.BssType == BSS_INFRA) &&
+               (pMacEntry->ValidAsDls == TRUE))
+               pTxWI->WirelessCliID = BSSID_WCID;
+       else
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+               pTxWI->WirelessCliID            = pTxBlk->Wcid;
+
+       pTxWI->MPDUtotalByteCount       = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
+       pTxWI->CFACK                            = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
+
+       // If CCK or OFDM, BW must be 20
+       pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+       if (pTxWI->BW)
+               pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
+#endif // DOT11N_DRAFT3 //
+       pTxWI->AMPDU    = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
+
+       // John tune the performace with Intel Client in 20 MHz performance
+       BASize = pAd->CommonCfg.TxBASize;
+       if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
+       {
+               UCHAR           RABAOriIdx = 0; //The RA's BA Originator table index.
+
+               RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
+               BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
+       }
+
+#if 0 // 3*3
+       if (BASize > 7)
+               BASize = 7;
+#endif
+
+       pTxWI->TxBF = pTransmit->field.TxBF;
+       pTxWI->BAWinSize = BASize;
+       pTxWI->ShortGI = pTransmit->field.ShortGI;
+       pTxWI->STBC = pTransmit->field.STBC;
+#endif // DOT11_N_SUPPORT //
+
+       pTxWI->MCS = pTransmit->field.MCS;
+       pTxWI->PHYMODE = pTransmit->field.MODE;
+
+#ifdef DOT11_N_SUPPORT
+       if (pMacEntry)
+       {
+               if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
+               {
+                       // Dynamic MIMO Power Save Mode
+                       pTxWI->MIMOps = 1;
+               }
+               else if (pMacEntry->MmpsMode == MMPS_STATIC)
+               {
+                       // Static MIMO Power Save Mode
+                       if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
+                       {
+                               pTxWI->MCS = 7;
+                               pTxWI->MIMOps = 0;
+                       }
+               }
+
+               if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
+               {
+                       pTxWI->MpduDensity = 7;
+               }
+               else
+               {
+                       pTxWI->MpduDensity = pMacEntry->MpduDensity;
+               }
+       }
+#endif // DOT11_N_SUPPORT //
+
+#ifdef DBG_DIAGNOSE
+               if (pTxBlk->QueIdx== 0)
+               {
+                       pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
+                       pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
+               }
+#endif // DBG_DIAGNOSE //
+
+       // for rate adapation
+       pTxWI->PacketId = pTxWI->MCS;
+}
+
+
+VOID RTMPWriteTxWI_Cache(
+       IN      PRTMP_ADAPTER           pAd,
+       IN      OUT PTXWI_STRUC         pTxWI,
+       IN      TX_BLK                          *pTxBlk)
+{
+       PHTTRANSMIT_SETTING     /*pTxHTPhyMode,*/ pTransmit;
+       PMAC_TABLE_ENTRY        pMacEntry;
+
+       //
+       // update TXWI
+       //
+       pMacEntry = pTxBlk->pMacEntry;
+       pTransmit = pTxBlk->pTransmit;
+
+       if (pMacEntry->bAutoTxRateSwitch)
+       {
+               pTxWI->txop = IFS_HTTXOP;
+
+               // If CCK or OFDM, BW must be 20
+               pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
+               pTxWI->ShortGI = pTransmit->field.ShortGI;
+               pTxWI->STBC = pTransmit->field.STBC;
+
+               pTxWI->MCS = pTransmit->field.MCS;
+               pTxWI->PHYMODE = pTransmit->field.MODE;
+
+               // set PID for TxRateSwitching
+               pTxWI->PacketId = pTransmit->field.MCS;
+       }
+
+#ifdef DOT11_N_SUPPORT
+       pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
+       pTxWI->MIMOps = 0;
+
+#ifdef DOT11N_DRAFT3
+       if (pTxWI->BW)
+               pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
+#endif // DOT11N_DRAFT3 //
+
+       if (pAd->CommonCfg.bMIMOPSEnable)
+       {
+               // MIMO Power Save Mode
+               if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
+               {
+                       // Dynamic MIMO Power Save Mode
+                       pTxWI->MIMOps = 1;
+               }
+               else if (pMacEntry->MmpsMode == MMPS_STATIC)
+               {
+                       // Static MIMO Power Save Mode
+                       if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
+                       {
+                               pTxWI->MCS = 7;
+                               pTxWI->MIMOps = 0;
+                       }
+               }
+       }
+#endif // DOT11_N_SUPPORT //
+
+#ifdef DBG_DIAGNOSE
+       if (pTxBlk->QueIdx== 0)
+       {
+               pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
+               pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
+       }
+#endif // DBG_DIAGNOSE //
+
+       pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
+
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Calculates the duration which is required to transmit out frames
+       with given size and specified rate.
+
+       Arguments:
+               pTxD            Pointer to transmit descriptor
+               Ack             Setting for Ack requirement bit
+               Fragment        Setting for Fragment bit
+               RetryMode       Setting for retry mode
+               Ifs             Setting for IFS gap
+               Rate            Setting for transmit rate
+               Service         Setting for service
+               Length          Frame length
+               TxPreamble      Short or Long preamble when using CCK rates
+               QueIdx - 0-3, according to 802.11e/d4.4 June/2003
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       ========================================================================
+*/
+VOID RTMPWriteTxDescriptor(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTXD_STRUC              pTxD,
+       IN      BOOLEAN                 bWIV,
+       IN      UCHAR                   QueueSEL)
+{
+       //
+       // Always use Long preamble before verifiation short preamble functionality works well.
+       // Todo: remove the following line if short preamble functionality works
+       //
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+
+       pTxD->WIV       = (bWIV) ? 1: 0;
+       pTxD->QSEL= (QueueSEL);
+       //RT2860c??  fixed using EDCA queue for test...  We doubt Queue1 has problem.  2006-09-26 Jan
+       //pTxD->QSEL= FIFO_EDCA;
+       if (pAd->bGenOneHCCA == TRUE)
+               pTxD->QSEL= FIFO_HCCA;
+       pTxD->DMADONE = 0;
+}
+
+
+// should be called only when -
+// 1. MEADIA_CONNECTED
+// 2. AGGREGATION_IN_USED
+// 3. Fragmentation not in used
+// 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
+BOOLEAN TxFrameIsAggregatible(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pPrevAddr1,
+       IN      PUCHAR                  p8023hdr)
+{
+
+       // can't aggregate EAPOL (802.1x) frame
+       if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
+               return FALSE;
+
+       // can't aggregate multicast/broadcast frame
+       if (p8023hdr[0] & 0x01)
+               return FALSE;
+
+       if (INFRA_ON(pAd)) // must be unicast to AP
+               return TRUE;
+       else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
+               return TRUE;
+       else
+               return FALSE;
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+          Check the MSDU Aggregation policy
+       1.HT aggregation is A-MSDU
+       2.legaacy rate aggregation is software aggregation by Ralink.
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+BOOLEAN PeerIsAggreOn(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      ULONG              TxRate,
+       IN      PMAC_TABLE_ENTRY pMacEntry)
+{
+       ULONG   AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
+
+       if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
+       {
+#ifdef DOT11_N_SUPPORT
+               if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
+               {
+                       return TRUE;
+               }
+#endif // DOT11_N_SUPPORT //
+
+#ifdef AGGREGATION_SUPPORT
+               if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
+               {       // legacy  Ralink Aggregation support
+                       return TRUE;
+               }
+#endif // AGGREGATION_SUPPORT //
+       }
+
+       return FALSE;
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Check and fine the packet waiting in SW queue with highest priority
+
+       Arguments:
+               pAd Pointer to our adapter
+
+       Return Value:
+               pQueue          Pointer to Waiting Queue
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+PQUEUE_HEADER  RTMPCheckTxSwQueue(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT PUCHAR                      pQueIdx)
+{
+
+       ULONG   Number;
+       // 2004-11-15 to be removed. test aggregation only
+//     if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
+//              return NULL;
+
+       Number = pAd->TxSwQueue[QID_AC_BK].Number
+                        + pAd->TxSwQueue[QID_AC_BE].Number
+                        + pAd->TxSwQueue[QID_AC_VI].Number
+                        + pAd->TxSwQueue[QID_AC_VO].Number
+                        + pAd->TxSwQueue[QID_HCCA].Number;
+
+       if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
+       {
+               *pQueIdx = QID_AC_VO;
+               return (&pAd->TxSwQueue[QID_AC_VO]);
+       }
+       else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
+       {
+               *pQueIdx = QID_AC_VI;
+               return (&pAd->TxSwQueue[QID_AC_VI]);
+       }
+       else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
+       {
+               *pQueIdx = QID_AC_BE;
+               return (&pAd->TxSwQueue[QID_AC_BE]);
+       }
+       else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
+       {
+               *pQueIdx = QID_AC_BK;
+               return (&pAd->TxSwQueue[QID_AC_BK]);
+       }
+       else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
+       {
+               *pQueIdx = QID_HCCA;
+               return (&pAd->TxSwQueue[QID_HCCA]);
+       }
+
+       // No packet pending in Tx Sw queue
+       *pQueIdx = QID_AC_BK;
+
+       return (NULL);
+}
+
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Suspend MSDU transmission
+
+       Arguments:
+               pAd     Pointer to our adapter
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPSuspendMsduTransmission(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
+
+
+       //
+       // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
+       // use Lowbound as R66 value on ScanNextChannel(...)
+       //
+       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
+
+       // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
+       //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
+       RTMPSetAGCInitValue(pAd, BW_20);
+
+       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+       //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000);                // abort all TX rings
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Resume MSDU transmission
+
+       Arguments:
+               pAd     Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID RTMPResumeMsduTransmission(
+       IN      PRTMP_ADAPTER   pAd)
+{
+//    UCHAR                    IrqState;
+
+       DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
+
+
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
+
+       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+// sample, for IRQ LOCK to SEM LOCK
+//    IrqState = pAd->irq_disabled;
+//     if (IrqState)
+//             RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+//    else
+       RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+}
+
+
+UINT deaggregate_AMSDU_announce(
+       IN      PRTMP_ADAPTER   pAd,
+       PNDIS_PACKET            pPacket,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize)
+{
+       USHORT                  PayloadSize;
+       USHORT                  SubFrameSize;
+       PHEADER_802_3   pAMSDUsubheader;
+       UINT                    nMSDU;
+    UCHAR                      Header802_3[14];
+
+       PUCHAR                  pPayload, pDA, pSA, pRemovedLLCSNAP;
+       PNDIS_PACKET    pClonePacket;
+
+
+
+       nMSDU = 0;
+
+       while (DataSize > LENGTH_802_3)
+       {
+
+               nMSDU++;
+
+               //hex_dump("subheader", pData, 64);
+               pAMSDUsubheader = (PHEADER_802_3)pData;
+               //pData += LENGTH_802_3;
+               PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
+               SubFrameSize = PayloadSize + LENGTH_802_3;
+
+
+               if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
+               {
+                       break;
+               }
+
+               //printk("%d subframe: Size = %d\n",  nMSDU, PayloadSize);
+
+               pPayload = pData + LENGTH_802_3;
+               pDA = pData;
+               pSA = pData + MAC_ADDR_LEN;
+
+               // convert to 802.3 header
+        CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
+
+#ifdef CONFIG_STA_SUPPORT
+               if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
+               {
+                   // avoid local heap overflow, use dyanamic allocation
+                  MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+                  memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
+                  Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
+                  WpaEAPOLKeyAction(pAd, Elem);
+                  kfree(Elem);
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       if (pRemovedLLCSNAP)
+                       {
+                               pPayload -= LENGTH_802_3;
+                               PayloadSize += LENGTH_802_3;
+                               NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
+                       }
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+               pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
+               if (pClonePacket)
+               {
+#ifdef CONFIG_STA_SUPPORT
+                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
+#endif // CONFIG_STA_SUPPORT //
+               }
+
+
+               // A-MSDU has padding to multiple of 4 including subframe header.
+               // align SubFrameSize up to multiple of 4
+               SubFrameSize = (SubFrameSize+3)&(~0x3);
+
+
+               if (SubFrameSize > 1528 || SubFrameSize < 32)
+               {
+                       break;
+               }
+
+               if (DataSize > SubFrameSize)
+               {
+                       pData += SubFrameSize;
+                       DataSize -= SubFrameSize;
+               }
+               else
+               {
+                       // end of A-MSDU
+                       DataSize = 0;
+               }
+       }
+
+       // finally release original rx packet
+       RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+
+       return nMSDU;
+}
+
+
+UINT BA_Reorder_AMSDU_Annnounce(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket)
+{
+       PUCHAR                  pData;
+       USHORT                  DataSize;
+       UINT                    nMSDU = 0;
+
+       pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
+       DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
+
+       nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
+
+       return nMSDU;
+}
+
+
+/*
+       ==========================================================================
+       Description:
+               Look up the MAC address in the MAC table. Return NULL if not found.
+       Return:
+               pEntry - pointer to the MAC entry; NULL is not found
+       ==========================================================================
+*/
+MAC_TABLE_ENTRY *MacTableLookup(
+       IN PRTMP_ADAPTER pAd,
+       PUCHAR pAddr)
+{
+       ULONG HashIdx;
+       MAC_TABLE_ENTRY *pEntry = NULL;
+
+       HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+       pEntry = pAd->MacTab.Hash[HashIdx];
+
+       while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
+       {
+               if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
+               {
+                       break;
+               }
+               else
+                       pEntry = pEntry->pNext;
+       }
+
+       return pEntry;
+}
+
+MAC_TABLE_ENTRY *MacTableInsertEntry(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR                      pAddr,
+       IN      UCHAR                   apidx,
+       IN BOOLEAN      CleanAll)
+{
+       UCHAR HashIdx;
+       int i, FirstWcid;
+       MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
+
+       // if FULL, return
+       if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
+               return NULL;
+
+       FirstWcid = 1;
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       if (pAd->StaCfg.BssType == BSS_INFRA)
+               FirstWcid = 2;
+#endif // CONFIG_STA_SUPPORT //
+
+       // allocate one MAC entry
+       NdisAcquireSpinLock(&pAd->MacTabLock);
+       for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++)   // skip entry#0 so that "entry index == AID" for fast lookup
+       {
+               // pick up the first available vacancy
+               if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
+                       (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
+                       (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
+                       (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+                       && (pAd->MacTab.Content[i].ValidAsDls == FALSE)
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+                       )
+               {
+                       pEntry = &pAd->MacTab.Content[i];
+                       if (CleanAll == TRUE)
+                       {
+                               pEntry->MaxSupportedRate = RATE_11;
+                               pEntry->CurrTxRate = RATE_11;
+                               NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
+                               pEntry->PairwiseKey.KeyLen = 0;
+                               pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
+                       }
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+                       if (apidx >= MIN_NET_DEVICE_FOR_DLS)
+                       {
+                               pEntry->ValidAsCLI = FALSE;
+                               pEntry->ValidAsWDS = FALSE;
+                               pEntry->ValidAsApCli = FALSE;
+                               pEntry->ValidAsMesh = FALSE;
+                               pEntry->ValidAsDls = TRUE;
+                               pEntry->isCached = FALSE;
+                       }
+                       else
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+                       {
+
+#ifdef CONFIG_STA_SUPPORT
+                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               {
+                                       pEntry->ValidAsCLI = TRUE;
+                                       pEntry->ValidAsWDS = FALSE;
+                                       pEntry->ValidAsApCli = FALSE;
+                                       pEntry->ValidAsMesh = FALSE;
+                                       pEntry->ValidAsDls = FALSE;
+                               }
+#endif // CONFIG_STA_SUPPORT //
+                       }
+
+                       pEntry->bIAmBadAtheros = FALSE;
+                       pEntry->pAd = pAd;
+                       pEntry->CMTimerRunning = FALSE;
+                       pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+                       pEntry->RSNIE_Len = 0;
+                       NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
+                       pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
+
+                       if (pEntry->ValidAsMesh)
+                               pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
+                       else if (pEntry->ValidAsApCli)
+                               pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
+                       else if (pEntry->ValidAsWDS)
+                               pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+                       else if (pEntry->ValidAsDls)
+                               pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS);
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+                       else
+                               pEntry->apidx = apidx;
+
+                       {
+
+#ifdef CONFIG_STA_SUPPORT
+                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               {
+                                       pEntry->AuthMode = pAd->StaCfg.AuthMode;
+                                       pEntry->WepStatus = pAd->StaCfg.WepStatus;
+                                       pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
+                               }
+#endif // CONFIG_STA_SUPPORT //
+                       }
+
+                       pEntry->GTKState = REKEY_NEGOTIATING;
+                       pEntry->PairwiseKey.KeyLen = 0;
+                       pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+                       if (pEntry->ValidAsDls == TRUE)
+                               pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+#endif //QOS_DLS_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+                       pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                       pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
+                       COPY_MAC_ADDR(pEntry->Addr, pAddr);
+                       pEntry->Sst = SST_NOT_AUTH;
+                       pEntry->AuthState = AS_NOT_AUTH;
+                       pEntry->Aid = (USHORT)i;  //0;
+                       pEntry->CapabilityInfo = 0;
+                       pEntry->PsMode = PWR_ACTIVE;
+                       pEntry->PsQIdleCount = 0;
+                       pEntry->NoDataIdleCount = 0;
+                       pEntry->ContinueTxFailCnt = 0;
+                       InitializeQueueHeader(&pEntry->PsQueue);
+
+
+                       pAd->MacTab.Size ++;
+                       // Add this entry into ASIC RX WCID search table
+                       RT28XX_STA_ENTRY_ADD(pAd, pEntry);
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
+                       break;
+               }
+       }
+
+       // add this MAC entry into HASH table
+       if (pEntry)
+       {
+               HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+               if (pAd->MacTab.Hash[HashIdx] == NULL)
+               {
+                       pAd->MacTab.Hash[HashIdx] = pEntry;
+               }
+               else
+               {
+                       pCurrEntry = pAd->MacTab.Hash[HashIdx];
+                       while (pCurrEntry->pNext != NULL)
+                               pCurrEntry = pCurrEntry->pNext;
+                       pCurrEntry->pNext = pEntry;
+               }
+       }
+
+       NdisReleaseSpinLock(&pAd->MacTabLock);
+       return pEntry;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Delete a specified client from MAC table
+       ==========================================================================
+ */
+BOOLEAN MacTableDeleteEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT wcid,
+       IN PUCHAR pAddr)
+{
+       USHORT HashIdx;
+       MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
+       BOOLEAN Cancelled;
+       //USHORT        offset; // unused variable
+       //UCHAR j;                      // unused variable
+
+       if (wcid >= MAX_LEN_OF_MAC_TABLE)
+               return FALSE;
+
+       NdisAcquireSpinLock(&pAd->MacTabLock);
+
+       HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+       //pEntry = pAd->MacTab.Hash[HashIdx];
+       pEntry = &pAd->MacTab.Content[wcid];
+
+       if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+               || pEntry->ValidAsDls
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+               ))
+       {
+               if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
+               {
+
+                       // Delete this entry from ASIC on-chip WCID Table
+                       RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
+
+#ifdef DOT11_N_SUPPORT
+                       // free resources of BA
+                       BASessionTearDownALL(pAd, pEntry->Aid);
+#endif // DOT11_N_SUPPORT //
+
+
+                       pPrevEntry = NULL;
+                       pProbeEntry = pAd->MacTab.Hash[HashIdx];
+                       ASSERT(pProbeEntry);
+
+                       // update Hash list
+                       do
+                       {
+                               if (pProbeEntry == pEntry)
+                               {
+                                       if (pPrevEntry == NULL)
+                                       {
+                                               pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
+                                       }
+                                       else
+                                       {
+                                               pPrevEntry->pNext = pEntry->pNext;
+                                       }
+                                       break;
+                               }
+
+                               pPrevEntry = pProbeEntry;
+                               pProbeEntry = pProbeEntry->pNext;
+                       } while (pProbeEntry);
+
+                       // not found !!!
+                       ASSERT(pProbeEntry != NULL);
+
+                       RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
+
+
+               if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
+               {
+                       RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
+                       pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+               }
+
+
+                       NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
+                       pAd->MacTab.Size --;
+                       DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
+               }
+               else
+               {
+                       printk("\n%s: Impossible Wcid = %d !!!!!\n", __FUNCTION__, wcid);
+               }
+       }
+
+       NdisReleaseSpinLock(&pAd->MacTabLock);
+
+       //Reset operating mode when no Sta.
+       if (pAd->MacTab.Size == 0)
+       {
+#ifdef DOT11_N_SUPPORT
+               pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
+#endif // DOT11_N_SUPPORT //
+               AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
+       }
+
+       return TRUE;
+}
+
+
+/*
+       ==========================================================================
+       Description:
+               This routine reset the entire MAC table. All packets pending in
+               the power-saving queues are freed here.
+       ==========================================================================
+ */
+VOID MacTableReset(
+       IN  PRTMP_ADAPTER  pAd)
+{
+       int         i;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
+       //NdisAcquireSpinLock(&pAd->MacTabLock);
+
+       for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
+          {
+
+#ifdef DOT11_N_SUPPORT
+                       // free resources of BA
+                       BASessionTearDownALL(pAd, i);
+#endif // DOT11_N_SUPPORT //
+
+                       pAd->MacTab.Content[i].ValidAsCLI = FALSE;
+
+
+
+#ifdef RT2870
+                       NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
+                       RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
+#endif // RT2870 //
+
+                       //AsicDelWcidTab(pAd, i);
+               }
+       }
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID AssocParmFill(
+       IN PRTMP_ADAPTER pAd,
+       IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
+       IN PUCHAR                     pAddr,
+       IN USHORT                     CapabilityInfo,
+       IN ULONG                      Timeout,
+       IN USHORT                     ListenIntv)
+{
+       COPY_MAC_ADDR(AssocReq->Addr, pAddr);
+       // Add mask to support 802.11b mode only
+       AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
+       AssocReq->Timeout = Timeout;
+       AssocReq->ListenIntv = ListenIntv;
+}
+
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID DisassocParmFill(
+       IN PRTMP_ADAPTER pAd,
+       IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
+       IN PUCHAR pAddr,
+       IN USHORT Reason)
+{
+       COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
+       DisassocReq->Reason = Reason;
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Check the out going frame, if this is an DHCP or ARP datagram
+       will be duplicate another frame at low data rate transmit.
+
+       Arguments:
+               pAd             Pointer to our adapter
+               pPacket         Pointer to outgoing Ndis frame
+
+       Return Value:
+               TRUE            To be duplicate at Low data rate transmit. (1mb)
+               FALSE           Do nothing.
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+               MAC header + IP Header + UDP Header
+                 14 Bytes        20 Bytes
+
+               UDP Header
+               00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
+                                               Source Port
+               16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
+                                       Destination Port
+
+               port 0x43 means Bootstrap Protocol, server.
+               Port 0x44 means Bootstrap Protocol, client.
+
+       ========================================================================
+*/
+
+BOOLEAN RTMPCheckDHCPFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket)
+{
+       PACKET_INFO     PacketInfo;
+       ULONG                   NumberOfBytesRead = 0;
+       ULONG                   CurrentOffset = 0;
+       PVOID                   pVirtualAddress = NULL;
+       UINT                    NdisBufferLength;
+       PUCHAR                  pSrc;
+       USHORT                  Protocol;
+       UCHAR                   ByteOffset36 = 0;
+       UCHAR                   ByteOffset38 = 0;
+       BOOLEAN                 ReadFirstParm = TRUE;
+
+       RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
+
+       NumberOfBytesRead += NdisBufferLength;
+       pSrc = (PUCHAR) pVirtualAddress;
+       Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
+
+       //
+       // Check DHCP & BOOTP protocol
+       //
+       while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
+       {
+               if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
+               {
+                       CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
+                       ByteOffset36 = *(pSrc + CurrentOffset);
+                       ReadFirstParm = FALSE;
+               }
+
+               if (NumberOfBytesRead >= 37)
+               {
+                       CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
+                       ByteOffset38 = *(pSrc + CurrentOffset);
+                       //End of Read
+                       break;
+               }
+               return FALSE;
+       }
+
+       // Check for DHCP & BOOTP protocol
+       if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
+               {
+               //
+               // 2054 (hex 0806) for ARP datagrams
+               // if this packet is not ARP datagrams, then do nothing
+               // ARP datagrams will also be duplicate at 1mb broadcast frames
+               //
+               if (Protocol != 0x0806 )
+                       return FALSE;
+               }
+
+       return TRUE;
+}
+
+
+BOOLEAN RTMPCheckEtherType(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket)
+{
+       USHORT  TypeLen;
+       UCHAR   Byte0, Byte1;
+       PUCHAR  pSrcBuf;
+       UINT32  pktLen;
+       UINT16  srcPort, dstPort;
+       BOOLEAN status = TRUE;
+
+
+       pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
+       pktLen = GET_OS_PKT_LEN(pPacket);
+
+       ASSERT(pSrcBuf);
+
+       RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
+
+       // get Ethernet protocol field
+       TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
+
+       pSrcBuf += LENGTH_802_3;        // Skip the Ethernet Header.
+
+       if (TypeLen <= 1500)
+       {       // 802.3, 802.3 LLC
+               /*
+                       DestMAC(6) + SrcMAC(6) + Lenght(2) +
+                       DSAP(1) + SSAP(1) + Control(1) +
+                       if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
+                               => + SNAP (5, OriginationID(3) + etherType(2))
+               */
+               if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
+               {
+                       Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
+                       RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
+                       TypeLen = (USHORT)((Byte0 << 8) + Byte1);
+                       pSrcBuf += 8; // Skip this LLC/SNAP header
+               }
+               else
+               {
+                       //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
+               }
+       }
+
+       // If it's a VLAN packet, get the real Type/Length field.
+       if (TypeLen == 0x8100)
+       {
+               /* 0x8100 means VLAN packets */
+
+               /* Dest. MAC Address (6-bytes) +
+                  Source MAC Address (6-bytes) +
+                  Length/Type = 802.1Q Tag Type (2-byte) +
+                  Tag Control Information (2-bytes) +
+                  Length / Type (2-bytes) +
+                  data payload (0-n bytes) +
+                  Pad (0-p bytes) +
+                  Frame Check Sequence (4-bytes) */
+
+               RTMP_SET_PACKET_VLAN(pPacket, 1);
+               Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
+               TypeLen = (USHORT)((Byte0 << 8) + Byte1);
+
+               pSrcBuf += 4; // Skip the VLAN Header.
+       }
+
+       switch (TypeLen)
+       {
+               case 0x0800:
+                       {
+                               ASSERT((pktLen > 34));
+                               if (*(pSrcBuf + 9) == 0x11)
+                               {       // udp packet
+                                       ASSERT((pktLen > 34));  // 14 for ethernet header, 20 for IP header
+
+                                       pSrcBuf += 20;  // Skip the IP header
+                                       srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
+                                       dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
+
+                                       if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
+                                       {       //It's a BOOTP/DHCP packet
+                                               RTMP_SET_PACKET_DHCP(pPacket, 1);
+                                       }
+                               }
+                       }
+                       break;
+               case 0x0806:
+                       {
+                               //ARP Packet.
+                               RTMP_SET_PACKET_DHCP(pPacket, 1);
+                       }
+                       break;
+               case 0x888e:
+                       {
+                               // EAPOL Packet.
+                               RTMP_SET_PACKET_EAPOL(pPacket, 1);
+                       }
+                       break;
+               default:
+                       status = FALSE;
+                       break;
+       }
+
+       return status;
+
+}
+
+
+
+VOID Update_Rssi_Sample(
+       IN PRTMP_ADAPTER        pAd,
+       IN RSSI_SAMPLE          *pRssi,
+       IN PRXWI_STRUC          pRxWI)
+               {
+       CHAR    rssi0 = pRxWI->RSSI0;
+       CHAR    rssi1 = pRxWI->RSSI1;
+       CHAR    rssi2 = pRxWI->RSSI2;
+
+       if (rssi0 != 0)
+       {
+               pRssi->LastRssi0        = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
+               pRssi->AvgRssi0X8       = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
+               pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
+       }
+
+       if (rssi1 != 0)
+       {
+               pRssi->LastRssi1        = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
+               pRssi->AvgRssi1X8       = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
+               pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
+       }
+
+       if (rssi2 != 0)
+       {
+               pRssi->LastRssi2        = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
+               pRssi->AvgRssi2X8  = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
+               pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
+       }
+}
+
+
+
+// Normal legacy Rx packet indication
+VOID Indicate_Legacy_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID)
+{
+       PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
+       UCHAR                   Header802_3[LENGTH_802_3];
+
+       // 1. get 802.3 Header
+       // 2. remove LLC
+       //              a. pointer pRxBlk->pData to payload
+       //      b. modify pRxBlk->DataSize
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
+#endif // CONFIG_STA_SUPPORT //
+
+       if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
+       {
+#if 0 // sample take off, for multiple card design
+               static int err_size;
+
+               err_size++;
+               if (err_size > 20)
+               {
+                        printk("Legacy DataSize = %d\n", pRxBlk->DataSize);
+                        hex_dump("802.3 Header", Header802_3, LENGTH_802_3);
+                        hex_dump("Payload", pRxBlk->pData, 64);
+                        err_size = 0;
+               }
+#endif
+
+               // release packet
+               RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+               return;
+       }
+
+
+       STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
+
+#ifdef RT2870
+#ifdef DOT11_N_SUPPORT
+       if (pAd->CommonCfg.bDisableReordering == 0)
+       {
+               PBA_REC_ENTRY           pBAEntry;
+               ULONG                           Now32;
+               UCHAR                           Wcid = pRxBlk->pRxWI->WirelessCliID;
+               UCHAR                           TID = pRxBlk->pRxWI->TID;
+               USHORT                          Idx;
+
+#define REORDERING_PACKET_TIMEOUT              ((100 * HZ)/1000)       // system ticks -- 100 ms
+
+               if (Wcid < MAX_LEN_OF_MAC_TABLE)
+               {
+                       Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+                       if (Idx != 0)
+                       {
+                               pBAEntry = &pAd->BATable.BARecEntry[Idx];
+                               // update last rx time
+                               NdisGetSystemUpTime(&Now32);
+                               if ((pBAEntry->list.qlen > 0) &&
+                                        RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
+                                       )
+                               {
+                                       printk("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU);
+                                       hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
+                                       ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
+                               }
+                       }
+               }
+       }
+#endif // DOT11_N_SUPPORT //
+#endif // RT2870 //
+
+       wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
+
+       //
+       // pass this 802.3 packet to upper layer or forward this packet to WM directly
+       //
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
+#endif // CONFIG_STA_SUPPORT //
+
+}
+
+
+// Normal, AMPDU or AMSDU
+VOID CmmRxnonRalinkFrameIndicate(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID)
+{
+#ifdef DOT11_N_SUPPORT
+       if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
+       {
+               Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
+       }
+       else
+#endif // DOT11_N_SUPPORT //
+       {
+#ifdef DOT11_N_SUPPORT
+               if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
+               {
+                       // handle A-MSDU
+                       Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
+               }
+               else
+#endif // DOT11_N_SUPPORT //
+               {
+                       Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
+               }
+       }
+}
+
+
+VOID CmmRxRalinkFrameIndicate(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MAC_TABLE_ENTRY *pEntry,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID)
+{
+       UCHAR                   Header802_3[LENGTH_802_3];
+       UINT16                  Msdu2Size;
+       UINT16                  Payload1Size, Payload2Size;
+       PUCHAR                  pData2;
+       PNDIS_PACKET    pPacket2 = NULL;
+
+
+
+       Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
+
+       if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
+       {
+               /* skip two byte MSDU2 len */
+               pRxBlk->pData += 2;
+               pRxBlk->DataSize -= 2;
+       }
+       else
+       {
+               // release packet
+               RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+               return;
+       }
+
+       // get 802.3 Header and  remove LLC
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
+#endif // CONFIG_STA_SUPPORT //
+
+
+       ASSERT(pRxBlk->pRxPacket);
+
+       // Ralink Aggregation frame
+       pAd->RalinkCounters.OneSecRxAggregationCount ++;
+       Payload1Size = pRxBlk->DataSize - Msdu2Size;
+       Payload2Size = Msdu2Size - LENGTH_802_3;
+
+       pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
+#endif // CONFIG_STA_SUPPORT //
+
+       if (!pPacket2)
+       {
+               // release packet
+               RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+               return;
+       }
+
+       // update payload size of 1st packet
+       pRxBlk->DataSize = Payload1Size;
+       wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
+#endif // CONFIG_STA_SUPPORT //
+
+       if (pPacket2)
+       {
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
+#endif // CONFIG_STA_SUPPORT //
+       }
+}
+
+
+#define RESET_FRAGFRAME(_fragFrame) \
+       {                                                               \
+               _fragFrame.RxSize = 0;          \
+               _fragFrame.Sequence = 0;        \
+               _fragFrame.LastFrag = 0;        \
+               _fragFrame.Flags = 0;           \
+       }
+
+
+PNDIS_PACKET RTMPDeFragmentDataFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk)
+{
+       PHEADER_802_11  pHeader = pRxBlk->pHeader;
+       PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
+       UCHAR                   *pData = pRxBlk->pData;
+       USHORT                  DataSize = pRxBlk->DataSize;
+       PNDIS_PACKET    pRetPacket = NULL;
+       UCHAR                   *pFragBuffer = NULL;
+       BOOLEAN                 bReassDone = FALSE;
+       UCHAR                   HeaderRoom = 0;
+
+
+       ASSERT(pHeader);
+
+       HeaderRoom = pData - (UCHAR *)pHeader;
+
+       // Re-assemble the fragmented packets
+       if (pHeader->Frag == 0)         // Frag. Number is 0 : First frag or only one pkt
+       {
+               // the first pkt of fragment, record it.
+               if (pHeader->FC.MoreFrag)
+               {
+                       ASSERT(pAd->FragFrame.pFragPacket);
+                       pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
+                       pAd->FragFrame.RxSize   = DataSize + HeaderRoom;
+                       NdisMoveMemory(pFragBuffer,      pHeader, pAd->FragFrame.RxSize);
+                       pAd->FragFrame.Sequence = pHeader->Sequence;
+                       pAd->FragFrame.LastFrag = pHeader->Frag;           // Should be 0
+                       ASSERT(pAd->FragFrame.LastFrag == 0);
+                       goto done;      // end of processing this frame
+               }
+       }
+       else    //Middle & End of fragment
+       {
+               if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
+                       (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
+               {
+                       // Fragment is not the same sequence or out of fragment number order
+                       // Reset Fragment control blk
+                       RESET_FRAGFRAME(pAd->FragFrame);
+                       DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
+                       goto done; // give up this frame
+               }
+               else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
+               {
+                       // Fragment frame is too large, it exeeds the maximum frame size.
+                       // Reset Fragment control blk
+                       RESET_FRAGFRAME(pAd->FragFrame);
+                       DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
+                       goto done; // give up this frame
+               }
+
+        //
+               // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
+               // In this case, we will dropt it.
+               //
+               if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
+               {
+                       DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
+                       goto done; // give up this frame
+               }
+
+               pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
+
+               // concatenate this fragment into the re-assembly buffer
+               NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
+               pAd->FragFrame.RxSize  += DataSize;
+               pAd->FragFrame.LastFrag = pHeader->Frag;           // Update fragment number
+
+               // Last fragment
+               if (pHeader->FC.MoreFrag == FALSE)
+               {
+                       bReassDone = TRUE;
+               }
+       }
+
+done:
+       // always release rx fragmented packet
+       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+
+       // return defragmented packet if packet is reassembled completely
+       // otherwise return NULL
+       if (bReassDone)
+       {
+               PNDIS_PACKET pNewFragPacket;
+
+               // allocate a new packet buffer for fragment
+               pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
+               if (pNewFragPacket)
+               {
+                       // update RxBlk
+                       pRetPacket = pAd->FragFrame.pFragPacket;
+                       pAd->FragFrame.pFragPacket = pNewFragPacket;
+                       pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
+                       pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
+                       pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
+                       pRxBlk->pRxPacket = pRetPacket;
+               }
+               else
+               {
+                       RESET_FRAGFRAME(pAd->FragFrame);
+               }
+       }
+
+       return pRetPacket;
+}
+
+
+VOID Indicate_AMSDU_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID)
+{
+       UINT                    nMSDU;
+
+       update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
+       RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
+       nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
+}
+
+VOID Indicate_EAPOL_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID)
+{
+       MAC_TABLE_ENTRY *pEntry = NULL;
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               pEntry = &pAd->MacTab.Content[BSSID_WCID];
+               STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
+               return;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       if (pEntry == NULL)
+       {
+               DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
+               // release packet
+               RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+               return;
+       }
+}
+
+#define BCN_TBTT_OFFSET                64      //defer 64 us
+VOID ReSyncBeaconTime(
+       IN  PRTMP_ADAPTER   pAd)
+{
+
+       UINT32  Offset;
+
+
+       Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
+
+       pAd->TbttTickCount++;
+
+       //
+       // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
+       // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
+       //
+       if (Offset == (BCN_TBTT_OFFSET-2))
+       {
+               BCN_TIME_CFG_STRUC csr;
+               RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+               csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ;     // ASIC register in units of 1/16 TU = 64us
+               RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+       }
+       else
+       {
+               if (Offset == (BCN_TBTT_OFFSET-1))
+               {
+                       BCN_TIME_CFG_STRUC csr;
+
+                       RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+                       csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
+                       RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+               }
+       }
+}
+
diff --git a/drivers/staging/rt2870/common/cmm_data_2870.c b/drivers/staging/rt2870/common/cmm_data_2870.c
new file mode 100644 (file)
index 0000000..f77000f
--- /dev/null
@@ -0,0 +1,963 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+*/
+/*
+   All functions in this file must be USB-depended, or you should out your function
+       in other files.
+
+*/
+#include "../rt_config.h"
+
+
+/*
+       We can do copy the frame into pTxContext when match following conditions.
+               =>
+               =>
+               =>
+*/
+static inline NDIS_STATUS RtmpUSBCanDoWrite(
+       IN RTMP_ADAPTER         *pAd,
+       IN UCHAR                        QueIdx,
+       IN HT_TX_CONTEXT        *pHTTXContext)
+{
+       NDIS_STATUS     canWrite = NDIS_STATUS_RESOURCES;
+
+       if (((pHTTXContext->CurWritePosition) < pHTTXContext->NextBulkOutPosition) && (pHTTXContext->CurWritePosition + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c1!\n"));
+               RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
+       }
+       else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < LOCAL_TXBUF_SIZE))
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c2!\n"));
+               RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
+       }
+       else if (pHTTXContext->bCurWriting == TRUE)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c3!\n"));
+       }
+       else
+       {
+               canWrite = NDIS_STATUS_SUCCESS;
+       }
+
+
+       return canWrite;
+}
+
+
+USHORT RtmpUSB_WriteSubTxResource(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      BOOLEAN                 bIsLast,
+       OUT     USHORT                  *FreeNumber)
+{
+
+       // Dummy function. Should be removed in the future.
+       return 0;
+
+}
+
+USHORT RtmpUSB_WriteFragTxResource(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      UCHAR                   fragNum,
+       OUT     USHORT                  *FreeNumber)
+{
+       HT_TX_CONTEXT   *pHTTXContext;
+       USHORT                  hwHdrLen;       // The hwHdrLen consist of 802.11 header length plus the header padding length.
+       UINT32                  fillOffset;
+       TXINFO_STRUC    *pTxInfo;
+       TXWI_STRUC              *pTxWI;
+       PUCHAR                  pWirelessPacket = NULL;
+       UCHAR                   QueIdx;
+       NDIS_STATUS             Status;
+       unsigned long   IrqFlags;
+       UINT32                  USBDMApktLen = 0, DMAHdrLen, padding;
+       BOOLEAN                 TxQLastRound = FALSE;
+
+       //
+       // get Tx Ring Resource & Dma Buffer address
+       //
+       QueIdx = pTxBlk->QueIdx;
+       pHTTXContext  = &pAd->TxContext[QueIdx];
+
+       RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+       pHTTXContext  = &pAd->TxContext[QueIdx];
+       fillOffset = pHTTXContext->CurWritePosition;
+
+       if(fragNum == 0)
+       {
+               // Check if we have enough space for this bulk-out batch.
+               Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
+               if (Status == NDIS_STATUS_SUCCESS)
+               {
+                       pHTTXContext->bCurWriting = TRUE;
+
+                       // Reserve space for 8 bytes padding.
+                       if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
+                       {
+                               pHTTXContext->ENextBulkOutPosition += 8;
+                               pHTTXContext->CurWritePosition += 8;
+                               fillOffset += 8;
+                       }
+                       pTxBlk->Priv = 0;
+                       pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+               }
+               else
+               {
+                       RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+                       RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+                       return(Status);
+               }
+       }
+       else
+       {
+               // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.
+               Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
+               if (Status == NDIS_STATUS_SUCCESS)
+               {
+                       fillOffset += pTxBlk->Priv;
+               }
+               else
+               {
+                       RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+                       RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+                       return(Status);
+               }
+       }
+
+       NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE);
+       pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
+       pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
+
+       pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
+
+       // copy TXWI + WLAN Header + LLC into DMA Header Buffer
+       //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
+       hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
+
+       // Build our URB for USBD
+       DMAHdrLen = TXWI_SIZE + hwHdrLen;
+       USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen;
+       padding = (4 - (USBDMApktLen % 4)) & 0x03;      // round up to 4 byte alignment
+       USBDMApktLen += padding;
+
+       pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen);
+
+       // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload
+       RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/,  FALSE);
+
+       if (fragNum == pTxBlk->TotalFragNum)
+       {
+               pTxInfo->USBDMATxburst = 0;
+               if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT)
+               {
+                       pTxInfo->SwUseLastRound = 1;
+                       TxQLastRound = TRUE;
+               }
+       }
+       else
+       {
+               pTxInfo->USBDMATxburst = 1;
+       }
+
+       NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
+#ifdef RT_BIG_ENDIAN
+       RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
+#endif // RT_BIG_ENDIAN //
+       pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
+       pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
+
+       RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+       NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
+
+       //      Zero the last padding.
+       pWirelessPacket += pTxBlk->SrcBufLen;
+       NdisZeroMemory(pWirelessPacket, padding + 8);
+
+       if (fragNum == pTxBlk->TotalFragNum)
+       {
+               RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+               // Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame.
+               pHTTXContext->CurWritePosition += pTxBlk->Priv;
+               if (TxQLastRound == TRUE)
+                       pHTTXContext->CurWritePosition = 8;
+               pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+
+
+               // Finally, set bCurWriting as FALSE
+       pHTTXContext->bCurWriting = FALSE;
+
+               RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+               // succeed and release the skb buffer
+               RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
+       }
+
+
+       return(Status);
+
+}
+
+
+USHORT RtmpUSB_WriteSingleTxResource(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      BOOLEAN                 bIsLast,
+       OUT     USHORT                  *FreeNumber)
+{
+       HT_TX_CONTEXT   *pHTTXContext;
+       USHORT                  hwHdrLen;
+       UINT32                  fillOffset;
+       TXINFO_STRUC    *pTxInfo;
+       TXWI_STRUC              *pTxWI;
+       PUCHAR                  pWirelessPacket;
+       UCHAR                   QueIdx;
+       unsigned long   IrqFlags;
+       NDIS_STATUS             Status;
+       UINT32                  USBDMApktLen = 0, DMAHdrLen, padding;
+       BOOLEAN                 bTxQLastRound = FALSE;
+
+       // For USB, didn't need PCI_MAP_SINGLE()
+       //SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE);
+
+
+       //
+       // get Tx Ring Resource & Dma Buffer address
+       //
+       QueIdx = pTxBlk->QueIdx;
+
+       RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+       pHTTXContext  = &pAd->TxContext[QueIdx];
+       fillOffset = pHTTXContext->CurWritePosition;
+
+
+
+       // Check ring full.
+       Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
+       if(Status == NDIS_STATUS_SUCCESS)
+       {
+               pHTTXContext->bCurWriting = TRUE;
+
+               pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
+               pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
+
+               // Reserve space for 8 bytes padding.
+               if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
+               {
+                       pHTTXContext->ENextBulkOutPosition += 8;
+                       pHTTXContext->CurWritePosition += 8;
+                       fillOffset += 8;
+               }
+               pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+
+               pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
+
+               // copy TXWI + WLAN Header + LLC into DMA Header Buffer
+               //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
+               hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
+
+               // Build our URB for USBD
+               DMAHdrLen = TXWI_SIZE + hwHdrLen;
+               USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen;
+               padding = (4 - (USBDMApktLen % 4)) & 0x03;      // round up to 4 byte alignment
+               USBDMApktLen += padding;
+
+               pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen);
+
+               // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload
+               RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/,  FALSE);
+
+               if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT)
+               {
+                       pTxInfo->SwUseLastRound = 1;
+                       bTxQLastRound = TRUE;
+               }
+               NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
+#ifdef RT_BIG_ENDIAN
+               RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
+#endif // RT_BIG_ENDIAN //
+               pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
+
+               // We unlock it here to prevent the first 8 bytes maybe over-writed issue.
+               //      1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext.
+               //      2. An interrupt break our routine and handle bulk-out complete.
+               //      3. In the bulk-out compllete, it need to do another bulk-out,
+               //                      if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
+               //                      but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
+               //      4. Interrupt complete.
+               //  5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
+               //      6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
+               //              and the packet will wrong.
+               pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
+               RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+               NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
+               pWirelessPacket += pTxBlk->SrcBufLen;
+               NdisZeroMemory(pWirelessPacket, padding + 8);
+
+               RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+               pHTTXContext->CurWritePosition += pTxBlk->Priv;
+               if (bTxQLastRound)
+                       pHTTXContext->CurWritePosition = 8;
+               pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+
+       pHTTXContext->bCurWriting = FALSE;
+       }
+
+
+       RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+
+       // succeed and release the skb buffer
+       RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
+
+       return(Status);
+
+}
+
+
+USHORT RtmpUSB_WriteMultiTxResource(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      UCHAR                   frameNum,
+       OUT     USHORT                  *FreeNumber)
+{
+       HT_TX_CONTEXT   *pHTTXContext;
+       USHORT                  hwHdrLen;       // The hwHdrLen consist of 802.11 header length plus the header padding length.
+       UINT32                  fillOffset;
+       TXINFO_STRUC    *pTxInfo;
+       TXWI_STRUC              *pTxWI;
+       PUCHAR                  pWirelessPacket = NULL;
+       UCHAR                   QueIdx;
+       NDIS_STATUS             Status;
+       unsigned long   IrqFlags;
+       //UINT32                        USBDMApktLen = 0, DMAHdrLen, padding;
+
+       //
+       // get Tx Ring Resource & Dma Buffer address
+       //
+       QueIdx = pTxBlk->QueIdx;
+       pHTTXContext  = &pAd->TxContext[QueIdx];
+
+       RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+       if(frameNum == 0)
+       {
+               // Check if we have enough space for this bulk-out batch.
+               Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
+               if (Status == NDIS_STATUS_SUCCESS)
+               {
+                       pHTTXContext->bCurWriting = TRUE;
+
+                       pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
+                       pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
+
+
+                       // Reserve space for 8 bytes padding.
+                       if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
+                       {
+
+                               pHTTXContext->CurWritePosition += 8;
+                               pHTTXContext->ENextBulkOutPosition += 8;
+                       }
+                       fillOffset = pHTTXContext->CurWritePosition;
+                       pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+
+                       pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
+
+                       //
+                       // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
+                       //
+                       if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
+                               //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
+                               hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
+                       else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
+                               //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
+                               hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
+                       else
+                               //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
+                               hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
+
+                       // Update the pTxBlk->Priv.
+                       pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
+
+                       //      pTxInfo->USBDMApktLen now just a temp value and will to correct latter.
+                       RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/,  FALSE);
+
+                       // Copy it.
+                       NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv);
+#ifdef RT_BIG_ENDIAN
+                       RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
+#endif // RT_BIG_ENDIAN //
+                       pHTTXContext->CurWriteRealPos += pTxBlk->Priv;
+                       pWirelessPacket += pTxBlk->Priv;
+               }
+       }
+       else
+       {       // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.
+
+               Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
+               if (Status == NDIS_STATUS_SUCCESS)
+               {
+                       fillOffset =  (pHTTXContext->CurWritePosition + pTxBlk->Priv);
+                       pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
+
+                       //hwHdrLen = pTxBlk->MpduHeaderLen;
+                       NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen);
+                       pWirelessPacket += (pTxBlk->MpduHeaderLen);
+                       pTxBlk->Priv += pTxBlk->MpduHeaderLen;
+               }
+               else
+               {       // It should not happened now unless we are going to shutdown.
+                       DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n"));
+                       Status = NDIS_STATUS_FAILURE;
+               }
+       }
+
+
+       // We unlock it here to prevent the first 8 bytes maybe over-write issue.
+       //      1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext.
+       //      2. An interrupt break our routine and handle bulk-out complete.
+       //      3. In the bulk-out compllete, it need to do another bulk-out,
+       //                      if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
+       //                      but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
+       //      4. Interrupt complete.
+       //  5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
+       //      6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
+       //              and the packet will wrong.
+       RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+       if (Status != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition));
+               goto done;
+       }
+
+       // Copy the frame content into DMA buffer and update the pTxBlk->Priv
+       NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
+       pWirelessPacket += pTxBlk->SrcBufLen;
+       pTxBlk->Priv += pTxBlk->SrcBufLen;
+
+done:
+       // Release the skb buffer here
+       RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
+
+       return(Status);
+
+}
+
+
+VOID RtmpUSB_FinalWriteTxResource(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      USHORT                  totalMPDUSize,
+       IN      USHORT                  TxIdx)
+{
+       UCHAR                   QueIdx;
+       HT_TX_CONTEXT   *pHTTXContext;
+       UINT32                  fillOffset;
+       TXINFO_STRUC    *pTxInfo;
+       TXWI_STRUC              *pTxWI;
+       UINT32                  USBDMApktLen, padding;
+       unsigned long   IrqFlags;
+       PUCHAR                  pWirelessPacket;
+
+       QueIdx = pTxBlk->QueIdx;
+       pHTTXContext  = &pAd->TxContext[QueIdx];
+
+       RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+       if (pHTTXContext->bCurWriting == TRUE)
+       {
+               fillOffset = pHTTXContext->CurWritePosition;
+               if (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition))
+                       && (pHTTXContext->bCopySavePad == TRUE))
+                       pWirelessPacket = (PUCHAR)(&pHTTXContext->SavedPad[0]);
+               else
+                       pWirelessPacket = (PUCHAR)(&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]);
+
+               //
+               // Update TxInfo->USBDMApktLen ,
+               //              the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding
+               //
+               pTxInfo = (PTXINFO_STRUC)(pWirelessPacket);
+
+               // Calculate the bulk-out padding
+               USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE;
+               padding = (4 - (USBDMApktLen % 4)) & 0x03;      // round up to 4 byte alignment
+               USBDMApktLen += padding;
+
+               pTxInfo->USBDMATxPktLen = USBDMApktLen;
+
+               //
+               // Update TXWI->MPDUtotalByteCount ,
+               //              the length = 802.11 header + payload_of_all_batch_frames
+               pTxWI= (PTXWI_STRUC)(pWirelessPacket + TXINFO_SIZE);
+               pTxWI->MPDUtotalByteCount = totalMPDUSize;
+
+               //
+               // Update the pHTTXContext->CurWritePosition
+               //
+               pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen);
+               if ((pHTTXContext->CurWritePosition + 3906)> MAX_TXBULK_LIMIT)
+               {       // Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame.
+                       pHTTXContext->CurWritePosition = 8;
+                       pTxInfo->SwUseLastRound = 1;
+               }
+               pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+
+
+               //
+               //      Zero the last padding.
+               //
+               pWirelessPacket = (&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset + pTxBlk->Priv]);
+               NdisZeroMemory(pWirelessPacket, padding + 8);
+
+               // Finally, set bCurWriting as FALSE
+               pHTTXContext->bCurWriting = FALSE;
+
+       }
+       else
+       {       // It should not happened now unless we are going to shutdown.
+               DBGPRINT(RT_DEBUG_ERROR, ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n"));
+       }
+
+       RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+}
+
+
+VOID RtmpUSBDataLastTxIdx(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   QueIdx,
+       IN      USHORT                  TxIdx)
+{
+       // DO nothing for USB.
+}
+
+
+/*
+       When can do bulk-out:
+               1. TxSwFreeIdx < TX_RING_SIZE;
+                       It means has at least one Ring entity is ready for bulk-out, kick it out.
+               2. If TxSwFreeIdx == TX_RING_SIZE
+                       Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out.
+
+*/
+VOID RtmpUSBDataKickOut(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      UCHAR                   QueIdx)
+{
+       RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
+       RTUSBKickBulkOut(pAd);
+
+}
+
+
+/*
+       Must be run in Interrupt context
+       This function handle RT2870 specific TxDesc and cpu index update and kick the packet out.
+ */
+int RtmpUSBMgmtKickOut(
+       IN RTMP_ADAPTER         *pAd,
+       IN UCHAR                        QueIdx,
+       IN PNDIS_PACKET         pPacket,
+       IN PUCHAR                       pSrcBufVA,
+       IN UINT                         SrcBufLen)
+{
+       PTXINFO_STRUC   pTxInfo;
+       ULONG                   BulkOutSize;
+       UCHAR                   padLen;
+       PUCHAR                  pDest;
+       ULONG                   SwIdx = pAd->MgmtRing.TxCpuIdx;
+       PTX_CONTEXT             pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[SwIdx].AllocVa;
+       unsigned long   IrqFlags;
+
+
+       pTxInfo = (PTXINFO_STRUC)(pSrcBufVA);
+
+       // Build our URB for USBD
+       BulkOutSize = SrcBufLen;
+       BulkOutSize = (BulkOutSize + 3) & (~3);
+       RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(BulkOutSize - TXINFO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE,  FALSE);
+
+       BulkOutSize += 4; // Always add 4 extra bytes at every packet.
+
+       // If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again.
+       if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0)
+               BulkOutSize += 4;
+
+       padLen = BulkOutSize - SrcBufLen;
+       ASSERT((padLen <= RTMP_PKT_TAIL_PADDING));
+
+       // Now memzero all extra padding bytes.
+       pDest = (PUCHAR)(pSrcBufVA + SrcBufLen);
+       skb_put(GET_OS_PKT_TYPE(pPacket), padLen);
+       NdisZeroMemory(pDest, padLen);
+
+       RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags);
+
+       pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket;
+       pMLMEContext->TransferBuffer = (PTX_BUFFER)(GET_OS_PKT_DATAPTR(pPacket));
+
+       // Length in TxInfo should be 8 less than bulkout size.
+       pMLMEContext->BulkOutSize = BulkOutSize;
+       pMLMEContext->InUse = TRUE;
+       pMLMEContext->bWaitingBulkOut = TRUE;
+
+
+       //for debug
+       //hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize));
+
+       //pAd->RalinkCounters.KickTxCount++;
+       //pAd->RalinkCounters.OneSecTxDoneCount++;
+
+       //if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE)
+       //      needKickOut = TRUE;
+
+       // Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX
+       pAd->MgmtRing.TxSwFreeIdx--;
+       INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
+
+       RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags);
+
+       RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
+       //if (needKickOut)
+       RTUSBKickBulkOut(pAd);
+
+       return 0;
+}
+
+
+VOID RtmpUSBNullFrameKickOut(
+       IN RTMP_ADAPTER *pAd,
+       IN UCHAR                QueIdx,
+       IN UCHAR                *pNullFrame,
+       IN UINT32               frameLen)
+{
+       if (pAd->NullContext.InUse == FALSE)
+       {
+               PTX_CONTEXT             pNullContext;
+               PTXINFO_STRUC   pTxInfo;
+               PTXWI_STRUC             pTxWI;
+               PUCHAR                  pWirelessPkt;
+
+               pNullContext = &(pAd->NullContext);
+
+               // Set the in use bit
+               pNullContext->InUse = TRUE;
+               pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0];
+
+               RTMPZeroMemory(&pWirelessPkt[0], 100);
+               pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[0];
+               RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE,  FALSE);
+               pTxInfo->QSEL = FIFO_EDCA;
+               pTxWI = (PTXWI_STRUC)&pWirelessPkt[TXINFO_SIZE];
+               RTMPWriteTxWI(pAd, pTxWI,  FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)),
+                       0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit);
+#ifdef RT_BIG_ENDIAN
+               RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
+#endif // RT_BIG_ENDIAN //
+
+               RTMPMoveMemory(&pWirelessPkt[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11));
+#ifdef RT_BIG_ENDIAN
+               RTMPFrameEndianChange(pAd, (PUCHAR)&pWirelessPkt[TXINFO_SIZE + TXWI_SIZE], DIR_WRITE, FALSE);
+#endif // RT_BIG_ENDIAN //
+               pAd->NullContext.BulkOutSize =  TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4;
+
+               // Fill out frame length information for global Bulk out arbitor
+               //pNullContext->BulkOutSize = TransferBufferLength;
+               DBGPRINT(RT_DEBUG_TRACE, ("SYNC - send NULL Frame @%d Mbps...\n", RateIdToMbps[pAd->CommonCfg.TxRate]));
+               RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL);
+
+               // Kick bulk out
+               RTUSBKickBulkOut(pAd);
+       }
+
+}
+
+#ifdef CONFIG_STA_SUPPORT
+/*
+       ========================================================================
+
+       Routine Description:
+               Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
+
+       Arguments:
+               pRxD            Pointer to the Rx descriptor
+
+       Return Value:
+               NDIS_STATUS_SUCCESS             No err
+               NDIS_STATUS_FAILURE             Error
+
+       Note:
+
+       ========================================================================
+*/
+NDIS_STATUS    RTMPCheckRxError(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PHEADER_802_11  pHeader,
+       IN      PRXWI_STRUC     pRxWI,
+       IN      PRT28XX_RXD_STRUC       pRxINFO)
+{
+       PCIPHER_KEY pWpaKey;
+       INT     dBm;
+
+       if (pAd->bPromiscuous == TRUE)
+               return(NDIS_STATUS_SUCCESS);
+       if(pRxINFO == NULL)
+               return(NDIS_STATUS_FAILURE);
+
+       // Phy errors & CRC errors
+       if (pRxINFO->Crc)
+       {
+               // Check RSSI for Noise Hist statistic collection.
+               dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
+               if (dBm <= -87)
+                       pAd->StaCfg.RPIDensity[0] += 1;
+               else if (dBm <= -82)
+                       pAd->StaCfg.RPIDensity[1] += 1;
+               else if (dBm <= -77)
+                       pAd->StaCfg.RPIDensity[2] += 1;
+               else if (dBm <= -72)
+                       pAd->StaCfg.RPIDensity[3] += 1;
+               else if (dBm <= -67)
+                       pAd->StaCfg.RPIDensity[4] += 1;
+               else if (dBm <= -62)
+                       pAd->StaCfg.RPIDensity[5] += 1;
+               else if (dBm <= -57)
+                       pAd->StaCfg.RPIDensity[6] += 1;
+               else if (dBm > -57)
+                       pAd->StaCfg.RPIDensity[7] += 1;
+
+               return(NDIS_STATUS_FAILURE);
+       }
+
+       // Add Rx size to channel load counter, we should ignore error counts
+       pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount+ 14);
+
+       // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
+       if (pHeader->FC.ToDs)
+       {
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n"));
+               return NDIS_STATUS_FAILURE;
+       }
+
+       // Paul 04-03 for OFDM Rx length issue
+       if (pRxWI->MPDUtotalByteCount > MAX_AGGREGATION_SIZE)
+       {
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n"));
+               return NDIS_STATUS_FAILURE;
+       }
+
+       // Drop not U2M frames, cant's drop here because we will drop beacon in this case
+       // I am kind of doubting the U2M bit operation
+       // if (pRxD->U2M == 0)
+       //      return(NDIS_STATUS_FAILURE);
+
+       // drop decyption fail frame
+       if (pRxINFO->Decrypted && pRxINFO->CipherErr)
+       {
+
+               //
+               // MIC Error
+               //
+               if ((pRxINFO->CipherErr == 2) && pRxINFO->MyBss)
+               {
+                       pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
+                       RTMPReportMicError(pAd, pWpaKey);
+                       DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
+               }
+
+               if (pRxINFO->Decrypted &&
+                       (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg == CIPHER_AES) &&
+                       (pHeader->Sequence == pAd->FragFrame.Sequence))
+               {
+                       //
+                       // Acceptable since the First FragFrame no CipherErr problem.
+                       //
+                       return(NDIS_STATUS_SUCCESS);
+               }
+
+               return(NDIS_STATUS_FAILURE);
+       }
+
+       return(NDIS_STATUS_SUCCESS);
+}
+
+VOID RT28xxUsbStaAsicForceWakeup(
+       IN PRTMP_ADAPTER pAd,
+       IN BOOLEAN       bFromTx)
+{
+    AUTO_WAKEUP_STRUC  AutoWakeupCfg;
+
+       AutoWakeupCfg.word = 0;
+       RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
+
+       AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
+
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
+}
+
+VOID RT28xxUsbStaAsicSleepThenAutoWakeup(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT TbttNumToNextWakeUp)
+{
+       AUTO_WAKEUP_STRUC       AutoWakeupCfg;
+
+       // we have decided to SLEEP, so at least do it for a BEACON period.
+       if (TbttNumToNextWakeUp == 0)
+               TbttNumToNextWakeUp = 1;
+
+       AutoWakeupCfg.word = 0;
+       RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
+
+       AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
+       AutoWakeupCfg.field.EnableAutoWakeup = 1;
+       AutoWakeupCfg.field.AutoLeadTime = 5;
+       RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
+
+       AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);   // send POWER-SAVE command to MCU. Timeout 40us.
+
+       OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
+
+}
+#endif // CONFIG_STA_SUPPORT //
+
+VOID RT28xxUsbMlmeRadioOn(
+       IN PRTMP_ADAPTER pAd)
+{
+    DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOn()\n"));
+
+       if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
+               return;
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+       AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
+               RTMPusecDelay(10000);
+       }
+#endif // CONFIG_STA_SUPPORT //
+       NICResetFromError(pAd);
+
+       // Enable Tx/Rx
+       RTMPEnableRxTx(pAd);
+
+       // Clear Radio off flag
+       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               RTUSBBulkReceive(pAd);
+#endif // CONFIG_STA_SUPPORT //
+
+       // Set LED
+       RTMPSetLED(pAd, LED_RADIO_ON);
+}
+
+VOID RT28xxUsbMlmeRadioOFF(
+       IN PRTMP_ADAPTER pAd)
+{
+       WPDMA_GLO_CFG_STRUC     GloCfg;
+       UINT32  Value, i;
+
+       DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOFF()\n"));
+
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
+               return;
+
+       // Set LED
+       RTMPSetLED(pAd, LED_RADIO_OFF);
+       // Set Radio off flag
+       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // Link down first if any association exists
+               if (INFRA_ON(pAd) || ADHOC_ON(pAd))
+                       LinkDown(pAd, FALSE);
+               RTMPusecDelay(10000);
+
+               //==========================================
+               // Clean up old bss table
+               BssTableInit(&pAd->ScanTab);
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+
+       // Disable MAC Tx/Rx
+       RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+       Value &= (0xfffffff3);
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+       // MAC_SYS_CTRL => value = 0x0 => 40mA
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0);
+
+       // PWR_PIN_CFG => value = 0x0 => 40mA
+       RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0);
+
+       // TX_PIN_CFG => value = 0x0 => 20mA
+       RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0);
+
+       if (pAd->CommonCfg.BBPCurrentBW == BW_40)
+       {
+               // Must using 40MHz.
+               AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
+       }
+       else
+       {
+               // Must using 20MHz.
+               AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
+       }
+
+       // Waiting for DMA idle
+       i = 0;
+       do
+       {
+               RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
+               if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
+                       break;
+
+               RTMPusecDelay(1000);
+       }while (i++ < 100);
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
+#endif // CONFIG_STA_SUPPORT //
+}
+
diff --git a/drivers/staging/rt2870/common/cmm_info.c b/drivers/staging/rt2870/common/cmm_info.c
new file mode 100644 (file)
index 0000000..40792e1
--- /dev/null
@@ -0,0 +1,3712 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+*/
+
+#include "../rt_config.h"
+
+INT    Show_SSID_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_WirelessMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_TxBurst_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_TxPreamble_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_TxPower_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_Channel_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_BGProtection_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_RTSThreshold_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_FragThreshold_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+#ifdef DOT11_N_SUPPORT
+INT    Show_HtBw_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_HtMcs_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_HtGi_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_HtOpMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_HtExtcha_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_HtMpduDensity_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_HtBaWinSize_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_HtRdg_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_HtAmsdu_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_HtAutoBa_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+#endif // DOT11_N_SUPPORT //
+
+INT    Show_CountryRegion_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_CountryRegionABand_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_CountryCode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+#ifdef AGGREGATION_SUPPORT
+INT    Show_PktAggregate_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+#endif // AGGREGATION_SUPPORT //
+
+#ifdef WMM_SUPPORT
+INT    Show_WmmCapable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+#endif // WMM_SUPPORT //
+
+INT    Show_IEEE80211H_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+#ifdef CONFIG_STA_SUPPORT
+INT    Show_NetworkType_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+#endif // CONFIG_STA_SUPPORT //
+
+INT    Show_AuthMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_EncrypType_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_DefaultKeyID_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_Key1_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_Key2_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_Key3_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_Key4_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+INT    Show_WPAPSK_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf);
+
+static struct {
+       CHAR *name;
+       INT (*show_proc)(PRTMP_ADAPTER pAdapter, PUCHAR arg);
+} *PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC, RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC[] = {
+       {"SSID",                                        Show_SSID_Proc},
+       {"WirelessMode",                        Show_WirelessMode_Proc},
+       {"TxBurst",                                     Show_TxBurst_Proc},
+       {"TxPreamble",                          Show_TxPreamble_Proc},
+       {"TxPower",                                     Show_TxPower_Proc},
+       {"Channel",                                     Show_Channel_Proc},
+       {"BGProtection",                        Show_BGProtection_Proc},
+       {"RTSThreshold",                        Show_RTSThreshold_Proc},
+       {"FragThreshold",                       Show_FragThreshold_Proc},
+#ifdef DOT11_N_SUPPORT
+       {"HtBw",                                        Show_HtBw_Proc},
+       {"HtMcs",                                       Show_HtMcs_Proc},
+       {"HtGi",                                        Show_HtGi_Proc},
+       {"HtOpMode",                            Show_HtOpMode_Proc},
+       {"HtExtcha",                            Show_HtExtcha_Proc},
+       {"HtMpduDensity",                       Show_HtMpduDensity_Proc},
+       {"HtBaWinSize",                 Show_HtBaWinSize_Proc},
+       {"HtRdg",                               Show_HtRdg_Proc},
+       {"HtAmsdu",                             Show_HtAmsdu_Proc},
+       {"HtAutoBa",                    Show_HtAutoBa_Proc},
+#endif // DOT11_N_SUPPORT //
+       {"CountryRegion",                       Show_CountryRegion_Proc},
+       {"CountryRegionABand",          Show_CountryRegionABand_Proc},
+       {"CountryCode",                         Show_CountryCode_Proc},
+#ifdef AGGREGATION_SUPPORT
+       {"PktAggregate",                        Show_PktAggregate_Proc},
+#endif
+
+#ifdef WMM_SUPPORT
+       {"WmmCapable",                          Show_WmmCapable_Proc},
+#endif
+       {"IEEE80211H",                          Show_IEEE80211H_Proc},
+#ifdef CONFIG_STA_SUPPORT
+    {"NetworkType",                            Show_NetworkType_Proc},
+#endif // CONFIG_STA_SUPPORT //
+       {"AuthMode",                            Show_AuthMode_Proc},
+       {"EncrypType",                          Show_EncrypType_Proc},
+       {"DefaultKeyID",                        Show_DefaultKeyID_Proc},
+       {"Key1",                                        Show_Key1_Proc},
+       {"Key2",                                        Show_Key2_Proc},
+       {"Key3",                                        Show_Key3_Proc},
+       {"Key4",                                        Show_Key4_Proc},
+       {"WPAPSK",                                      Show_WPAPSK_Proc},
+       {NULL, NULL}
+};
+
+/*
+    ==========================================================================
+    Description:
+        Get Driver version.
+
+    Return:
+    ==========================================================================
+*/
+INT Set_DriverVersion_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               DBGPRINT(RT_DEBUG_TRACE, ("Driver version-%s\n", STA_DRIVER_VERSION));
+#endif // CONFIG_STA_SUPPORT //
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Country Region.
+        This command will not work, if the field of CountryRegion in eeprom is programmed.
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_CountryRegion_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG region;
+
+       region = simple_strtol(arg, 0, 10);
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+       return -EOPNOTSUPP;
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+       // Country can be set only when EEPROM not programmed
+       if (pAd->CommonCfg.CountryRegion & 0x80)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegion_Proc::parameter of CountryRegion in eeprom is programmed \n"));
+               return FALSE;
+       }
+
+       if((region >= 0) && (region <= REGION_MAXIMUM_BG_BAND))
+       {
+               pAd->CommonCfg.CountryRegion = (UCHAR) region;
+       }
+       else if (region == REGION_31_BG_BAND)
+       {
+               pAd->CommonCfg.CountryRegion = (UCHAR) region;
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegion_Proc::parameters out of range\n"));
+               return FALSE;
+       }
+
+       // if set country region, driver needs to be reset
+       BuildChannelList(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegion_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegion));
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Country Region for A band.
+        This command will not work, if the field of CountryRegion in eeprom is programmed.
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_CountryRegionABand_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG region;
+
+       region = simple_strtol(arg, 0, 10);
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+       return -EOPNOTSUPP;
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+       // Country can be set only when EEPROM not programmed
+       if (pAd->CommonCfg.CountryRegionForABand & 0x80)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegionABand_Proc::parameter of CountryRegion in eeprom is programmed \n"));
+               return FALSE;
+       }
+
+       if((region >= 0) && (region <= REGION_MAXIMUM_A_BAND))
+       {
+               pAd->CommonCfg.CountryRegionForABand = (UCHAR) region;
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegionABand_Proc::parameters out of range\n"));
+               return FALSE;
+       }
+
+       // if set country region, driver needs to be reset
+       BuildChannelList(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegionABand_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegionForABand));
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Wireless Mode
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_WirelessMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG   WirelessMode;
+       INT             success = TRUE;
+
+       WirelessMode = simple_strtol(arg, 0, 10);
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               INT MaxPhyMode = PHY_11G;
+
+#ifdef DOT11_N_SUPPORT
+               MaxPhyMode = PHY_11N_5G;
+#endif // DOT11_N_SUPPORT //
+
+               if (WirelessMode <= MaxPhyMode)
+               {
+                       RTMPSetPhyMode(pAd, WirelessMode);
+#ifdef DOT11_N_SUPPORT
+                       if (WirelessMode >= PHY_11ABGN_MIXED)
+                       {
+                               pAd->CommonCfg.BACapability.field.AutoBA = TRUE;
+                               pAd->CommonCfg.REGBACapability.field.AutoBA = TRUE;
+                       }
+                       else
+                       {
+                               pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+                               pAd->CommonCfg.REGBACapability.field.AutoBA = FALSE;
+                       }
+#endif // DOT11_N_SUPPORT //
+                       // Set AdhocMode rates
+                       if (pAd->StaCfg.BssType == BSS_ADHOC)
+                       {
+                               MlmeUpdateTxRates(pAd, FALSE, 0);
+                               MakeIbssBeacon(pAd);           // re-build BEACON frame
+                               AsicEnableIbssSync(pAd);       // copy to on-chip memory
+                       }
+               }
+               else
+               {
+                       success = FALSE;
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       // it is needed to set SSID to take effect
+       if (success == TRUE)
+       {
+#ifdef DOT11_N_SUPPORT
+               SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+               DBGPRINT(RT_DEBUG_TRACE, ("Set_WirelessMode_Proc::(=%ld)\n", WirelessMode));
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Set_WirelessMode_Proc::parameters out of range\n"));
+       }
+
+       return success;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Channel
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_Channel_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       INT             success = TRUE;
+       UCHAR   Channel;
+
+       Channel = (UCHAR) simple_strtol(arg, 0, 10);
+
+       // check if this channel is valid
+       if (ChannelSanity(pAd, Channel) == TRUE)
+       {
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       pAd->CommonCfg.Channel = Channel;
+
+                       if (MONITOR_ON(pAd))
+                       {
+#ifdef DOT11_N_SUPPORT
+                               N_ChannelCheck(pAd);
+                               if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED &&
+                                       pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
+                               {
+                                       N_SetCenCh(pAd);
+                                       AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+                                       AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("BW_40, control_channel(%d), CentralChannel(%d) \n",
+                                                               pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel));
+                               }
+                               else
+#endif // DOT11_N_SUPPORT //
+                               {
+                                       AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+                                       AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAd->CommonCfg.Channel));
+                               }
+                       }
+               }
+#endif // CONFIG_STA_SUPPORT //
+               success = TRUE;
+       }
+       else
+       {
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       success = FALSE;
+#endif // CONFIG_STA_SUPPORT //
+       }
+
+
+       if (success == TRUE)
+               DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", pAd->CommonCfg.Channel));
+
+       return success;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Short Slot Time Enable or Disable
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ShortSlot_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG ShortSlot;
+
+       ShortSlot = simple_strtol(arg, 0, 10);
+
+       if (ShortSlot == 1)
+               pAd->CommonCfg.bUseShortSlotTime = TRUE;
+       else if (ShortSlot == 0)
+               pAd->CommonCfg.bUseShortSlotTime = FALSE;
+       else
+               return FALSE;  //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_ShortSlot_Proc::(ShortSlot=%d)\n", pAd->CommonCfg.bUseShortSlotTime));
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Tx power
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_TxPower_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG TxPower;
+       INT   success = FALSE;
+
+       TxPower = (ULONG) simple_strtol(arg, 0, 10);
+       if (TxPower <= 100)
+       {
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       pAd->CommonCfg.TxPowerDefault = TxPower;
+                       pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
+               }
+#endif // CONFIG_STA_SUPPORT //
+               success = TRUE;
+       }
+       else
+               success = FALSE;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPower_Proc::(TxPowerPercentage=%ld)\n", pAd->CommonCfg.TxPowerPercentage));
+
+       return success;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set 11B/11G Protection
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_BGProtection_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       switch (simple_strtol(arg, 0, 10))
+       {
+               case 0: //AUTO
+                       pAd->CommonCfg.UseBGProtection = 0;
+                       break;
+               case 1: //Always On
+                       pAd->CommonCfg.UseBGProtection = 1;
+                       break;
+               case 2: //Always OFF
+                       pAd->CommonCfg.UseBGProtection = 2;
+                       break;
+               default:  //Invalid argument
+                       return FALSE;
+       }
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_BGProtection_Proc::(BGProtection=%ld)\n", pAd->CommonCfg.UseBGProtection));
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set TxPreamble
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_TxPreamble_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       RT_802_11_PREAMBLE      Preamble;
+
+       Preamble = simple_strtol(arg, 0, 10);
+
+
+       switch (Preamble)
+       {
+               case Rt802_11PreambleShort:
+                       pAd->CommonCfg.TxPreamble = Preamble;
+#ifdef CONFIG_STA_SUPPORT
+                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               MlmeSetTxPreamble(pAd, Rt802_11PreambleShort);
+#endif // CONFIG_STA_SUPPORT //
+                       break;
+               case Rt802_11PreambleLong:
+#ifdef CONFIG_STA_SUPPORT
+               case Rt802_11PreambleAuto:
+                       // if user wants AUTO, initialize to LONG here, then change according to AP's
+                       // capability upon association.
+#endif // CONFIG_STA_SUPPORT //
+                       pAd->CommonCfg.TxPreamble = Preamble;
+#ifdef CONFIG_STA_SUPPORT
+                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               MlmeSetTxPreamble(pAd, Rt802_11PreambleLong);
+#endif // CONFIG_STA_SUPPORT //
+                       break;
+               default: //Invalid argument
+                       return FALSE;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPreamble_Proc::(TxPreamble=%ld)\n", pAd->CommonCfg.TxPreamble));
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set RTS Threshold
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_RTSThreshold_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+        NDIS_802_11_RTS_THRESHOLD           RtsThresh;
+
+       RtsThresh = simple_strtol(arg, 0, 10);
+
+       if((RtsThresh > 0) && (RtsThresh <= MAX_RTS_THRESHOLD))
+               pAd->CommonCfg.RtsThreshold  = (USHORT)RtsThresh;
+#ifdef CONFIG_STA_SUPPORT
+       else if (RtsThresh == 0)
+               pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD;
+#endif // CONFIG_STA_SUPPORT //
+       else
+               return FALSE; //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_RTSThreshold_Proc::(RTSThreshold=%d)\n", pAd->CommonCfg.RtsThreshold));
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Fragment Threshold
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_FragThreshold_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+        NDIS_802_11_FRAGMENTATION_THRESHOLD     FragThresh;
+
+       FragThresh = simple_strtol(arg, 0, 10);
+
+       if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD)
+       {
+               //Illegal FragThresh so we set it to default
+               pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;
+       }
+       else if (FragThresh % 2 == 1)
+       {
+               // The length of each fragment shall always be an even number of octets, except for the last fragment
+               // of an MSDU or MMPDU, which may be either an even or an odd number of octets.
+               pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1);
+       }
+       else
+       {
+               pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh;
+       }
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               if (pAd->CommonCfg.FragmentThreshold == MAX_FRAG_THRESHOLD)
+                       pAd->CommonCfg.bUseZeroToDisableFragment = TRUE;
+               else
+                       pAd->CommonCfg.bUseZeroToDisableFragment = FALSE;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_FragThreshold_Proc::(FragThreshold=%d)\n", pAd->CommonCfg.FragmentThreshold));
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set TxBurst
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_TxBurst_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG TxBurst;
+
+       TxBurst = simple_strtol(arg, 0, 10);
+       if (TxBurst == 1)
+               pAd->CommonCfg.bEnableTxBurst = TRUE;
+       else if (TxBurst == 0)
+               pAd->CommonCfg.bEnableTxBurst = FALSE;
+       else
+               return FALSE;  //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_TxBurst_Proc::(TxBurst=%d)\n", pAd->CommonCfg.bEnableTxBurst));
+
+       return TRUE;
+}
+
+#ifdef AGGREGATION_SUPPORT
+/*
+    ==========================================================================
+    Description:
+        Set TxBurst
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_PktAggregate_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG aggre;
+
+       aggre = simple_strtol(arg, 0, 10);
+
+       if (aggre == 1)
+               pAd->CommonCfg.bAggregationCapable = TRUE;
+       else if (aggre == 0)
+               pAd->CommonCfg.bAggregationCapable = FALSE;
+       else
+               return FALSE;  //Invalid argument
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_PktAggregate_Proc::(AGGRE=%d)\n", pAd->CommonCfg.bAggregationCapable));
+
+       return TRUE;
+}
+#endif
+
+/*
+    ==========================================================================
+    Description:
+        Set IEEE80211H.
+        This parameter is 1 when needs radar detection, otherwise 0
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_IEEE80211H_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+    ULONG ieee80211h;
+
+       ieee80211h = simple_strtol(arg, 0, 10);
+
+       if (ieee80211h == 1)
+               pAd->CommonCfg.bIEEE80211H = TRUE;
+       else if (ieee80211h == 0)
+               pAd->CommonCfg.bIEEE80211H = FALSE;
+       else
+               return FALSE;  //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_IEEE80211H_Proc::(IEEE80211H=%d)\n", pAd->CommonCfg.bIEEE80211H));
+
+       return TRUE;
+}
+
+
+#ifdef DBG
+/*
+    ==========================================================================
+    Description:
+        For Debug information
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_Debug_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       DBGPRINT(RT_DEBUG_TRACE, ("==> Set_Debug_Proc *******************\n"));
+
+    if(simple_strtol(arg, 0, 10) <= RT_DEBUG_LOUD)
+        RTDebugLevel = simple_strtol(arg, 0, 10);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<== Set_Debug_Proc(RTDebugLevel = %ld)\n", RTDebugLevel));
+
+       return TRUE;
+}
+#endif
+
+INT    Show_DescInfo_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Reset statistics counter
+
+    Arguments:
+        pAdapter            Pointer to our adapter
+        arg
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ResetStatCounter_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       //UCHAR           i;
+       //MAC_TABLE_ENTRY *pEntry;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("==>Set_ResetStatCounter_Proc\n"));
+
+       // add the most up-to-date h/w raw counters into software counters
+       NICUpdateRawCounters(pAd);
+
+       NdisZeroMemory(&pAd->WlanCounters, sizeof(COUNTER_802_11));
+       NdisZeroMemory(&pAd->Counters8023, sizeof(COUNTER_802_3));
+       NdisZeroMemory(&pAd->RalinkCounters, sizeof(COUNTER_RALINK));
+
+       // Reset HotSpot counter
+#if 0 // ToDo.
+       for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               pEntry = &pAd->MacTab.Content[i];
+
+               if ((pEntry->Valid == FALSE) || (pEntry->Sst != SST_ASSOC))
+                       continue;
+
+               pEntry->HSCounter.LastDataPacketTime = 0;
+               pEntry->HSCounter.TotalRxByteCount= 0;
+               pEntry->HSCounter.TotalTxByteCount= 0;
+       }
+#endif
+
+
+       return TRUE;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Add WPA key process.
+               In Adhoc WPANONE, bPairwise = 0;  KeyIdx = 0;
+
+       Arguments:
+               pAd                                     Pointer to our adapter
+               pBuf                                                    Pointer to the where the key stored
+
+       Return Value:
+               NDIS_SUCCESS                                    Add key successfully
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+#if 0 // remove by AlbertY
+NDIS_STATUS RTMPWPAAddKeyProc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PVOID                   pBuf)
+{
+       PNDIS_802_11_KEY        pKey;
+       ULONG                           KeyIdx;
+//     NDIS_STATUS             Status;
+//     ULONG   offset; // unused variable, snowpin 2006.07.13
+
+       PUCHAR          pTxMic, pRxMic;
+       BOOLEAN         bTxKey;                 // Set the key as transmit key
+       BOOLEAN         bPairwise;              // Indicate the key is pairwise key
+       BOOLEAN         bKeyRSC;                // indicate the receive  SC set by KeyRSC value.
+                                                               // Otherwise, it will set by the NIC.
+       BOOLEAN         bAuthenticator; // indicate key is set by authenticator.
+       UCHAR           apidx = BSS0;
+
+       pKey = (PNDIS_802_11_KEY) pBuf;
+       KeyIdx = pKey->KeyIndex & 0xff;
+       // Bit 31 of Add-key, Tx Key
+       bTxKey             = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE;
+       // Bit 30 of Add-key PairwiseKey
+       bPairwise          = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE;
+       // Bit 29 of Add-key KeyRSC
+       bKeyRSC            = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE;
+       // Bit 28 of Add-key Authenticator
+       bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE;
+
+       DBGPRINT(RT_DEBUG_TRACE,("RTMPWPAAddKeyProc==>pKey->KeyIndex = %x. bPairwise= %d\n", pKey->KeyIndex, bPairwise));
+       // 1. Check Group / Pairwise Key
+       if (bPairwise)  // Pairwise Key
+       {
+               // 1. KeyIdx must be 0, otherwise, return NDIS_STATUS_INVALID_DATA
+               if (KeyIdx != 0)
+                       return(NDIS_STATUS_INVALID_DATA);
+
+               // 2. Check bTx, it must be true, otherwise, return NDIS_STATUS_INVALID_DATA
+               if (bTxKey == FALSE)
+                       return(NDIS_STATUS_INVALID_DATA);
+
+               // 3. If BSSID is all 0xff, return NDIS_STATUS_INVALID_DATA
+               if (MAC_ADDR_EQUAL(pKey->BSSID, BROADCAST_ADDR))
+                       return(NDIS_STATUS_INVALID_DATA);
+
+               // 3.1 Check Pairwise key length for TKIP key. For AES, it's always 128 bits
+               //if ((pAdapter->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) && (pKey->KeyLength != LEN_TKIP_KEY))
+               if ((pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) && (pKey->KeyLength != LEN_TKIP_KEY))
+                       return(NDIS_STATUS_INVALID_DATA);
+
+               pAd->SharedKey[apidx][KeyIdx].Type = PAIRWISE_KEY;
+
+               if (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2)
+               {
+                       // Send media specific event to start PMKID caching
+                       RTMPIndicateWPA2Status(pAd);
+               }
+       }
+       else
+       {
+               // 1. Check BSSID, if not current BSSID or Bcast, return NDIS_STATUS_INVALID_DATA
+               if ((! MAC_ADDR_EQUAL(pKey->BSSID, BROADCAST_ADDR)) &&
+                       (! MAC_ADDR_EQUAL(pKey->BSSID, pAd->ApCfg.MBSSID[apidx].Bssid)))
+                       return(NDIS_STATUS_INVALID_DATA);
+
+               // 2. Check Key index for supported Group Key
+               if (KeyIdx >= GROUP_KEY_NUM)
+                       return(NDIS_STATUS_INVALID_DATA);
+
+               // 3. Set as default Tx Key if bTxKey is TRUE
+               if (bTxKey == TRUE)
+                       pAd->ApCfg.MBSSID[apidx].DefaultKeyId = (UCHAR) KeyIdx;
+
+               pAd->SharedKey[apidx][KeyIdx].Type = GROUP_KEY;
+       }
+
+       // 4. Select RxMic / TxMic based on Supp / Authenticator
+       if (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPANone)
+       {
+               // for WPA-None Tx, Rx MIC is the same
+               pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
+               pRxMic = pTxMic;
+       }
+       else if (bAuthenticator == TRUE)
+       {
+               pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
+               pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 24;
+       }
+       else
+       {
+               pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
+               pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 24;
+       }
+
+       // 6. Check RxTsc
+       if (bKeyRSC == TRUE)
+       {
+               NdisMoveMemory(pAd->SharedKey[apidx][KeyIdx].RxTsc, &pKey->KeyRSC, 6);
+               NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].PairwiseKey.RxTsc, &pKey->KeyRSC, 6);
+       }
+       else
+       {
+               NdisZeroMemory(pAd->SharedKey[apidx][KeyIdx].RxTsc, 6);
+       }
+
+       // 7. Copy information into Pairwise Key structure.
+       // pKey->KeyLength will include TxMic and RxMic, therefore, we use 16 bytes hardcoded.
+       pAd->SharedKey[apidx][KeyIdx].KeyLen = (UCHAR) pKey->KeyLength;
+       pAd->MacTab.Content[BSSID_WCID].PairwiseKey.KeyLen = (UCHAR)pKey->KeyLength;
+       NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pKey->KeyMaterial, 16);
+       NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].PairwiseKey.Key, &pKey->KeyMaterial, 16);
+       if (pKey->KeyLength == LEN_TKIP_KEY)
+       {
+               // Only Key lenth equal to TKIP key have these
+               NdisMoveMemory(pAd->SharedKey[apidx][KeyIdx].RxMic, pRxMic, 8);
+               NdisMoveMemory(pAd->SharedKey[apidx][KeyIdx].TxMic, pTxMic, 8);
+               NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].PairwiseKey.RxMic, pRxMic, 8);
+               NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].PairwiseKey.TxMic, pTxMic, 8);
+       }
+
+       COPY_MAC_ADDR(pAd->SharedKey[BSS0][KeyIdx].BssId, pKey->BSSID);
+
+       // Init TxTsc to one based on WiFi WPA specs
+       pAd->SharedKey[apidx][KeyIdx].TxTsc[0] = 1;
+       pAd->SharedKey[apidx][KeyIdx].TxTsc[1] = 0;
+       pAd->SharedKey[apidx][KeyIdx].TxTsc[2] = 0;
+       pAd->SharedKey[apidx][KeyIdx].TxTsc[3] = 0;
+       pAd->SharedKey[apidx][KeyIdx].TxTsc[4] = 0;
+       pAd->SharedKey[apidx][KeyIdx].TxTsc[5] = 0;
+       // 4. Init TxTsc to one based on WiFi WPA specs
+       pAd->MacTab.Content[BSSID_WCID].PairwiseKey.TxTsc[0] = 1;
+       pAd->MacTab.Content[BSSID_WCID].PairwiseKey.TxTsc[1] = 0;
+       pAd->MacTab.Content[BSSID_WCID].PairwiseKey.TxTsc[2] = 0;
+       pAd->MacTab.Content[BSSID_WCID].PairwiseKey.TxTsc[3] = 0;
+       pAd->MacTab.Content[BSSID_WCID].PairwiseKey.TxTsc[4] = 0;
+       pAd->MacTab.Content[BSSID_WCID].PairwiseKey.TxTsc[5] = 0;
+
+       if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption3Enabled)
+       {
+               pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_AES;
+               pAd->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = CIPHER_AES;
+       }
+       else if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption2Enabled)
+       {
+               pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_TKIP;
+               pAd->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = CIPHER_TKIP;
+       }
+       else if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption1Enabled)
+       {
+               if (pAd->SharedKey[apidx][KeyIdx].KeyLen == 5)
+               {
+                       pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_WEP64;
+                       pAd->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = CIPHER_WEP64;
+               }
+               else if (pAd->SharedKey[apidx][KeyIdx].KeyLen == 13)
+               {
+                       pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_WEP128;
+                       pAd->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = CIPHER_WEP128;
+               }
+               else
+               {
+                       pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_NONE;
+                       pAd->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = CIPHER_NONE;
+               }
+       }
+       else
+       {
+               pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_NONE;
+               pAd->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = CIPHER_NONE;
+       }
+
+       if ((pAd->OpMode == OPMODE_STA))  // Pairwise Key. Add BSSID to WCTable
+       {
+               pAd->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
+               pAd->MacTab.Content[BSSID_WCID].PairwiseKey.KeyLen = pAd->SharedKey[BSS0][KeyIdx].KeyLen;
+       }
+
+       if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2) ||
+               (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2PSK))
+       {
+               //
+               // On WPA2, Update Group Key Cipher.
+               //
+               if (!bPairwise)
+               {
+                       if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
+                               pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_AES;
+                       else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
+                               pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_TKIP;
+               }
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("pAd->SharedKey[%d][%d].CipherAlg = %d\n", apidx, KeyIdx, pAd->SharedKey[apidx][KeyIdx].CipherAlg));
+
+#if 0
+       DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s Key #%d", CipherName[pAd->SharedKey[apidx][KeyIdx].CipherAlg],KeyIdx));
+       for (i = 0; i < 16; i++)
+       {
+               DBGPRINT_RAW(RT_DEBUG_TRACE, ("%02x:", pAd->SharedKey[apidx][KeyIdx].Key[i]));
+       }
+       DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n         Rx MIC Key = "));
+       for (i = 0; i < 8; i++)
+       {
+               DBGPRINT_RAW(RT_DEBUG_TRACE, ("%02x:", pAd->SharedKey[apidx][KeyIdx].RxMic[i]));
+       }
+       DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n         Tx MIC Key = "));
+       for (i = 0; i < 8; i++)
+       {
+               DBGPRINT_RAW(RT_DEBUG_TRACE, ("%02x:", pAd->SharedKey[apidx][KeyIdx].TxMic[i]));
+       }
+       DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n         RxTSC = "));
+       for (i = 0; i < 6; i++)
+       {
+               DBGPRINT_RAW(RT_DEBUG_TRACE, ("%02x:", pAd->SharedKey[apidx][KeyIdx].RxTsc[i]));
+       }
+#endif
+       DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n pKey-> BSSID:%02x:%02x:%02x:%02x:%02x:%02x \n",
+               pKey->BSSID[0],pKey->BSSID[1],pKey->BSSID[2],pKey->BSSID[3],pKey->BSSID[4],pKey->BSSID[5]));
+
+       if ((bTxKey) && (pAd->OpMode == OPMODE_STA))  // Pairwise Key. Add BSSID to WCTable
+               RTMPAddBSSIDCipher(pAd, BSSID_WCID, pKey, pAd->SharedKey[BSS0][KeyIdx].CipherAlg);
+
+
+       // No matter pairwise key or what leyidx is, always has a copy at on-chip SharedKeytable.
+       AsicAddSharedKeyEntry(pAd,
+                                                 apidx,
+                                                 (UCHAR)KeyIdx,
+                                                 pAd->SharedKey[apidx][KeyIdx].CipherAlg,
+                                                 pAd->SharedKey[apidx][KeyIdx].Key,
+                                                 pAd->SharedKey[apidx][KeyIdx].TxMic,
+                                                 pAd->SharedKey[apidx][KeyIdx].RxMic);
+
+       // The WCID key specified in used at Tx. For STA, always use pairwise key.
+
+       // ad-hoc mode need to specify WAP Group key with WCID index=BSS0Mcast_WCID. Let's always set this key here.
+/*     if (bPairwise == FALSE)
+       {
+               offset = MAC_IVEIV_TABLE_BASE + (BSS0Mcast_WCID * HW_IVEIV_ENTRY_SIZE);
+               NdisZeroMemory(IVEIV, 8);
+               // 1. IV/EIV
+               // Specify key index to find shared key.
+               if ((pAd->SharedKey[BSS0][KeyIdx].CipherAlg==CIPHER_TKIP) ||
+                       (pAd->SharedKey[BSS0][KeyIdx].CipherAlg==CIPHER_AES))
+               IVEIV[3] = 0x20;                // Eiv bit on. keyid always 0 for pairwise key
+               IVEIV[3] |= (KeyIdx<< 6);       // groupkey index is not 0
+               for (i=0; i<8; i++)
+               {
+                       RTMP_IO_WRITE8(pAd, offset+i, IVEIV[i]);
+               }
+
+               // 2. WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:use share key, BSSIdx is 0
+               WCIDAttri = (pAd->SharedKey[BSS0][KeyIdx].CipherAlg<<1)|PAIRWISEKEYTABLE;
+               offset = MAC_WCID_ATTRIBUTE_BASE + (BSS0Mcast_WCID* HW_WCID_ATTRI_SIZE);
+               RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
+
+       }
+
+*/
+
+   if (pAd->SharedKey[apidx][KeyIdx].Type == GROUP_KEY)
+       {
+               // 802.1x port control
+               pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+               DBGPRINT(RT_DEBUG_TRACE,("!!WPA_802_1X_PORT_SECURED!!\n"));
+
+       }
+
+       return (NDIS_STATUS_SUCCESS);
+}
+#endif
+
+BOOLEAN RTMPCheckStrPrintAble(
+    IN  CHAR *pInPutStr,
+    IN  UCHAR strLen)
+{
+    UCHAR i=0;
+
+    for (i=0; i<strLen; i++)
+    {
+        if ((pInPutStr[i] < 0x21) ||
+            (pInPutStr[i] > 0x7E))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Remove WPA Key process
+
+       Arguments:
+               pAd                                     Pointer to our adapter
+               pBuf                                                    Pointer to the where the key stored
+
+       Return Value:
+               NDIS_SUCCESS                                    Add key successfully
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+#ifdef CONFIG_STA_SUPPORT
+VOID    RTMPSetDesiredRates(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  LONG            Rates)
+{
+    NDIS_802_11_RATES aryRates;
+
+    memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES));
+    switch (pAdapter->CommonCfg.PhyMode)
+    {
+        case PHY_11A: // A only
+            switch (Rates)
+            {
+                case 6000000: //6M
+                    aryRates[0] = 0x0c; // 6M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0;
+                    break;
+                case 9000000: //9M
+                    aryRates[0] = 0x12; // 9M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1;
+                    break;
+                case 12000000: //12M
+                    aryRates[0] = 0x18; // 12M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2;
+                    break;
+                case 18000000: //18M
+                    aryRates[0] = 0x24; // 18M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3;
+                    break;
+                case 24000000: //24M
+                    aryRates[0] = 0x30; // 24M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4;
+                    break;
+                case 36000000: //36M
+                    aryRates[0] = 0x48; // 36M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5;
+                    break;
+                case 48000000: //48M
+                    aryRates[0] = 0x60; // 48M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6;
+                    break;
+                case 54000000: //54M
+                    aryRates[0] = 0x6c; // 54M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7;
+                    break;
+                case -1: //Auto
+                default:
+                    aryRates[0] = 0x6c; // 54Mbps
+                    aryRates[1] = 0x60; // 48Mbps
+                    aryRates[2] = 0x48; // 36Mbps
+                    aryRates[3] = 0x30; // 24Mbps
+                    aryRates[4] = 0x24; // 18M
+                    aryRates[5] = 0x18; // 12M
+                    aryRates[6] = 0x12; // 9M
+                    aryRates[7] = 0x0c; // 6M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+                    break;
+            }
+            break;
+        case PHY_11BG_MIXED: // B/G Mixed
+        case PHY_11B: // B only
+        case PHY_11ABG_MIXED: // A/B/G Mixed
+        default:
+            switch (Rates)
+            {
+                case 1000000: //1M
+                    aryRates[0] = 0x02;
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0;
+                    break;
+                case 2000000: //2M
+                    aryRates[0] = 0x04;
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1;
+                    break;
+                case 5000000: //5.5M
+                    aryRates[0] = 0x0b; // 5.5M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2;
+                    break;
+                case 11000000: //11M
+                    aryRates[0] = 0x16; // 11M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3;
+                    break;
+                case 6000000: //6M
+                    aryRates[0] = 0x0c; // 6M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0;
+                    break;
+                case 9000000: //9M
+                    aryRates[0] = 0x12; // 9M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1;
+                    break;
+                case 12000000: //12M
+                    aryRates[0] = 0x18; // 12M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2;
+                    break;
+                case 18000000: //18M
+                    aryRates[0] = 0x24; // 18M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3;
+                    break;
+                case 24000000: //24M
+                    aryRates[0] = 0x30; // 24M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4;
+                    break;
+                case 36000000: //36M
+                    aryRates[0] = 0x48; // 36M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5;
+                    break;
+                case 48000000: //48M
+                    aryRates[0] = 0x60; // 48M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6;
+                    break;
+                case 54000000: //54M
+                    aryRates[0] = 0x6c; // 54M
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7;
+                    break;
+                case -1: //Auto
+                default:
+                    if (pAdapter->CommonCfg.PhyMode == PHY_11B)
+                    { //B Only
+                        aryRates[0] = 0x16; // 11Mbps
+                        aryRates[1] = 0x0b; // 5.5Mbps
+                        aryRates[2] = 0x04; // 2Mbps
+                        aryRates[3] = 0x02; // 1Mbps
+                    }
+                    else
+                    { //(B/G) Mixed or (A/B/G) Mixed
+                        aryRates[0] = 0x6c; // 54Mbps
+                        aryRates[1] = 0x60; // 48Mbps
+                        aryRates[2] = 0x48; // 36Mbps
+                        aryRates[3] = 0x30; // 24Mbps
+                        aryRates[4] = 0x16; // 11Mbps
+                        aryRates[5] = 0x0b; // 5.5Mbps
+                        aryRates[6] = 0x04; // 2Mbps
+                        aryRates[7] = 0x02; // 1Mbps
+                    }
+                    pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+                    break;
+            }
+            break;
+    }
+
+    NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES);
+    NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES));
+    DBGPRINT(RT_DEBUG_TRACE, (" RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n",
+        pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1],
+        pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3],
+        pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5],
+        pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] ));
+    // Changing DesiredRate may affect the MAX TX rate we used to TX frames out
+    MlmeUpdateTxRates(pAdapter, FALSE, 0);
+}
+
+NDIS_STATUS RTMPWPARemoveKeyProc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PVOID                   pBuf)
+{
+       PNDIS_802_11_REMOVE_KEY pKey;
+       ULONG                                   KeyIdx;
+       NDIS_STATUS                     Status = NDIS_STATUS_FAILURE;
+       BOOLEAN         bTxKey;                 // Set the key as transmit key
+       BOOLEAN         bPairwise;              // Indicate the key is pairwise key
+       BOOLEAN         bKeyRSC;                // indicate the receive  SC set by KeyRSC value.
+                                                               // Otherwise, it will set by the NIC.
+       BOOLEAN         bAuthenticator; // indicate key is set by authenticator.
+       INT             i;
+
+       DBGPRINT(RT_DEBUG_TRACE,("---> RTMPWPARemoveKeyProc\n"));
+
+       pKey = (PNDIS_802_11_REMOVE_KEY) pBuf;
+       KeyIdx = pKey->KeyIndex & 0xff;
+       // Bit 31 of Add-key, Tx Key
+       bTxKey             = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE;
+       // Bit 30 of Add-key PairwiseKey
+       bPairwise          = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE;
+       // Bit 29 of Add-key KeyRSC
+       bKeyRSC            = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE;
+       // Bit 28 of Add-key Authenticator
+       bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE;
+
+       // 1. If bTx is TRUE, return failure information
+       if (bTxKey == TRUE)
+               return(NDIS_STATUS_INVALID_DATA);
+
+       // 2. Check Pairwise Key
+       if (bPairwise)
+       {
+               // a. If BSSID is broadcast, remove all pairwise keys.
+               // b. If not broadcast, remove the pairwise specified by BSSID
+               for (i = 0; i < SHARE_KEY_NUM; i++)
+               {
+                       if (MAC_ADDR_EQUAL(pAd->SharedKey[BSS0][i].BssId, pKey->BSSID))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%d)\n", i));
+                               pAd->SharedKey[BSS0][i].KeyLen = 0;
+                               pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE;
+                               AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)i);
+                               Status = NDIS_STATUS_SUCCESS;
+                               break;
+                       }
+               }
+       }
+       // 3. Group Key
+       else
+       {
+               // a. If BSSID is broadcast, remove all group keys indexed
+               // b. If BSSID matched, delete the group key indexed.
+               DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%ld)\n", KeyIdx));
+               pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0;
+               pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE;
+               AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)KeyIdx);
+               Status = NDIS_STATUS_SUCCESS;
+       }
+
+       return (Status);
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+#ifdef CONFIG_STA_SUPPORT
+/*
+       ========================================================================
+
+       Routine Description:
+               Remove All WPA Keys
+
+       Arguments:
+               pAd                                     Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPWPARemoveAllKeys(
+       IN      PRTMP_ADAPTER   pAd)
+{
+
+       UCHAR   i;
+
+       DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveAllKeys(AuthMode=%d, WepStatus=%d)\n", pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus));
+
+       // For WEP/CKIP, there is no need to remove it, since WinXP won't set it again after
+       // Link up. And it will be replaced if user changed it.
+       if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
+               return;
+
+       // For WPA-None, there is no need to remove it, since WinXP won't set it again after
+       // Link up. And it will be replaced if user changed it.
+       if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+               return;
+
+       // set BSSID wcid entry of the Pair-wise Key table as no-security mode
+       AsicRemovePairwiseKeyEntry(pAd, BSS0, BSSID_WCID);
+
+       // set all shared key mode as no-security.
+       for (i = 0; i < SHARE_KEY_NUM; i++)
+    {
+               DBGPRINT(RT_DEBUG_TRACE,("remove %s key #%d\n", CipherName[pAd->SharedKey[BSS0][i].CipherAlg], i));
+               NdisZeroMemory(&pAd->SharedKey[BSS0][i], sizeof(CIPHER_KEY));
+
+               AsicRemoveSharedKeyEntry(pAd, BSS0, i);
+       }
+
+}
+#endif // CONFIG_STA_SUPPORT //
+
+/*
+       ========================================================================
+       Routine Description:
+               Change NIC PHY mode. Re-association may be necessary. possible settings
+               include - PHY_11B, PHY_11BG_MIXED, PHY_11A, and PHY_11ABG_MIXED
+
+       Arguments:
+               pAd - Pointer to our adapter
+               phymode  -
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       ========================================================================
+*/
+VOID   RTMPSetPhyMode(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      ULONG phymode)
+{
+       INT i;
+       // the selected phymode must be supported by the RF IC encoded in E2PROM
+
+       // if no change, do nothing
+       /* bug fix
+       if (pAd->CommonCfg.PhyMode == phymode)
+               return;
+    */
+       pAd->CommonCfg.PhyMode = (UCHAR)phymode;
+
+       DBGPRINT(RT_DEBUG_TRACE,("RTMPSetPhyMode : PhyMode=%d, channel=%d \n", pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel));
+#ifdef EXT_BUILD_CHANNEL_LIST
+       BuildChannelListEx(pAd);
+#else
+       BuildChannelList(pAd);
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+       // sanity check user setting
+       for (i = 0; i < pAd->ChannelListNum; i++)
+       {
+               if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel)
+                       break;
+       }
+
+       if (i == pAd->ChannelListNum)
+       {
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       pAd->CommonCfg.Channel = FirstChannel(pAd);
+#endif // CONFIG_STA_SUPPORT //
+               DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetPhyMode: channel is out of range, use first channel=%d \n", pAd->CommonCfg.Channel));
+       }
+
+       NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
+       NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
+       NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES);
+       switch (phymode) {
+               case PHY_11B:
+                       pAd->CommonCfg.SupRate[0]  = 0x82;        // 1 mbps, in units of 0.5 Mbps, basic rate
+                       pAd->CommonCfg.SupRate[1]  = 0x84;        // 2 mbps, in units of 0.5 Mbps, basic rate
+                       pAd->CommonCfg.SupRate[2]  = 0x8B;        // 5.5 mbps, in units of 0.5 Mbps, basic rate
+                       pAd->CommonCfg.SupRate[3]  = 0x96;        // 11 mbps, in units of 0.5 Mbps, basic rate
+                       pAd->CommonCfg.SupRateLen  = 4;
+                       pAd->CommonCfg.ExtRateLen  = 0;
+                       pAd->CommonCfg.DesireRate[0]  = 2;         // 1 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[1]  = 4;         // 2 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[2]  = 11;    // 5.5 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[3]  = 22;    // 11 mbps, in units of 0.5 Mbps
+                       //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; // This MODE is only FYI. not use
+                       break;
+
+               case PHY_11G:
+               case PHY_11BG_MIXED:
+               case PHY_11ABG_MIXED:
+#ifdef DOT11_N_SUPPORT
+               case PHY_11N_2_4G:
+               case PHY_11ABGN_MIXED:
+               case PHY_11BGN_MIXED:
+               case PHY_11GN_MIXED:
+#endif // DOT11_N_SUPPORT //
+                       pAd->CommonCfg.SupRate[0]  = 0x82;        // 1 mbps, in units of 0.5 Mbps, basic rate
+                       pAd->CommonCfg.SupRate[1]  = 0x84;        // 2 mbps, in units of 0.5 Mbps, basic rate
+                       pAd->CommonCfg.SupRate[2]  = 0x8B;        // 5.5 mbps, in units of 0.5 Mbps, basic rate
+                       pAd->CommonCfg.SupRate[3]  = 0x96;        // 11 mbps, in units of 0.5 Mbps, basic rate
+                       pAd->CommonCfg.SupRate[4]  = 0x12;        // 9 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.SupRate[5]  = 0x24;        // 18 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.SupRate[6]  = 0x48;        // 36 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.SupRate[7]  = 0x6c;        // 54 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.SupRateLen  = 8;
+                       pAd->CommonCfg.ExtRate[0]  = 0x0C;        // 6 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.ExtRate[1]  = 0x18;        // 12 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.ExtRate[2]  = 0x30;        // 24 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.ExtRate[3]  = 0x60;        // 48 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.ExtRateLen  = 4;
+                       pAd->CommonCfg.DesireRate[0]  = 2;         // 1 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[1]  = 4;         // 2 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[2]  = 11;    // 5.5 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[3]  = 22;    // 11 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[4]  = 12;    // 6 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[5]  = 18;    // 9 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[6]  = 24;    // 12 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[7]  = 36;    // 18 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[8]  = 48;    // 24 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[9]  = 72;    // 36 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[10] = 96;    // 48 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[11] = 108;   // 54 mbps, in units of 0.5 Mbps
+                       break;
+
+               case PHY_11A:
+#ifdef DOT11_N_SUPPORT
+               case PHY_11AN_MIXED:
+               case PHY_11AGN_MIXED:
+               case PHY_11N_5G:
+#endif // DOT11_N_SUPPORT //
+                       pAd->CommonCfg.SupRate[0]  = 0x8C;        // 6 mbps, in units of 0.5 Mbps, basic rate
+                       pAd->CommonCfg.SupRate[1]  = 0x12;        // 9 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.SupRate[2]  = 0x98;        // 12 mbps, in units of 0.5 Mbps, basic rate
+                       pAd->CommonCfg.SupRate[3]  = 0x24;        // 18 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.SupRate[4]  = 0xb0;        // 24 mbps, in units of 0.5 Mbps, basic rate
+                       pAd->CommonCfg.SupRate[5]  = 0x48;        // 36 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.SupRate[6]  = 0x60;        // 48 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.SupRate[7]  = 0x6c;        // 54 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.SupRateLen  = 8;
+                       pAd->CommonCfg.ExtRateLen  = 0;
+                       pAd->CommonCfg.DesireRate[0]  = 12;    // 6 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[1]  = 18;    // 9 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[2]  = 24;    // 12 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[3]  = 36;    // 18 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[4]  = 48;    // 24 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[5]  = 72;    // 36 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[6]  = 96;    // 48 mbps, in units of 0.5 Mbps
+                       pAd->CommonCfg.DesireRate[7]  = 108;   // 54 mbps, in units of 0.5 Mbps
+                       //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; // This MODE is only FYI. not use
+                       break;
+
+               default:
+                       break;
+       }
+
+
+       pAd->CommonCfg.BandState = UNKNOWN_BAND;
+}
+
+
+#ifdef DOT11_N_SUPPORT
+/*
+       ========================================================================
+       Routine Description:
+               Caller ensures we has 802.11n support.
+               Calls at setting HT from AP/STASetinformation
+
+       Arguments:
+               pAd - Pointer to our adapter
+               phymode  -
+
+       ========================================================================
+*/
+VOID   RTMPSetHT(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      OID_SET_HT_PHYMODE *pHTPhyMode)
+{
+       //ULONG *pmcs;
+       UINT32  Value = 0;
+       UCHAR   BBPValue = 0;
+       UCHAR   BBP3Value = 0;
+       UCHAR   RxStream = pAd->CommonCfg.RxStream;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : HT_mode(%d), ExtOffset(%d), MCS(%d), BW(%d), STBC(%d), SHORTGI(%d)\n",
+                                                                               pHTPhyMode->HtMode, pHTPhyMode->ExtOffset,
+                                                                               pHTPhyMode->MCS, pHTPhyMode->BW,
+                                                                               pHTPhyMode->STBC, pHTPhyMode->SHORTGI));
+
+       // Don't zero supportedHyPhy structure.
+       RTMPZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability));
+       RTMPZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo));
+       RTMPZeroMemory(&pAd->CommonCfg.NewExtChanOffset, sizeof(pAd->CommonCfg.NewExtChanOffset));
+       RTMPZeroMemory(&pAd->CommonCfg.DesiredHtPhy, sizeof(pAd->CommonCfg.DesiredHtPhy));
+
+       if (pAd->CommonCfg.bRdg)
+       {
+               pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 1;
+               pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 1;
+       }
+       else
+       {
+               pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 0;
+               pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 0;
+       }
+
+       pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor = 3;
+       pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor = 3;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : RxBAWinLimit = %d\n", pAd->CommonCfg.BACapability.field.RxBAWinLimit));
+
+       // Mimo power save, A-MSDU size,
+       pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable;
+       pAd->CommonCfg.DesiredHtPhy.AmsduSize = (UCHAR)pAd->CommonCfg.BACapability.field.AmsduSize;
+       pAd->CommonCfg.DesiredHtPhy.MimoPs = (UCHAR)pAd->CommonCfg.BACapability.field.MMPSmode;
+       pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
+
+       pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize;
+       pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode;
+       pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : AMsduSize = %d, MimoPs = %d, MpduDensity = %d, MaxRAmpduFactor = %d\n",
+                                                                                                       pAd->CommonCfg.DesiredHtPhy.AmsduSize,
+                                                                                                       pAd->CommonCfg.DesiredHtPhy.MimoPs,
+                                                                                                       pAd->CommonCfg.DesiredHtPhy.MpduDensity,
+                                                                                                       pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor));
+
+       if(pHTPhyMode->HtMode == HTMODE_GF)
+       {
+               pAd->CommonCfg.HtCapability.HtCapInfo.GF = 1;
+               pAd->CommonCfg.DesiredHtPhy.GF = 1;
+       }
+       else
+               pAd->CommonCfg.DesiredHtPhy.GF = 0;
+
+       // Decide Rx MCSSet
+       switch (RxStream)
+       {
+               case 1:
+                       pAd->CommonCfg.HtCapability.MCSSet[0] =  0xff;
+                       pAd->CommonCfg.HtCapability.MCSSet[1] =  0x00;
+                       break;
+
+               case 2:
+                       pAd->CommonCfg.HtCapability.MCSSet[0] =  0xff;
+                       pAd->CommonCfg.HtCapability.MCSSet[1] =  0xff;
+                       break;
+
+               case 3: // 3*3
+                       pAd->CommonCfg.HtCapability.MCSSet[0] =  0xff;
+                       pAd->CommonCfg.HtCapability.MCSSet[1] =  0xff;
+                       pAd->CommonCfg.HtCapability.MCSSet[2] =  0xff;
+                       break;
+       }
+
+       if (pAd->CommonCfg.bForty_Mhz_Intolerant && (pAd->CommonCfg.Channel <= 14) && (pHTPhyMode->BW == BW_40) )
+       {
+               pHTPhyMode->BW = BW_20;
+               pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant = 1;
+       }
+
+       if(pHTPhyMode->BW == BW_40)
+       {
+               pAd->CommonCfg.HtCapability.MCSSet[4] = 0x1; // MCS 32
+               pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 1;
+               if (pAd->CommonCfg.Channel <= 14)
+                       pAd->CommonCfg.HtCapability.HtCapInfo.CCKmodein40 = 1;
+
+               pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 1;
+               pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1;
+               pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = (pHTPhyMode->ExtOffset == EXTCHA_BELOW)? (EXTCHA_BELOW): EXTCHA_ABOVE;
+               // Set Regsiter for extension channel position.
+               RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBP3Value);
+               if ((pHTPhyMode->ExtOffset == EXTCHA_BELOW))
+               {
+                       Value |= 0x1;
+                       BBP3Value |= (0x20);
+                       RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+               }
+               else if ((pHTPhyMode->ExtOffset == EXTCHA_ABOVE))
+               {
+                       Value &= 0xfe;
+                       BBP3Value &= (~0x20);
+                       RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+               }
+
+               // Turn on BBP 40MHz mode now only as AP .
+               // Sta can turn on BBP 40MHz after connection with 40MHz AP. Sta only broadcast 40MHz capability before connection.
+               if ((pAd->OpMode == OPMODE_AP) || INFRA_ON(pAd) || ADHOC_ON(pAd)
+                       )
+               {
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+                       BBPValue &= (~0x18);
+                       BBPValue |= 0x10;
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBP3Value);
+                       pAd->CommonCfg.BBPCurrentBW = BW_40;
+               }
+       }
+       else
+       {
+               pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 0;
+               pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 0;
+               pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0;
+               pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = EXTCHA_NONE;
+               pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
+               // Turn on BBP 20MHz mode by request here.
+               {
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+                       BBPValue &= (~0x18);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+                       pAd->CommonCfg.BBPCurrentBW = BW_20;
+               }
+       }
+
+       if(pHTPhyMode->STBC == STBC_USE)
+       {
+               pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 1;
+               pAd->CommonCfg.DesiredHtPhy.TxSTBC = 1;
+               pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC = 1;
+               pAd->CommonCfg.DesiredHtPhy.RxSTBC = 1;
+       }
+       else
+       {
+               pAd->CommonCfg.DesiredHtPhy.TxSTBC = 0;
+               pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0;
+       }
+
+#ifdef RT2870
+       /* Frank recommend ,If not, Tx maybe block in high power. Rx has no problem*/
+       if(IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
+       {
+               pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 0;
+               pAd->CommonCfg.DesiredHtPhy.TxSTBC = 0;
+       }
+#endif // RT2870 //
+
+       if(pHTPhyMode->SHORTGI == GI_400)
+       {
+               pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 1;
+               pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 1;
+               pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 1;
+               pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 1;
+       }
+       else
+       {
+               pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 0;
+               pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 0;
+               pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 0;
+               pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 0;
+       }
+
+       // We support link adaptation for unsolicit MCS feedback, set to 2.
+       pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_NONE; //MCSFBK_UNSOLICIT;
+       pAd->CommonCfg.AddHTInfo.ControlChan = pAd->CommonCfg.Channel;
+       // 1, the extension channel above the control channel.
+
+       // EDCA parameters used for AP's own transmission
+       if (pAd->CommonCfg.APEdcaParm.bValid == FALSE)
+       {
+               pAd->CommonCfg.APEdcaParm.bValid = TRUE;
+               pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3;
+               pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7;
+               pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1;
+               pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1;
+
+               pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4;
+               pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4;
+               pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3;
+               pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2;
+
+               pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6;
+               pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10;
+               pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4;
+               pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3;
+
+               pAd->CommonCfg.APEdcaParm.Txop[0]  = 0;
+               pAd->CommonCfg.APEdcaParm.Txop[1]  = 0;
+               pAd->CommonCfg.APEdcaParm.Txop[2]  = 94;
+               pAd->CommonCfg.APEdcaParm.Txop[3]  = 47;
+       }
+       AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               RTMPSetIndividualHT(pAd, 0);
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+}
+
+/*
+       ========================================================================
+       Routine Description:
+               Caller ensures we has 802.11n support.
+               Calls at setting HT from AP/STASetinformation
+
+       Arguments:
+               pAd - Pointer to our adapter
+               phymode  -
+
+       ========================================================================
+*/
+VOID   RTMPSetIndividualHT(
+       IN      PRTMP_ADAPTER           pAd,
+       IN      UCHAR                           apidx)
+{
+       PRT_HT_PHY_INFO         pDesired_ht_phy = NULL;
+       UCHAR   TxStream = pAd->CommonCfg.TxStream;
+       UCHAR   DesiredMcs      = MCS_AUTO;
+
+       do
+       {
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       pDesired_ht_phy = &pAd->StaCfg.DesiredHtPhyInfo;
+                       DesiredMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
+                       //pAd->StaCfg.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE;
+                               break;
+               }
+#endif // CONFIG_STA_SUPPORT //
+       } while (FALSE);
+
+       if (pDesired_ht_phy == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx));
+               return;
+       }
+       RTMPZeroMemory(pDesired_ht_phy, sizeof(RT_HT_PHY_INFO));
+
+       DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs));
+       // Check the validity of MCS
+       if ((TxStream == 1) && ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15)))
+       {
+               DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n", DesiredMcs));
+               DesiredMcs = MCS_7;
+       }
+
+       if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20) && (DesiredMcs == MCS_32))
+       {
+               DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n"));
+               DesiredMcs = MCS_0;
+       }
+
+       pDesired_ht_phy->bHtEnable = TRUE;
+
+       // Decide desired Tx MCS
+       switch (TxStream)
+       {
+               case 1:
+                       if (DesiredMcs == MCS_AUTO)
+                       {
+                               pDesired_ht_phy->MCSSet[0]= 0xff;
+                               pDesired_ht_phy->MCSSet[1]= 0x00;
+                       }
+                       else if (DesiredMcs <= MCS_7)
+                       {
+                               pDesired_ht_phy->MCSSet[0]= 1<<DesiredMcs;
+                               pDesired_ht_phy->MCSSet[1]= 0x00;
+                       }
+                       break;
+
+               case 2:
+                       if (DesiredMcs == MCS_AUTO)
+                       {
+                               pDesired_ht_phy->MCSSet[0]= 0xff;
+                               pDesired_ht_phy->MCSSet[1]= 0xff;
+                       }
+                       else if (DesiredMcs <= MCS_15)
+                       {
+                               ULONG mode;
+
+                               mode = DesiredMcs / 8;
+                               if (mode < 2)
+                                       pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8));
+                       }
+                       break;
+
+               case 3: // 3*3
+                       if (DesiredMcs == MCS_AUTO)
+                       {
+                               /* MCS0 ~ MCS23, 3 bytes */
+                               pDesired_ht_phy->MCSSet[0]= 0xff;
+                               pDesired_ht_phy->MCSSet[1]= 0xff;
+                               pDesired_ht_phy->MCSSet[2]= 0xff;
+                       }
+                       else if (DesiredMcs <= MCS_23)
+                       {
+                               ULONG mode;
+
+                               mode = DesiredMcs / 8;
+                               if (mode < 3)
+                                       pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8));
+                       }
+                       break;
+       }
+
+       if(pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40)
+       {
+               if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32)
+                       pDesired_ht_phy->MCSSet[4] = 0x1;
+       }
+
+       // update HT Rate setting
+    if (pAd->OpMode == OPMODE_STA)
+        MlmeUpdateHtTxRates(pAd, BSS0);
+    else
+           MlmeUpdateHtTxRates(pAd, apidx);
+}
+
+
+/*
+       ========================================================================
+       Routine Description:
+               Update HT IE from our capability.
+
+       Arguments:
+               Send all HT IE in beacon/probe rsp/assoc rsp/action frame.
+
+
+       ========================================================================
+*/
+VOID   RTMPUpdateHTIE(
+       IN      RT_HT_CAPABILITY        *pRtHt,
+       IN              UCHAR                           *pMcsSet,
+       OUT             HT_CAPABILITY_IE *pHtCapability,
+       OUT             ADD_HT_INFO_IE          *pAddHtInfo)
+{
+       RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE));
+       RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE));
+
+               pHtCapability->HtCapInfo.ChannelWidth = pRtHt->ChannelWidth;
+               pHtCapability->HtCapInfo.MimoPs = pRtHt->MimoPs;
+               pHtCapability->HtCapInfo.GF = pRtHt->GF;
+               pHtCapability->HtCapInfo.ShortGIfor20 = pRtHt->ShortGIfor20;
+               pHtCapability->HtCapInfo.ShortGIfor40 = pRtHt->ShortGIfor40;
+               pHtCapability->HtCapInfo.TxSTBC = pRtHt->TxSTBC;
+               pHtCapability->HtCapInfo.RxSTBC = pRtHt->RxSTBC;
+               pHtCapability->HtCapInfo.AMsduSize = pRtHt->AmsduSize;
+               pHtCapability->HtCapParm.MaxRAmpduFactor = pRtHt->MaxRAmpduFactor;
+               pHtCapability->HtCapParm.MpduDensity = pRtHt->MpduDensity;
+
+               pAddHtInfo->AddHtInfo.ExtChanOffset = pRtHt->ExtChanOffset ;
+               pAddHtInfo->AddHtInfo.RecomWidth = pRtHt->RecomWidth;
+               pAddHtInfo->AddHtInfo2.OperaionMode = pRtHt->OperaionMode;
+               pAddHtInfo->AddHtInfo2.NonGfPresent = pRtHt->NonGfPresent;
+               RTMPMoveMemory(pAddHtInfo->MCSSet, /*pRtHt->MCSSet*/pMcsSet, 4); // rt2860 only support MCS max=32, no need to copy all 16 uchar.
+
+        DBGPRINT(RT_DEBUG_TRACE,("RTMPUpdateHTIE <== \n"));
+}
+#endif // DOT11_N_SUPPORT //
+
+/*
+       ========================================================================
+       Description:
+               Add Client security information into ASIC WCID table and IVEIV table.
+    Return:
+       ========================================================================
+*/
+VOID   RTMPAddWcidAttributeEntry(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   BssIdx,
+       IN      UCHAR                   KeyIdx,
+       IN      UCHAR                   CipherAlg,
+       IN      MAC_TABLE_ENTRY *pEntry)
+{
+       UINT32          WCIDAttri = 0;
+       USHORT          offset;
+       UCHAR           IVEIV = 0;
+       USHORT          Wcid = 0;
+
+       {
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       if (BssIdx > BSS0)
+                       {
+                               DBGPRINT(RT_DEBUG_ERROR, ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for Infra link. \n", BssIdx));
+                               return;
+                       }
+
+                       // 1.   In ADHOC mode, the AID is wcid number. And NO mesh link exists.
+                       // 2.   In Infra mode, the AID:1 MUST be wcid of infra STA.
+                       //                                         the AID:2~ assign to mesh link entry.
+                       if (pEntry && ADHOC_ON(pAd))
+                               Wcid = pEntry->Aid;
+                       else if (pEntry && INFRA_ON(pAd))
+                       {
+#ifdef QOS_DLS_SUPPORT
+                               if (pEntry->ValidAsDls == TRUE)
+                                       Wcid = pEntry->Aid;
+                               else
+#endif // QOS_DLS_SUPPORT //
+                               Wcid = BSSID_WCID;
+                       }
+                       else
+                               Wcid = MCAST_WCID;
+               }
+#endif // CONFIG_STA_SUPPORT //
+       }
+
+       // Update WCID attribute table
+       offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               if (pEntry && pEntry->ValidAsMesh)
+                       WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE;
+#ifdef QOS_DLS_SUPPORT
+               else if ((pEntry) && (pEntry->ValidAsDls) &&
+                                       ((CipherAlg == CIPHER_TKIP) ||
+                                       (CipherAlg == CIPHER_TKIP_NO_MIC) ||
+                                       (CipherAlg == CIPHER_AES) ||
+                                       (CipherAlg == CIPHER_NONE)))
+                       WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE;
+#endif // QOS_DLS_SUPPORT //
+               else
+                       WCIDAttri = (CipherAlg<<1) | SHAREDKEYTABLE;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
+
+
+       // Update IV/EIV table
+       offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE);
+
+       // WPA mode
+       if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) || (CipherAlg == CIPHER_AES))
+       {
+               // Eiv bit on. keyid always is 0 for pairwise key
+               IVEIV = (KeyIdx <<6) | 0x20;
+       }
+       else
+       {
+               // WEP KeyIdx is default tx key.
+               IVEIV = (KeyIdx << 6);
+       }
+
+       // For key index and ext IV bit, so only need to update the position(offset+3).
+#ifdef RT2870
+       RTUSBMultiWrite_OneByte(pAd, offset+3, &IVEIV);
+#endif // RT2870 //
+
+       DBGPRINT(RT_DEBUG_TRACE,("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n",Wcid, KeyIdx, CipherName[CipherAlg]));
+       DBGPRINT(RT_DEBUG_TRACE,("      WCIDAttri = 0x%x \n",  WCIDAttri));
+
+}
+
+/*
+    ==========================================================================
+    Description:
+        Parse encryption type
+Arguments:
+    pAdapter                    Pointer to our adapter
+    wrq                         Pointer to the ioctl argument
+
+    Return Value:
+        None
+
+    Note:
+    ==========================================================================
+*/
+CHAR *GetEncryptType(CHAR enc)
+{
+    if(enc == Ndis802_11WEPDisabled)
+        return "NONE";
+    if(enc == Ndis802_11WEPEnabled)
+       return "WEP";
+    if(enc == Ndis802_11Encryption2Enabled)
+       return "TKIP";
+    if(enc == Ndis802_11Encryption3Enabled)
+       return "AES";
+       if(enc == Ndis802_11Encryption4Enabled)
+       return "TKIPAES";
+    else
+       return "UNKNOW";
+}
+
+CHAR *GetAuthMode(CHAR auth)
+{
+    if(auth == Ndis802_11AuthModeOpen)
+       return "OPEN";
+    if(auth == Ndis802_11AuthModeShared)
+       return "SHARED";
+       if(auth == Ndis802_11AuthModeAutoSwitch)
+       return "AUTOWEP";
+    if(auth == Ndis802_11AuthModeWPA)
+       return "WPA";
+    if(auth == Ndis802_11AuthModeWPAPSK)
+       return "WPAPSK";
+    if(auth == Ndis802_11AuthModeWPANone)
+       return "WPANONE";
+    if(auth == Ndis802_11AuthModeWPA2)
+       return "WPA2";
+    if(auth == Ndis802_11AuthModeWPA2PSK)
+       return "WPA2PSK";
+       if(auth == Ndis802_11AuthModeWPA1WPA2)
+       return "WPA1WPA2";
+       if(auth == Ndis802_11AuthModeWPA1PSKWPA2PSK)
+       return "WPA1PSKWPA2PSK";
+
+       return "UNKNOW";
+}
+
+#if 1 //#ifndef UCOS
+/*
+    ==========================================================================
+    Description:
+        Get site survey results
+       Arguments:
+           pAdapter                    Pointer to our adapter
+           wrq                         Pointer to the ioctl argument
+
+    Return Value:
+        None
+
+    Note:
+        Usage:
+                       1.) UI needs to wait 4 seconds after issue a site survey command
+                       2.) iwpriv ra0 get_site_survey
+                       3.) UI needs to prepare at least 4096bytes to get the results
+    ==========================================================================
+*/
+#define        LINE_LEN        (4+33+20+8+10+9+7+3)    // Channel+SSID+Bssid+WepStatus+AuthMode+Signal+WiressMode+NetworkType
+VOID RTMPIoctlGetSiteSurvey(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq)
+{
+       CHAR            *msg;
+       INT             i=0;
+       INT                     WaitCnt;
+       INT             Status=0;
+       CHAR            Ssid[MAX_LEN_OF_SSID +1];
+    INT         Rssi = 0, max_len = LINE_LEN;
+       UINT        Rssi_Quality = 0;
+       NDIS_802_11_NETWORK_TYPE    wireless_mode;
+
+       os_alloc_mem(NULL, (PUCHAR *)&msg, sizeof(CHAR)*((MAX_LEN_OF_BSS_TABLE)*max_len));
+
+       if (msg == NULL)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - msg memory alloc fail.\n"));
+               return;
+       }
+
+       memset(msg, 0 ,(MAX_LEN_OF_BSS_TABLE)*max_len );
+       memset(Ssid, 0 ,(MAX_LEN_OF_SSID +1));
+       sprintf(msg,"%s","\n");
+       sprintf(msg+strlen(msg),"%-4s%-33s%-20s%-8s%-10s%-9s%-7s%-3s\n",
+           "Ch", "SSID", "BSSID", "Enc", "Auth", "Siganl(%)", "W-Mode", " NT");
+
+
+       WaitCnt = 0;
+#ifdef CONFIG_STA_SUPPORT
+       pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE;
+       while ((ScanRunning(pAdapter) == TRUE) && (WaitCnt++ < 200))
+               OS_WAIT(500);
+#endif // CONFIG_STA_SUPPORT //
+
+       for(i=0; i<pAdapter->ScanTab.BssNr ;i++)
+       {
+               if( pAdapter->ScanTab.BssEntry[i].Channel==0)
+                       break;
+
+               if((strlen(msg)+max_len ) >= IW_SCAN_MAX_DATA)
+                       break;
+
+               //Channel
+               sprintf(msg+strlen(msg),"%-4d", pAdapter->ScanTab.BssEntry[i].Channel);
+               //SSID
+               memcpy(Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen);
+               Ssid[pAdapter->ScanTab.BssEntry[i].SsidLen] = '\0';
+               sprintf(msg+strlen(msg),"%-33s", Ssid);
+               //BSSID
+               sprintf(msg+strlen(msg),"%02x:%02x:%02x:%02x:%02x:%02x   ",
+                       pAdapter->ScanTab.BssEntry[i].Bssid[0],
+                       pAdapter->ScanTab.BssEntry[i].Bssid[1],
+                       pAdapter->ScanTab.BssEntry[i].Bssid[2],
+                       pAdapter->ScanTab.BssEntry[i].Bssid[3],
+                       pAdapter->ScanTab.BssEntry[i].Bssid[4],
+                       pAdapter->ScanTab.BssEntry[i].Bssid[5]);
+               //Encryption Type
+               sprintf(msg+strlen(msg),"%-8s",GetEncryptType(pAdapter->ScanTab.BssEntry[i].WepStatus));
+               //Authentication Mode
+               if (pAdapter->ScanTab.BssEntry[i].WepStatus == Ndis802_11WEPEnabled)
+                       sprintf(msg+strlen(msg),"%-10s", "UNKNOW");
+               else
+                       sprintf(msg+strlen(msg),"%-10s",GetAuthMode(pAdapter->ScanTab.BssEntry[i].AuthMode));
+               // Rssi
+               Rssi = (INT)pAdapter->ScanTab.BssEntry[i].Rssi;
+               if (Rssi >= -50)
+                       Rssi_Quality = 100;
+               else if (Rssi >= -80)    // between -50 ~ -80dbm
+                       Rssi_Quality = (UINT)(24 + ((Rssi + 80) * 26)/10);
+               else if (Rssi >= -90)   // between -80 ~ -90dbm
+                       Rssi_Quality = (UINT)(((Rssi + 90) * 26)/10);
+               else    // < -84 dbm
+                       Rssi_Quality = 0;
+               sprintf(msg+strlen(msg),"%-9d", Rssi_Quality);
+               // Wireless Mode
+               wireless_mode = NetworkTypeInUseSanity(&pAdapter->ScanTab.BssEntry[i]);
+               if (wireless_mode == Ndis802_11FH ||
+                       wireless_mode == Ndis802_11DS)
+                       sprintf(msg+strlen(msg),"%-7s", "11b");
+               else if (wireless_mode == Ndis802_11OFDM5)
+                       sprintf(msg+strlen(msg),"%-7s", "11a");
+               else if (wireless_mode == Ndis802_11OFDM5_N)
+                       sprintf(msg+strlen(msg),"%-7s", "11a/n");
+               else if (wireless_mode == Ndis802_11OFDM24)
+                       sprintf(msg+strlen(msg),"%-7s", "11b/g");
+               else if (wireless_mode == Ndis802_11OFDM24_N)
+                       sprintf(msg+strlen(msg),"%-7s", "11b/g/n");
+               else
+                       sprintf(msg+strlen(msg),"%-7s", "unknow");
+               //Network Type
+               if (pAdapter->ScanTab.BssEntry[i].BssType == BSS_ADHOC)
+                       sprintf(msg+strlen(msg),"%-3s", " Ad");
+               else
+                       sprintf(msg+strlen(msg),"%-3s", " In");
+
+        sprintf(msg+strlen(msg),"\n");
+       }
+
+#ifdef CONFIG_STA_SUPPORT
+       pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE;
+#endif // CONFIG_STA_SUPPORT //
+       wrq->u.data.length = strlen(msg);
+       Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - wrq->u.data.length = %d\n", wrq->u.data.length));
+       os_free_mem(NULL, (PUCHAR)msg);
+}
+
+
+#define        MAC_LINE_LEN    (14+4+4+10+10+10+6+6)   // Addr+aid+psm+datatime+rxbyte+txbyte+current tx rate+last tx rate
+VOID RTMPIoctlGetMacTable(
+       IN PRTMP_ADAPTER pAd,
+       IN struct iwreq *wrq)
+{
+       INT i;
+       RT_802_11_MAC_TABLE MacTab;
+       char *msg;
+
+       MacTab.Num = 0;
+       for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               if (pAd->MacTab.Content[i].ValidAsCLI && (pAd->MacTab.Content[i].Sst == SST_ASSOC))
+               {
+                       COPY_MAC_ADDR(MacTab.Entry[MacTab.Num].Addr, &pAd->MacTab.Content[i].Addr);
+                       MacTab.Entry[MacTab.Num].Aid = (UCHAR)pAd->MacTab.Content[i].Aid;
+                       MacTab.Entry[MacTab.Num].Psm = pAd->MacTab.Content[i].PsMode;
+#ifdef DOT11_N_SUPPORT
+                       MacTab.Entry[MacTab.Num].MimoPs = pAd->MacTab.Content[i].MmpsMode;
+#endif // DOT11_N_SUPPORT //
+
+                       // Fill in RSSI per entry
+                       MacTab.Entry[MacTab.Num].AvgRssi0 = pAd->MacTab.Content[i].RssiSample.AvgRssi0;
+                       MacTab.Entry[MacTab.Num].AvgRssi1 = pAd->MacTab.Content[i].RssiSample.AvgRssi1;
+                       MacTab.Entry[MacTab.Num].AvgRssi2 = pAd->MacTab.Content[i].RssiSample.AvgRssi2;
+
+                       // the connected time per entry
+                       MacTab.Entry[MacTab.Num].ConnectedTime = pAd->MacTab.Content[i].StaConnectTime;
+#if 0 // ToDo
+                       MacTab.Entry[MacTab.Num].HSCounter.LastDataPacketTime = pAd->MacTab.Content[i].HSCounter.LastDataPacketTime;
+                       MacTab.Entry[MacTab.Num].HSCounter.TotalRxByteCount = pAd->MacTab.Content[i].HSCounter.TotalRxByteCount;
+                       MacTab.Entry[MacTab.Num].HSCounter.TotalTxByteCount = pAd->MacTab.Content[i].HSCounter.TotalTxByteCount;
+#endif
+                       MacTab.Entry[MacTab.Num].TxRate.field.MCS = pAd->MacTab.Content[i].HTPhyMode.field.MCS;
+                       MacTab.Entry[MacTab.Num].TxRate.field.BW = pAd->MacTab.Content[i].HTPhyMode.field.BW;
+                       MacTab.Entry[MacTab.Num].TxRate.field.ShortGI = pAd->MacTab.Content[i].HTPhyMode.field.ShortGI;
+                       MacTab.Entry[MacTab.Num].TxRate.field.STBC = pAd->MacTab.Content[i].HTPhyMode.field.STBC;
+                       MacTab.Entry[MacTab.Num].TxRate.field.rsv = pAd->MacTab.Content[i].HTPhyMode.field.rsv;
+                       MacTab.Entry[MacTab.Num].TxRate.field.MODE = pAd->MacTab.Content[i].HTPhyMode.field.MODE;
+                       MacTab.Entry[MacTab.Num].TxRate.word = pAd->MacTab.Content[i].HTPhyMode.word;
+
+                       MacTab.Num += 1;
+               }
+       }
+       wrq->u.data.length = sizeof(RT_802_11_MAC_TABLE);
+       if (copy_to_user(wrq->u.data.pointer, &MacTab, wrq->u.data.length))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__));
+       }
+
+       msg = (CHAR *) kmalloc(sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN), MEM_ALLOC_FLAG);
+       memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN );
+       sprintf(msg,"%s","\n");
+       sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-10s%-10s%-10s%-6s%-6s\n",
+               "MAC", "AID", "PSM", "LDT", "RxB", "TxB","CTxR", "LTxR");
+
+       for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+               if (pEntry->ValidAsCLI && (pEntry->Sst == SST_ASSOC))
+               {
+                       if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) )
+                               break;
+                       sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x  ",
+                               pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+                               pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]);
+                       sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid);
+                       sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode);
+                       sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); // ToDo
+                       sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); // ToDo
+                       sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); // ToDo
+                       sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]);
+                       sprintf(msg+strlen(msg),"%-6d\n",0/*RateIdToMbps[pAd->MacTab.Content[i].LastTxRate]*/); // ToDo
+               }
+       }
+       // for compatible with old API just do the printk to console
+       //wrq->u.data.length = strlen(msg);
+       //if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("%s", msg));
+       }
+
+       kfree(msg);
+}
+#endif // UCOS //
+
+#ifdef DOT11_N_SUPPORT
+INT    Set_BASetup_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+    UCHAR mac[6], tid;
+       char *token, sepValue[] = ":", DASH = '-';
+       INT i;
+    MAC_TABLE_ENTRY *pEntry;
+
+/*
+       The BASetup inupt string format should be xx:xx:xx:xx:xx:xx-d,
+               =>The six 2 digit hex-decimal number previous are the Mac address,
+               =>The seventh decimal number is the tid value.
+*/
+       //printk("\n%s\n", arg);
+
+       if(strlen(arg) < 19)  //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.
+               return FALSE;
+
+       token = strchr(arg, DASH);
+       if ((token != NULL) && (strlen(token)>1))
+       {
+               tid = simple_strtol((token+1), 0, 10);
+               if (tid > 15)
+                       return FALSE;
+
+               *token = '\0';
+               for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
+               {
+                       if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
+                               return FALSE;
+                       AtoH(token, (PUCHAR)(&mac[i]), 1);
+               }
+               if(i != 6)
+                       return FALSE;
+
+               printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", mac[0], mac[1],
+                               mac[2], mac[3], mac[4], mac[5], tid);
+
+           pEntry = MacTableLookup(pAd, mac);
+
+       if (pEntry) {
+               printk("\nSetup BA Session: Tid = %d\n", tid);
+               BAOriSessionSetUp(pAd, pEntry, tid, 0, 100, TRUE);
+       }
+
+               return TRUE;
+       }
+
+       return FALSE;
+
+}
+
+INT    Set_BADecline_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG bBADecline;
+
+       bBADecline = simple_strtol(arg, 0, 10);
+
+       if (bBADecline == 0)
+       {
+               pAd->CommonCfg.bBADecline = FALSE;
+       }
+       else if (bBADecline == 1)
+       {
+               pAd->CommonCfg.bBADecline = TRUE;
+       }
+       else
+       {
+               return FALSE; //Invalid argument
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_BADecline_Proc::(BADecline=%d)\n", pAd->CommonCfg.bBADecline));
+
+       return TRUE;
+}
+
+INT    Set_BAOriTearDown_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+    UCHAR mac[6], tid;
+       char *token, sepValue[] = ":", DASH = '-';
+       INT i;
+    MAC_TABLE_ENTRY *pEntry;
+
+    //printk("\n%s\n", arg);
+/*
+       The BAOriTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d,
+               =>The six 2 digit hex-decimal number previous are the Mac address,
+               =>The seventh decimal number is the tid value.
+*/
+    if(strlen(arg) < 19)  //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.
+               return FALSE;
+
+       token = strchr(arg, DASH);
+       if ((token != NULL) && (strlen(token)>1))
+       {
+               tid = simple_strtol((token+1), 0, 10);
+               if (tid > NUM_OF_TID)
+                       return FALSE;
+
+               *token = '\0';
+               for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
+               {
+                       if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
+                               return FALSE;
+                       AtoH(token, (PUCHAR)(&mac[i]), 1);
+               }
+               if(i != 6)
+                       return FALSE;
+
+           printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1],
+                  mac[2], mac[3], mac[4], mac[5], tid);
+
+           pEntry = MacTableLookup(pAd, mac);
+
+           if (pEntry) {
+               printk("\nTear down Ori BA Session: Tid = %d\n", tid);
+        BAOriSessionTearDown(pAd, pEntry->Aid, tid, FALSE, TRUE);
+           }
+
+               return TRUE;
+       }
+
+       return FALSE;
+
+}
+
+INT    Set_BARecTearDown_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+    UCHAR mac[6], tid;
+       char *token, sepValue[] = ":", DASH = '-';
+       INT i;
+    MAC_TABLE_ENTRY *pEntry;
+
+    //printk("\n%s\n", arg);
+/*
+       The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d,
+               =>The six 2 digit hex-decimal number previous are the Mac address,
+               =>The seventh decimal number is the tid value.
+*/
+    if(strlen(arg) < 19)  //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.
+               return FALSE;
+
+       token = strchr(arg, DASH);
+       if ((token != NULL) && (strlen(token)>1))
+       {
+               tid = simple_strtol((token+1), 0, 10);
+               if (tid > NUM_OF_TID)
+                       return FALSE;
+
+               *token = '\0';
+               for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
+               {
+                       if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
+                               return FALSE;
+                       AtoH(token, (PUCHAR)(&mac[i]), 1);
+               }
+               if(i != 6)
+                       return FALSE;
+
+               printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1],
+                      mac[2], mac[3], mac[4], mac[5], tid);
+
+               pEntry = MacTableLookup(pAd, mac);
+
+               if (pEntry) {
+                   printk("\nTear down Rec BA Session: Tid = %d\n", tid);
+                   BARecSessionTearDown(pAd, pEntry->Aid, tid, FALSE);
+               }
+
+               return TRUE;
+       }
+
+       return FALSE;
+
+}
+
+INT    Set_HtBw_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG HtBw;
+
+       HtBw = simple_strtol(arg, 0, 10);
+       if (HtBw == BW_40)
+               pAd->CommonCfg.RegTransmitSetting.field.BW  = BW_40;
+       else if (HtBw == BW_20)
+               pAd->CommonCfg.RegTransmitSetting.field.BW  = BW_20;
+       else
+               return FALSE;  //Invalid argument
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBw_Proc::(HtBw=%d)\n", pAd->CommonCfg.RegTransmitSetting.field.BW));
+
+       return TRUE;
+}
+
+INT    Set_HtMcs_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG HtMcs, Mcs_tmp;
+#ifdef CONFIG_STA_SUPPORT
+    BOOLEAN bAutoRate = FALSE;
+#endif // CONFIG_STA_SUPPORT //
+
+       Mcs_tmp = simple_strtol(arg, 0, 10);
+
+       if (Mcs_tmp <= 15 || Mcs_tmp == 32)
+               HtMcs = Mcs_tmp;
+       else
+               HtMcs = MCS_AUTO;
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               pAd->StaCfg.DesiredTransmitSetting.field.MCS = HtMcs;
+               pAd->StaCfg.bAutoTxRateSwitch = (HtMcs == MCS_AUTO) ? TRUE:FALSE;
+               DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d, bAutoTxRateSwitch = %d)\n",
+                                               pAd->StaCfg.DesiredTransmitSetting.field.MCS, pAd->StaCfg.bAutoTxRateSwitch));
+
+               if ((pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) ||
+                       (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE < MODE_HTMIX))
+               {
+               if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) &&
+                               (HtMcs >= 0 && HtMcs <= 3) &&
+                   (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_CCK))
+                       {
+                               RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs] * 1000000));
+                       }
+               else if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) &&
+                                       (HtMcs >= 0 && HtMcs <= 7) &&
+                       (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_OFDM))
+                       {
+                               RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs+4] * 1000000));
+                       }
+                       else
+                               bAutoRate = TRUE;
+
+                       if (bAutoRate)
+                       {
+                   pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+                               RTMPSetDesiredRates(pAd, -1);
+                       }
+               DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(FixedTxMode=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode));
+               }
+        if (ADHOC_ON(pAd))
+            return TRUE;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       SetCommonHT(pAd);
+
+       return TRUE;
+}
+
+INT    Set_HtGi_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG HtGi;
+
+       HtGi = simple_strtol(arg, 0, 10);
+
+       if ( HtGi == GI_400)
+               pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400;
+       else if ( HtGi == GI_800 )
+               pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800;
+       else
+               return FALSE; //Invalid argument
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtGi_Proc::(ShortGI=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.ShortGI));
+
+       return TRUE;
+}
+
+
+INT    Set_HtTxBASize_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UCHAR Size;
+
+       Size = simple_strtol(arg, 0, 10);
+
+       if (Size <=0 || Size >=64)
+       {
+               Size = 8;
+       }
+       pAd->CommonCfg.TxBASize = Size-1;
+       DBGPRINT(RT_DEBUG_ERROR, ("Set_HtTxBASize ::(TxBASize= %d)\n", Size));
+
+       return TRUE;
+}
+
+
+INT    Set_HtOpMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+
+       if (Value == HTMODE_GF)
+               pAd->CommonCfg.RegTransmitSetting.field.HTMODE  = HTMODE_GF;
+       else if ( Value == HTMODE_MM )
+               pAd->CommonCfg.RegTransmitSetting.field.HTMODE  = HTMODE_MM;
+       else
+               return FALSE; //Invalid argument
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtOpMode_Proc::(HtOpMode=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.HTMODE));
+
+       return TRUE;
+
+}
+
+INT    Set_HtStbc_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+
+       if (Value == STBC_USE)
+               pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE;
+       else if ( Value == STBC_NONE )
+               pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE;
+       else
+               return FALSE; //Invalid argument
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_Stbc_Proc::(HtStbc=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.STBC));
+
+       return TRUE;
+}
+
+INT    Set_HtHtc_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+       if (Value == 0)
+               pAd->HTCEnable = FALSE;
+       else if ( Value ==1 )
+               pAd->HTCEnable = TRUE;
+       else
+               return FALSE; //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtHtc_Proc::(HtHtc=%d)\n",pAd->HTCEnable));
+
+       return TRUE;
+}
+
+INT    Set_HtExtcha_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+
+       if (Value == 0)
+               pAd->CommonCfg.RegTransmitSetting.field.EXTCHA  = EXTCHA_BELOW;
+       else if ( Value ==1 )
+        pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+       else
+               return FALSE; //Invalid argument
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtExtcha_Proc::(HtExtcha=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.EXTCHA));
+
+       return TRUE;
+}
+
+INT    Set_HtMpduDensity_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+
+       if (Value <=7 && Value >= 0)
+               pAd->CommonCfg.BACapability.field.MpduDensity = Value;
+       else
+               pAd->CommonCfg.BACapability.field.MpduDensity = 4;
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMpduDensity_Proc::(HtMpduDensity=%d)\n",pAd->CommonCfg.BACapability.field.MpduDensity));
+
+       return TRUE;
+}
+
+INT    Set_HtBaWinSize_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+
+
+       if (Value >=1 && Value <= 64)
+       {
+               pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value;
+               pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value;
+       }
+       else
+       {
+        pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64;
+               pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64;
+       }
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBaWinSize_Proc::(HtBaWinSize=%d)\n",pAd->CommonCfg.BACapability.field.RxBAWinLimit));
+
+       return TRUE;
+}
+
+INT    Set_HtRdg_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+
+       if (Value == 0)
+               pAd->CommonCfg.bRdg = FALSE;
+       else if ( Value ==1 )
+       {
+               pAd->HTCEnable = TRUE;
+               pAd->CommonCfg.bRdg = TRUE;
+       }
+       else
+               return FALSE; //Invalid argument
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtRdg_Proc::(HtRdg=%d)\n",pAd->CommonCfg.bRdg));
+
+       return TRUE;
+}
+
+INT    Set_HtLinkAdapt_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+       if (Value == 0)
+               pAd->bLinkAdapt = FALSE;
+       else if ( Value ==1 )
+       {
+                       pAd->HTCEnable = TRUE;
+                       pAd->bLinkAdapt = TRUE;
+       }
+       else
+               return FALSE; //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtLinkAdapt_Proc::(HtLinkAdapt=%d)\n",pAd->bLinkAdapt));
+
+       return TRUE;
+}
+
+INT    Set_HtAmsdu_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+       if (Value == 0)
+               pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE;
+       else if ( Value == 1 )
+        pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE;
+       else
+               return FALSE; //Invalid argument
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAmsdu_Proc::(HtAmsdu=%d)\n",pAd->CommonCfg.BACapability.field.AmsduEnable));
+
+       return TRUE;
+}
+
+INT    Set_HtAutoBa_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+       if (Value == 0)
+               pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+    else if (Value == 1)
+               pAd->CommonCfg.BACapability.field.AutoBA = TRUE;
+       else
+               return FALSE; //Invalid argument
+
+    pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA;
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAutoBa_Proc::(HtAutoBa=%d)\n",pAd->CommonCfg.BACapability.field.AutoBA));
+
+       return TRUE;
+
+}
+
+INT    Set_HtProtect_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+       if (Value == 0)
+               pAd->CommonCfg.bHTProtect = FALSE;
+    else if (Value == 1)
+               pAd->CommonCfg.bHTProtect = TRUE;
+       else
+               return FALSE; //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtProtect_Proc::(HtProtect=%d)\n",pAd->CommonCfg.bHTProtect));
+
+       return TRUE;
+}
+
+INT    Set_SendPSMPAction_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+    UCHAR mac[6], mode;
+       char *token, sepValue[] = ":", DASH = '-';
+       INT i;
+    MAC_TABLE_ENTRY *pEntry;
+
+    //printk("\n%s\n", arg);
+/*
+       The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d,
+               =>The six 2 digit hex-decimal number previous are the Mac address,
+               =>The seventh decimal number is the mode value.
+*/
+    if(strlen(arg) < 19)  //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and mode value in decimal format.
+               return FALSE;
+
+       token = strchr(arg, DASH);
+       if ((token != NULL) && (strlen(token)>1))
+       {
+               mode = simple_strtol((token+1), 0, 10);
+               if (mode > MMPS_ENABLE)
+                       return FALSE;
+
+               *token = '\0';
+               for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
+               {
+                       if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
+                               return FALSE;
+                       AtoH(token, (PUCHAR)(&mac[i]), 1);
+               }
+               if(i != 6)
+                       return FALSE;
+
+               printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1],
+                      mac[2], mac[3], mac[4], mac[5], mode);
+
+               pEntry = MacTableLookup(pAd, mac);
+
+               if (pEntry) {
+                   printk("\nSendPSMPAction MIPS mode = %d\n", mode);
+                   SendPSMPAction(pAd, pEntry->Aid, mode);
+               }
+
+               return TRUE;
+       }
+
+       return FALSE;
+
+
+}
+
+INT    Set_HtMIMOPSmode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+
+       if (Value <=3 && Value >= 0)
+               pAd->CommonCfg.BACapability.field.MMPSmode = Value;
+       else
+               pAd->CommonCfg.BACapability.field.MMPSmode = 3;
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMIMOPSmode_Proc::(MIMOPS mode=%d)\n",pAd->CommonCfg.BACapability.field.MMPSmode));
+
+       return TRUE;
+}
+
+
+INT    Set_ForceShortGI_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+       if (Value == 0)
+               pAd->WIFItestbed.bShortGI = FALSE;
+       else if (Value == 1)
+               pAd->WIFItestbed.bShortGI = TRUE;
+       else
+               return FALSE; //Invalid argument
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceShortGI_Proc::(ForceShortGI=%d)\n", pAd->WIFItestbed.bShortGI));
+
+       return TRUE;
+}
+
+
+
+INT    Set_ForceGF_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+       if (Value == 0)
+               pAd->WIFItestbed.bGreenField = FALSE;
+       else if (Value == 1)
+               pAd->WIFItestbed.bGreenField = TRUE;
+       else
+               return FALSE; //Invalid argument
+
+       SetCommonHT(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceGF_Proc::(ForceGF=%d)\n", pAd->WIFItestbed.bGreenField));
+
+       return TRUE;
+}
+
+INT    Set_HtMimoPs_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+       if (Value == 0)
+               pAd->CommonCfg.bMIMOPSEnable = FALSE;
+       else if (Value == 1)
+               pAd->CommonCfg.bMIMOPSEnable = TRUE;
+       else
+               return FALSE; //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMimoPs_Proc::(HtMimoPs=%d)\n",pAd->CommonCfg.bMIMOPSEnable));
+
+       return TRUE;
+}
+#endif // DOT11_N_SUPPORT //
+
+
+#ifdef DOT11_N_SUPPORT
+INT    SetCommonHT(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       OID_SET_HT_PHYMODE              SetHT;
+
+       if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED)
+               return FALSE;
+
+       SetHT.PhyMode = pAd->CommonCfg.PhyMode;
+       SetHT.TransmitNo = ((UCHAR)pAd->Antenna.field.TxPath);
+       SetHT.HtMode = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.HTMODE;
+       SetHT.ExtOffset = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.EXTCHA;
+       SetHT.MCS = MCS_AUTO;
+       SetHT.BW = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.BW;
+       SetHT.STBC = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.STBC;
+       SetHT.SHORTGI = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.ShortGI;
+
+       RTMPSetHT(pAd, &SetHT);
+
+       return TRUE;
+}
+#endif // DOT11_N_SUPPORT //
+
+INT    Set_FixedTxMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UCHAR   fix_tx_mode = FIXED_TXMODE_HT;
+
+       if (strcmp(arg, "OFDM") == 0 || strcmp(arg, "ofdm") == 0)
+       {
+               fix_tx_mode = FIXED_TXMODE_OFDM;
+       }
+       else if (strcmp(arg, "CCK") == 0 || strcmp(arg, "cck") == 0)
+       {
+        fix_tx_mode = FIXED_TXMODE_CCK;
+       }
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode;
+#endif // CONFIG_STA_SUPPORT //
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_FixedTxMode_Proc::(FixedTxMode=%d)\n", fix_tx_mode));
+
+       return TRUE;
+}
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+INT    Set_OpMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG Value;
+
+       Value = simple_strtol(arg, 0, 10);
+
+#ifdef RT2870
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
+#endif // RT2870 //
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Can not switch operate mode on interface up !! \n"));
+               return FALSE;
+       }
+
+       if (Value == 0)
+               pAd->OpMode = OPMODE_STA;
+       else if (Value == 1)
+               pAd->OpMode = OPMODE_AP;
+       else
+               return FALSE; //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_OpMode_Proc::(OpMode=%s)\n", pAd->OpMode == 1 ? "AP Mode" : "STA Mode"));
+
+       return TRUE;
+}
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+
+/////////////////////////////////////////////////////////////////////////
+PCHAR   RTMPGetRalinkAuthModeStr(
+    IN  NDIS_802_11_AUTHENTICATION_MODE authMode)
+{
+       switch(authMode)
+       {
+               case Ndis802_11AuthModeOpen:
+                       return "OPEN";
+               case Ndis802_11AuthModeWPAPSK:
+                       return "WPAPSK";
+               case Ndis802_11AuthModeShared:
+                       return "SHARED";
+               case Ndis802_11AuthModeWPA:
+                       return "WPA";
+               case Ndis802_11AuthModeWPA2:
+                       return "WPA2";
+               case Ndis802_11AuthModeWPA2PSK:
+                       return "WPA2PSK";
+        case Ndis802_11AuthModeWPA1PSKWPA2PSK:
+                       return "WPAPSKWPA2PSK";
+        case Ndis802_11AuthModeWPA1WPA2:
+                       return "WPA1WPA2";
+               case Ndis802_11AuthModeWPANone:
+                       return "WPANONE";
+               default:
+                       return "UNKNOW";
+       }
+}
+
+PCHAR   RTMPGetRalinkEncryModeStr(
+    IN  USHORT encryMode)
+{
+       switch(encryMode)
+       {
+               case Ndis802_11WEPDisabled:
+                       return "NONE";
+               case Ndis802_11WEPEnabled:
+                       return "WEP";
+               case Ndis802_11Encryption2Enabled:
+                       return "TKIP";
+               case Ndis802_11Encryption3Enabled:
+                       return "AES";
+        case Ndis802_11Encryption4Enabled:
+                       return "TKIPAES";
+               default:
+                       return "UNKNOW";
+       }
+}
+
+INT RTMPShowCfgValue(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pName,
+       IN      PUCHAR                  pBuf)
+{
+       INT     Status = 0;
+
+       for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++)
+       {
+               if (!strcmp(pName, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name))
+               {
+                       if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->show_proc(pAd, pBuf))
+                               Status = -EINVAL;
+                       break;  //Exit for loop.
+               }
+       }
+
+       if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name == NULL)
+       {
+               sprintf(pBuf, "\n");
+               for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++)
+                       sprintf(pBuf, "%s%s\n", pBuf, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name);
+       }
+
+       return Status;
+}
+
+INT    Show_SSID_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               sprintf(pBuf, "\t%s", pAd->CommonCfg.Ssid);
+#endif // CONFIG_STA_SUPPORT //
+       return 0;
+}
+
+INT    Show_WirelessMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       switch(pAd->CommonCfg.PhyMode)
+       {
+               case PHY_11BG_MIXED:
+                       sprintf(pBuf, "\t11B/G");
+                       break;
+               case PHY_11B:
+                       sprintf(pBuf, "\t11B");
+                       break;
+               case PHY_11A:
+                       sprintf(pBuf, "\t11A");
+                       break;
+               case PHY_11ABG_MIXED:
+                       sprintf(pBuf, "\t11A/B/G");
+                       break;
+               case PHY_11G:
+                       sprintf(pBuf, "\t11G");
+                       break;
+#ifdef DOT11_N_SUPPORT
+               case PHY_11ABGN_MIXED:
+                       sprintf(pBuf, "\t11A/B/G/N");
+                       break;
+               case PHY_11N_2_4G:
+                       sprintf(pBuf, "\t11N only with 2.4G");
+                       break;
+               case PHY_11GN_MIXED:
+                       sprintf(pBuf, "\t11G/N");
+                       break;
+               case PHY_11AN_MIXED:
+                       sprintf(pBuf, "\t11A/N");
+                       break;
+               case PHY_11BGN_MIXED:
+                       sprintf(pBuf, "\t11B/G/N");
+                       break;
+               case PHY_11AGN_MIXED:
+                       sprintf(pBuf, "\t11A/G/N");
+                       break;
+               case PHY_11N_5G:
+                       sprintf(pBuf, "\t11N only with 5G");
+                       break;
+#endif // DOT11_N_SUPPORT //
+               default:
+                       sprintf(pBuf, "\tUnknow Value(%d)", pAd->CommonCfg.PhyMode);
+                       break;
+       }
+       return 0;
+}
+
+
+INT    Show_TxBurst_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%s", pAd->CommonCfg.bEnableTxBurst ? "TRUE":"FALSE");
+       return 0;
+}
+
+INT    Show_TxPreamble_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       switch(pAd->CommonCfg.TxPreamble)
+       {
+               case Rt802_11PreambleShort:
+                       sprintf(pBuf, "\tShort");
+                       break;
+               case Rt802_11PreambleLong:
+                       sprintf(pBuf, "\tLong");
+                       break;
+               case Rt802_11PreambleAuto:
+                       sprintf(pBuf, "\tAuto");
+                       break;
+               default:
+                       sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.TxPreamble);
+                       break;
+       }
+
+       return 0;
+}
+
+INT    Show_TxPower_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%lu", pAd->CommonCfg.TxPowerPercentage);
+       return 0;
+}
+
+INT    Show_Channel_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%d", pAd->CommonCfg.Channel);
+       return 0;
+}
+
+INT    Show_BGProtection_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       switch(pAd->CommonCfg.UseBGProtection)
+       {
+               case 1: //Always On
+                       sprintf(pBuf, "\tON");
+                       break;
+               case 2: //Always OFF
+                       sprintf(pBuf, "\tOFF");
+                       break;
+               case 0: //AUTO
+                       sprintf(pBuf, "\tAuto");
+                       break;
+               default:
+                       sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.UseBGProtection);
+                       break;
+       }
+       return 0;
+}
+
+INT    Show_RTSThreshold_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%u", pAd->CommonCfg.RtsThreshold);
+       return 0;
+}
+
+INT    Show_FragThreshold_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%u", pAd->CommonCfg.FragmentThreshold);
+       return 0;
+}
+
+#ifdef DOT11_N_SUPPORT
+INT    Show_HtBw_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
+       {
+               sprintf(pBuf, "\t40 MHz");
+       }
+       else
+       {
+        sprintf(pBuf, "\t20 MHz");
+       }
+       return 0;
+}
+
+INT    Show_HtMcs_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               sprintf(pBuf, "\t%u", pAd->StaCfg.DesiredTransmitSetting.field.MCS);
+#endif // CONFIG_STA_SUPPORT //
+       return 0;
+}
+
+INT    Show_HtGi_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       switch(pAd->CommonCfg.RegTransmitSetting.field.ShortGI)
+       {
+               case GI_400:
+                       sprintf(pBuf, "\tGI_400");
+                       break;
+               case GI_800:
+                       sprintf(pBuf, "\tGI_800");
+                       break;
+               default:
+                       sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.ShortGI);
+                       break;
+       }
+       return 0;
+}
+
+INT    Show_HtOpMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       switch(pAd->CommonCfg.RegTransmitSetting.field.HTMODE)
+       {
+               case HTMODE_GF:
+                       sprintf(pBuf, "\tGF");
+                       break;
+               case HTMODE_MM:
+                       sprintf(pBuf, "\tMM");
+                       break;
+               default:
+                       sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.HTMODE);
+                       break;
+       }
+       return 0;
+}
+
+INT    Show_HtExtcha_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       switch(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA)
+       {
+               case EXTCHA_BELOW:
+                       sprintf(pBuf, "\tBelow");
+                       break;
+               case EXTCHA_ABOVE:
+                       sprintf(pBuf, "\tAbove");
+                       break;
+               default:
+                       sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.EXTCHA);
+                       break;
+       }
+       return 0;
+}
+
+
+INT    Show_HtMpduDensity_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.MpduDensity);
+       return 0;
+}
+
+INT    Show_HtBaWinSize_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.RxBAWinLimit);
+       return 0;
+}
+
+INT    Show_HtRdg_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%s", pAd->CommonCfg.bRdg ? "TRUE":"FALSE");
+       return 0;
+}
+
+INT    Show_HtAmsdu_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AmsduEnable ? "TRUE":"FALSE");
+       return 0;
+}
+
+INT    Show_HtAutoBa_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AutoBA ? "TRUE":"FALSE");
+       return 0;
+}
+#endif // DOT11_N_SUPPORT //
+
+INT    Show_CountryRegion_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegion);
+       return 0;
+}
+
+INT    Show_CountryRegionABand_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegionForABand);
+       return 0;
+}
+
+INT    Show_CountryCode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%s", pAd->CommonCfg.CountryCode);
+       return 0;
+}
+
+#ifdef AGGREGATION_SUPPORT
+INT    Show_PktAggregate_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%s", pAd->CommonCfg.bAggregationCapable ? "TRUE":"FALSE");
+       return 0;
+}
+#endif // AGGREGATION_SUPPORT //
+
+#ifdef WMM_SUPPORT
+INT    Show_WmmCapable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               sprintf(pBuf, "\t%s", pAd->CommonCfg.bWmmCapable ? "TRUE":"FALSE");
+#endif // CONFIG_STA_SUPPORT //
+
+       return 0;
+}
+#endif // WMM_SUPPORT //
+
+INT    Show_IEEE80211H_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       sprintf(pBuf, "\t%s", pAd->CommonCfg.bIEEE80211H ? "TRUE":"FALSE");
+       return 0;
+}
+
+#ifdef CONFIG_STA_SUPPORT
+INT    Show_NetworkType_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       switch(pAd->StaCfg.BssType)
+       {
+               case BSS_ADHOC:
+                       sprintf(pBuf, "\tAdhoc");
+                       break;
+               case BSS_INFRA:
+                       sprintf(pBuf, "\tInfra");
+                       break;
+               case BSS_ANY:
+                       sprintf(pBuf, "\tAny");
+                       break;
+               case BSS_MONITOR:
+                       sprintf(pBuf, "\tMonitor");
+                       break;
+               default:
+                       sprintf(pBuf, "\tUnknow Value(%d)", pAd->StaCfg.BssType);
+                       break;
+       }
+       return 0;
+}
+#endif // CONFIG_STA_SUPPORT //
+
+INT    Show_AuthMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeOpen;
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               AuthMode = pAd->StaCfg.AuthMode;
+#endif // CONFIG_STA_SUPPORT //
+
+       if ((AuthMode >= Ndis802_11AuthModeOpen) &&
+               (AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK))
+               sprintf(pBuf, "\t%s", RTMPGetRalinkAuthModeStr(AuthMode));
+       else
+               sprintf(pBuf, "\tUnknow Value(%d)", AuthMode);
+
+       return 0;
+}
+
+INT    Show_EncrypType_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       NDIS_802_11_WEP_STATUS  WepStatus = Ndis802_11WEPDisabled;
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               WepStatus = pAd->StaCfg.WepStatus;
+#endif // CONFIG_STA_SUPPORT //
+
+       if ((WepStatus >= Ndis802_11WEPEnabled) &&
+               (WepStatus <= Ndis802_11Encryption4KeyAbsent))
+               sprintf(pBuf, "\t%s", RTMPGetRalinkEncryModeStr(WepStatus));
+       else
+               sprintf(pBuf, "\tUnknow Value(%d)", WepStatus);
+
+       return 0;
+}
+
+INT    Show_DefaultKeyID_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       UCHAR DefaultKeyId = 0;
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               DefaultKeyId = pAd->StaCfg.DefaultKeyId;
+#endif // CONFIG_STA_SUPPORT //
+
+       sprintf(pBuf, "\t%d", DefaultKeyId);
+
+       return 0;
+}
+
+INT    Show_WepKey_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN  INT                         KeyIdx,
+       OUT     PUCHAR                  pBuf)
+{
+       UCHAR   Key[16] = {0}, KeyLength = 0;
+       INT             index = BSS0;
+
+       KeyLength = pAd->SharedKey[index][KeyIdx].KeyLen;
+       NdisMoveMemory(Key, pAd->SharedKey[index][KeyIdx].Key, KeyLength);
+
+       //check key string is ASCII or not
+    if (RTMPCheckStrPrintAble(Key, KeyLength))
+        sprintf(pBuf, "\t%s", Key);
+    else
+    {
+        int idx;
+        sprintf(pBuf, "\t");
+        for (idx = 0; idx < KeyLength; idx++)
+            sprintf(pBuf+strlen(pBuf), "%02X", Key[idx]);
+    }
+       return 0;
+}
+
+INT    Show_Key1_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       Show_WepKey_Proc(pAd, 0, pBuf);
+       return 0;
+}
+
+INT    Show_Key2_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       Show_WepKey_Proc(pAd, 1, pBuf);
+       return 0;
+}
+
+INT    Show_Key3_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       Show_WepKey_Proc(pAd, 2, pBuf);
+       return 0;
+}
+
+INT    Show_Key4_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       Show_WepKey_Proc(pAd, 3, pBuf);
+       return 0;
+}
+
+INT    Show_WPAPSK_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUCHAR                  pBuf)
+{
+       INT     idx;
+       UCHAR   PMK[32] = {0};
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               NdisMoveMemory(PMK, pAd->StaCfg.PMK, 32);
+#endif // CONFIG_STA_SUPPORT //
+
+    sprintf(pBuf, "\tPMK = ");
+    for (idx = 0; idx < 32; idx++)
+        sprintf(pBuf+strlen(pBuf), "%02X", PMK[idx]);
+
+       return 0;
+}
+
diff --git a/drivers/staging/rt2870/common/cmm_sanity.c b/drivers/staging/rt2870/common/cmm_sanity.c
new file mode 100644 (file)
index 0000000..1e24320
--- /dev/null
@@ -0,0 +1,1663 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       sanity.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       John Chang  2004-09-01      add WMM support
+*/
+#include "../rt_config.h"
+
+
+extern UCHAR   CISCO_OUI[];
+
+extern UCHAR   WPA_OUI[];
+extern UCHAR   RSN_OUI[];
+extern UCHAR   WME_INFO_ELEM[];
+extern UCHAR   WME_PARM_ELEM[];
+extern UCHAR   Ccx2QosInfo[];
+extern UCHAR   RALINK_OUI[];
+extern UCHAR   BROADCOM_OUI[];
+extern UCHAR    WPS_OUI[];
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+BOOLEAN MlmeAddBAReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr2)
+{
+    PMLME_ADDBA_REQ_STRUCT   pInfo;
+
+    pInfo = (MLME_ADDBA_REQ_STRUCT *)Msg;
+
+    if ((MsgLen != sizeof(MLME_ADDBA_REQ_STRUCT)))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - message lenght not correct.\n"));
+        return FALSE;
+    }
+
+    if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n"));
+        return FALSE;
+    }
+
+       /*
+    if ((pInfo->BaBufSize > MAX_RX_REORDERBUF) || (pInfo->BaBufSize < 2))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - Rx Reordering buffer too big or too small\n"));
+        return FALSE;
+    }
+       */
+
+    if ((pInfo->pAddr[0]&0x01) == 0x01)
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - broadcast address not support BA\n"));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+BOOLEAN MlmeDelBAReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen)
+{
+       MLME_DELBA_REQ_STRUCT *pInfo;
+       pInfo = (MLME_DELBA_REQ_STRUCT *)Msg;
+
+    if ((MsgLen != sizeof(MLME_DELBA_REQ_STRUCT)))
+    {
+        DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - message lenght not correct.\n"));
+        return FALSE;
+    }
+
+    if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE))
+    {
+        DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n"));
+        return FALSE;
+    }
+
+    if ((pInfo->TID & 0xf0))
+    {
+        DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n"));
+        return FALSE;
+    }
+
+       if (NdisEqualMemory(pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, MAC_ADDR_LEN) == 0)
+    {
+        DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n"));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+BOOLEAN PeerAddBAReqActionSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *pMsg,
+    IN ULONG MsgLen,
+       OUT PUCHAR pAddr2)
+{
+       PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;
+       PFRAME_ADDBA_REQ pAddFrame;
+       pAddFrame = (PFRAME_ADDBA_REQ)(pMsg);
+       if (MsgLen < (sizeof(FRAME_ADDBA_REQ)))
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", MsgLen));
+               return FALSE;
+       }
+       // we support immediate BA.
+       *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm));
+       pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue);
+       pAddFrame->BaStartSeq.word = cpu2le16(pAddFrame->BaStartSeq.word);
+
+       if (pAddFrame->BaParm.BAPolicy != IMMED_BA)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy));
+               DBGPRINT(RT_DEBUG_ERROR,("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, pAddFrame->BaParm.AMSDUSupported));
+               return FALSE;
+       }
+
+       // we support immediate BA.
+       if (pAddFrame->BaParm.TID &0xfff0)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request incorrect TID = %d\n", pAddFrame->BaParm.TID));
+               return FALSE;
+       }
+       COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+       return TRUE;
+}
+
+BOOLEAN PeerAddBARspActionSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *pMsg,
+    IN ULONG MsgLen)
+{
+       //PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;
+       PFRAME_ADDBA_RSP pAddFrame;
+
+       pAddFrame = (PFRAME_ADDBA_RSP)(pMsg);
+       if (MsgLen < (sizeof(FRAME_ADDBA_RSP)))
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response frame length size = %ld incorrect\n", MsgLen));
+               return FALSE;
+       }
+       // we support immediate BA.
+       *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm));
+       pAddFrame->StatusCode = cpu2le16(pAddFrame->StatusCode);
+       pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue);
+
+       if (pAddFrame->BaParm.BAPolicy != IMMED_BA)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Response Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy));
+               return FALSE;
+       }
+
+       // we support immediate BA.
+       if (pAddFrame->BaParm.TID &0xfff0)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response incorrect TID = %d\n", pAddFrame->BaParm.TID));
+               return FALSE;
+       }
+       return TRUE;
+
+}
+
+BOOLEAN PeerDelBAActionSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN UCHAR Wcid,
+    IN VOID *pMsg,
+    IN ULONG MsgLen )
+{
+       //PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;
+       PFRAME_DELBA_REQ  pDelFrame;
+       if (MsgLen != (sizeof(FRAME_DELBA_REQ)))
+               return FALSE;
+
+       if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+               return FALSE;
+
+       pDelFrame = (PFRAME_DELBA_REQ)(pMsg);
+
+       *(USHORT *)(&pDelFrame->DelbaParm) = cpu2le16(*(USHORT *)(&pDelFrame->DelbaParm));
+       pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode);
+
+       if (pDelFrame->DelbaParm.TID &0xfff0)
+               return FALSE;
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+BOOLEAN PeerBeaconAndProbeRspSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    IN UCHAR  MsgChannel,
+    OUT PUCHAR pAddr2,
+    OUT PUCHAR pBssid,
+    OUT CHAR Ssid[],
+    OUT UCHAR *pSsidLen,
+    OUT UCHAR *pBssType,
+    OUT USHORT *pBeaconPeriod,
+    OUT UCHAR *pChannel,
+    OUT UCHAR *pNewChannel,
+    OUT LARGE_INTEGER *pTimestamp,
+    OUT CF_PARM *pCfParm,
+    OUT USHORT *pAtimWin,
+    OUT USHORT *pCapabilityInfo,
+    OUT UCHAR *pErp,
+    OUT UCHAR *pDtimCount,
+    OUT UCHAR *pDtimPeriod,
+    OUT UCHAR *pBcastFlag,
+    OUT UCHAR *pMessageToMe,
+    OUT UCHAR SupRate[],
+    OUT UCHAR *pSupRateLen,
+    OUT UCHAR ExtRate[],
+    OUT UCHAR *pExtRateLen,
+    OUT        UCHAR *pCkipFlag,
+    OUT        UCHAR *pAironetCellPowerLimit,
+    OUT PEDCA_PARM       pEdcaParm,
+    OUT PQBSS_LOAD_PARM  pQbssLoad,
+    OUT PQOS_CAPABILITY_PARM pQosCapability,
+    OUT ULONG *pRalinkIe,
+    OUT UCHAR           *pHtCapabilityLen,
+#ifdef CONFIG_STA_SUPPORT
+    OUT UCHAR           *pPreNHtCapabilityLen,
+#endif // CONFIG_STA_SUPPORT //
+    OUT HT_CAPABILITY_IE *pHtCapability,
+       OUT UCHAR                *AddHtInfoLen,
+       OUT ADD_HT_INFO_IE *AddHtInfo,
+       OUT UCHAR *NewExtChannelOffset,         // Ht extension channel offset(above or below)
+    OUT USHORT *LengthVIE,
+    OUT        PNDIS_802_11_VARIABLE_IEs pVIE)
+{
+    CHAR                               *Ptr;
+#ifdef CONFIG_STA_SUPPORT
+       CHAR                            TimLen;
+#endif // CONFIG_STA_SUPPORT //
+    PFRAME_802_11              pFrame;
+    PEID_STRUCT         pEid;
+    UCHAR                              SubType;
+    UCHAR                              Sanity;
+    //UCHAR                            ECWMin, ECWMax;
+    //MAC_CSR9_STRUC           Csr9;
+    ULONG                              Length = 0;
+
+       // For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel
+       //      1. If the AP is 11n enabled, then check the control channel.
+       //      2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!!)
+       UCHAR                   CtrlChannel = 0;
+
+    // Add for 3 necessary EID field check
+    Sanity = 0;
+
+    *pAtimWin = 0;
+    *pErp = 0;
+    *pDtimCount = 0;
+    *pDtimPeriod = 0;
+    *pBcastFlag = 0;
+    *pMessageToMe = 0;
+    *pExtRateLen = 0;
+    *pCkipFlag = 0;                            // Default of CkipFlag is 0
+    *pAironetCellPowerLimit = 0xFF;  // Default of AironetCellPowerLimit is 0xFF
+    *LengthVIE = 0;                                    // Set the length of VIE to init value 0
+    *pHtCapabilityLen = 0;                                     // Set the length of VIE to init value 0
+#ifdef CONFIG_STA_SUPPORT
+       if (pAd->OpMode == OPMODE_STA)
+               *pPreNHtCapabilityLen = 0;                                      // Set the length of VIE to init value 0
+#endif // CONFIG_STA_SUPPORT //
+    *AddHtInfoLen = 0;                                 // Set the length of VIE to init value 0
+    *pRalinkIe = 0;
+    *pNewChannel = 0;
+    *NewExtChannelOffset = 0xff;       //Default 0xff means no such IE
+    pCfParm->bValid = FALSE;        // default: no IE_CF found
+    pQbssLoad->bValid = FALSE;      // default: no IE_QBSS_LOAD found
+    pEdcaParm->bValid = FALSE;      // default: no IE_EDCA_PARAMETER found
+    pQosCapability->bValid = FALSE; // default: no IE_QOS_CAPABILITY found
+
+    pFrame = (PFRAME_802_11)Msg;
+
+    // get subtype from header
+    SubType = (UCHAR)pFrame->Hdr.FC.SubType;
+
+    // get Addr2 and BSSID from header
+    COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+    COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3);
+
+//     hex_dump("Beacon", Msg, MsgLen);
+
+    Ptr = pFrame->Octet;
+    Length += LENGTH_802_11;
+
+    // get timestamp from payload and advance the pointer
+    NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN);
+
+       pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart);
+       pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart);
+
+    Ptr += TIMESTAMP_LEN;
+    Length += TIMESTAMP_LEN;
+
+    // get beacon interval from payload and advance the pointer
+    NdisMoveMemory(pBeaconPeriod, Ptr, 2);
+    Ptr += 2;
+    Length += 2;
+
+    // get capability info from payload and advance the pointer
+    NdisMoveMemory(pCapabilityInfo, Ptr, 2);
+    Ptr += 2;
+    Length += 2;
+
+    if (CAP_IS_ESS_ON(*pCapabilityInfo))
+        *pBssType = BSS_INFRA;
+    else
+        *pBssType = BSS_ADHOC;
+
+    pEid = (PEID_STRUCT) Ptr;
+
+    // get variable fields from payload and advance the pointer
+    while ((Length + 2 + pEid->Len) <= MsgLen)
+    {
+        //
+        // Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow.
+        //
+        if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN)
+        {
+            DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n",
+                    (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN));
+            break;
+        }
+
+        switch(pEid->Eid)
+        {
+            case IE_SSID:
+                // Already has one SSID EID in this beacon, ignore the second one
+                if (Sanity & 0x1)
+                    break;
+                if(pEid->Len <= MAX_LEN_OF_SSID)
+                {
+                    NdisMoveMemory(Ssid, pEid->Octet, pEid->Len);
+                    *pSsidLen = pEid->Len;
+                    Sanity |= 0x1;
+                }
+                else
+                {
+                    DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len));
+                    return FALSE;
+                }
+                break;
+
+            case IE_SUPP_RATES:
+                if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
+                {
+                    Sanity |= 0x2;
+                    NdisMoveMemory(SupRate, pEid->Octet, pEid->Len);
+                    *pSupRateLen = pEid->Len;
+
+                    // TODO: 2004-09-14 not a good design here, cause it exclude extra rates
+                    // from ScanTab. We should report as is. And filter out unsupported
+                    // rates in MlmeAux.
+                    // Check against the supported rates
+                    // RTMPCheckRates(pAd, SupRate, pSupRateLen);
+                }
+                else
+                {
+                    DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n",pEid->Len));
+                    return FALSE;
+                }
+                break;
+
+            case IE_HT_CAP:
+                       if (pEid->Len >= SIZE_HT_CAP_IE)  //Note: allow extension.!!
+                       {
+                               NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE));
+                               *pHtCapabilityLen = SIZE_HT_CAP_IE;     // Nnow we only support 26 bytes.
+
+                               *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
+                               *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
+
+#ifdef CONFIG_STA_SUPPORT
+                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               {
+                                       *pPreNHtCapabilityLen = 0;      // Nnow we only support 26 bytes.
+
+                                       Ptr = (PUCHAR) pVIE;
+                                       NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+                                       *LengthVIE += (pEid->Len + 2);
+                               }
+#endif // CONFIG_STA_SUPPORT //
+                       }
+                       else
+                       {
+                               DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", pEid->Len));
+                       }
+
+               break;
+            case IE_ADD_HT:
+                       if (pEid->Len >= sizeof(ADD_HT_INFO_IE))
+                       {
+                               // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only
+                               // copy first sizeof(ADD_HT_INFO_IE)
+                               NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE));
+                               *AddHtInfoLen = SIZE_ADD_HT_INFO_IE;
+
+                               CtrlChannel = AddHtInfo->ControlChan;
+
+                               *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2));
+                               *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3));
+
+#ifdef CONFIG_STA_SUPPORT
+                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               {
+                                       Ptr = (PUCHAR) pVIE;
+                                       NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+                                       *LengthVIE += (pEid->Len + 2);
+                               }
+#endif // CONFIG_STA_SUPPORT //
+                       }
+                       else
+                       {
+                               DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_ADD_HT. \n"));
+                       }
+
+               break;
+            case IE_SECONDARY_CH_OFFSET:
+                       if (pEid->Len == 1)
+                       {
+                               *NewExtChannelOffset = pEid->Octet[0];
+                       }
+                       else
+                       {
+                               DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n"));
+                       }
+
+               break;
+            case IE_FH_PARM:
+                DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n"));
+                break;
+
+            case IE_DS_PARM:
+                if(pEid->Len == 1)
+                {
+                    *pChannel = *pEid->Octet;
+#ifdef CONFIG_STA_SUPPORT
+                                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                       {
+                                               if (ChannelSanity(pAd, *pChannel) == 0)
+                                               {
+
+                                                       return FALSE;
+                                               }
+                                       }
+#endif // CONFIG_STA_SUPPORT //
+                    Sanity |= 0x4;
+                }
+                else
+                {
+                    DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n",pEid->Len));
+                    return FALSE;
+                }
+                break;
+
+            case IE_CF_PARM:
+                if(pEid->Len == 6)
+                {
+                    pCfParm->bValid = TRUE;
+                    pCfParm->CfpCount = pEid->Octet[0];
+                    pCfParm->CfpPeriod = pEid->Octet[1];
+                    pCfParm->CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3];
+                    pCfParm->CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5];
+                }
+                else
+                {
+                    DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n"));
+                    return FALSE;
+                }
+                break;
+
+            case IE_IBSS_PARM:
+                if(pEid->Len == 2)
+                {
+                    NdisMoveMemory(pAtimWin, pEid->Octet, pEid->Len);
+                }
+                else
+                {
+                    DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n"));
+                    return FALSE;
+                }
+                break;
+
+#ifdef CONFIG_STA_SUPPORT
+            case IE_TIM:
+                if(INFRA_ON(pAd) && SubType == SUBTYPE_BEACON)
+                {
+                    GetTimBit((PUCHAR)pEid, pAd->StaActive.Aid, &TimLen, pBcastFlag, pDtimCount, pDtimPeriod, pMessageToMe);
+                }
+                break;
+#endif // CONFIG_STA_SUPPORT //
+            case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
+                if(pEid->Len == 3)
+                {
+                       *pNewChannel = pEid->Octet[1];  //extract new channel number
+                }
+                break;
+
+            // New for WPA
+            // CCX v2 has the same IE, we need to parse that too
+            // Wifi WMM use the same IE vale, need to parse that too
+            // case IE_WPA:
+            case IE_VENDOR_SPECIFIC:
+                // Check Broadcom/Atheros 802.11n OUI version, for HT Capability IE.
+                // This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan.
+                /*if (NdisEqualMemory(pEid->Octet, BROADCOM_OUI, 3) && (pEid->Len >= 4))
+                {
+                       if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 30))
+                       {
+                               {
+                                       NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(HT_CAPABILITY_IE));
+                                       *pHtCapabilityLen = SIZE_HT_CAP_IE;     // Nnow we only support 26 bytes.
+                               }
+                       }
+                       if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 26))
+                       {
+                               {
+                                       NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(ADD_HT_INFO_IE));
+                                       *AddHtInfoLen = SIZE_ADD_HT_INFO_IE;    // Nnow we only support 26 bytes.
+                               }
+                       }
+                }
+                               */
+                // Check the OUI version, filter out non-standard usage
+                if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7))
+                {
+                    //*pRalinkIe = pEid->Octet[3];
+                    if (pEid->Octet[3] != 0)
+                                       *pRalinkIe = pEid->Octet[3];
+                               else
+                                       *pRalinkIe = 0xf0000000; // Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag.
+                }
+#ifdef CONFIG_STA_SUPPORT
+#ifdef DOT11_N_SUPPORT
+               // This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan.
+
+                // Other vendors had production before IE_HT_CAP value is assigned. To backward support those old-firmware AP,
+                // Check broadcom-defiend pre-802.11nD1.0 OUI for HT related IE, including HT Capatilities IE and HT Information IE
+                else if ((*pHtCapabilityLen == 0) && NdisEqualMemory(pEid->Octet, PRE_N_HT_OUI, 3) && (pEid->Len >= 4) && (pAd->OpMode == OPMODE_STA))
+                {
+                    if ((pEid->Octet[3] == OUI_PREN_HT_CAP) && (pEid->Len >= 30) && (*pHtCapabilityLen == 0))
+                    {
+                        NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(HT_CAPABILITY_IE));
+                        *pPreNHtCapabilityLen = SIZE_HT_CAP_IE;
+                    }
+
+                    if ((pEid->Octet[3] == OUI_PREN_ADD_HT) && (pEid->Len >= 26))
+                    {
+                        NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(ADD_HT_INFO_IE));
+                        *AddHtInfoLen = SIZE_ADD_HT_INFO_IE;
+                    }
+                }
+#endif // DOT11_N_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+                else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
+                {
+                    // Copy to pVIE which will report to microsoft bssid list.
+                    Ptr = (PUCHAR) pVIE;
+                    NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+                    *LengthVIE += (pEid->Len + 2);
+                }
+                else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24))
+                {
+                    PUCHAR ptr;
+                    int i;
+
+                    // parsing EDCA parameters
+                    pEdcaParm->bValid          = TRUE;
+                    pEdcaParm->bQAck           = FALSE; // pEid->Octet[0] & 0x10;
+                    pEdcaParm->bQueueRequest   = FALSE; // pEid->Octet[0] & 0x20;
+                    pEdcaParm->bTxopRequest    = FALSE; // pEid->Octet[0] & 0x40;
+                    pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f;
+                    pEdcaParm->bAPSDCapable    = (pEid->Octet[6] & 0x80) ? 1 : 0;
+                    ptr = &pEid->Octet[8];
+                    for (i=0; i<4; i++)
+                    {
+                        UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX
+                        pEdcaParm->bACM[aci]  = (((*ptr) & 0x10) == 0x10);   // b5 is ACM
+                        pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f;               // b0~3 is AIFSN
+                        pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f;             // b0~4 is Cwmin
+                        pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4;               // b5~8 is Cwmax
+                        pEdcaParm->Txop[aci]  = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us
+                        ptr += 4; // point to next AC
+                    }
+                }
+                else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7))
+                {
+                    // parsing EDCA parameters
+                    pEdcaParm->bValid          = TRUE;
+                    pEdcaParm->bQAck           = FALSE; // pEid->Octet[0] & 0x10;
+                    pEdcaParm->bQueueRequest   = FALSE; // pEid->Octet[0] & 0x20;
+                    pEdcaParm->bTxopRequest    = FALSE; // pEid->Octet[0] & 0x40;
+                    pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f;
+                    pEdcaParm->bAPSDCapable    = (pEid->Octet[6] & 0x80) ? 1 : 0;
+
+                    // use default EDCA parameter
+                    pEdcaParm->bACM[QID_AC_BE]  = 0;
+                    pEdcaParm->Aifsn[QID_AC_BE] = 3;
+                    pEdcaParm->Cwmin[QID_AC_BE] = CW_MIN_IN_BITS;
+                    pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS;
+                    pEdcaParm->Txop[QID_AC_BE]  = 0;
+
+                    pEdcaParm->bACM[QID_AC_BK]  = 0;
+                    pEdcaParm->Aifsn[QID_AC_BK] = 7;
+                    pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS;
+                    pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS;
+                    pEdcaParm->Txop[QID_AC_BK]  = 0;
+
+                    pEdcaParm->bACM[QID_AC_VI]  = 0;
+                    pEdcaParm->Aifsn[QID_AC_VI] = 2;
+                    pEdcaParm->Cwmin[QID_AC_VI] = CW_MIN_IN_BITS-1;
+                    pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS;
+                    pEdcaParm->Txop[QID_AC_VI]  = 96;   // AC_VI: 96*32us ~= 3ms
+
+                    pEdcaParm->bACM[QID_AC_VO]  = 0;
+                    pEdcaParm->Aifsn[QID_AC_VO] = 2;
+                    pEdcaParm->Cwmin[QID_AC_VO] = CW_MIN_IN_BITS-2;
+                    pEdcaParm->Cwmax[QID_AC_VO] = CW_MAX_IN_BITS-1;
+                    pEdcaParm->Txop[QID_AC_VO]  = 48;   // AC_VO: 48*32us ~= 1.5ms
+                }
+                break;
+
+            case IE_EXT_SUPP_RATES:
+                if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
+                {
+                    NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len);
+                    *pExtRateLen = pEid->Len;
+
+                    // TODO: 2004-09-14 not a good design here, cause it exclude extra rates
+                    // from ScanTab. We should report as is. And filter out unsupported
+                    // rates in MlmeAux.
+                    // Check against the supported rates
+                    // RTMPCheckRates(pAd, ExtRate, pExtRateLen);
+                }
+                break;
+
+            case IE_ERP:
+                if (pEid->Len == 1)
+                {
+                    *pErp = (UCHAR)pEid->Octet[0];
+                }
+                break;
+
+            case IE_AIRONET_CKIP:
+                // 0. Check Aironet IE length, it must be larger or equal to 28
+                // Cisco AP350 used length as 28
+                // Cisco AP12XX used length as 30
+                if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2))
+                    break;
+
+                // 1. Copy CKIP flag byte to buffer for process
+                *pCkipFlag = *(pEid->Octet + 8);
+                break;
+
+            case IE_AP_TX_POWER:
+                // AP Control of Client Transmit Power
+                //0. Check Aironet IE length, it must be 6
+                if (pEid->Len != 0x06)
+                    break;
+
+                // Get cell power limit in dBm
+                if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1)
+                    *pAironetCellPowerLimit = *(pEid->Octet + 4);
+                break;
+
+            // WPA2 & 802.11i RSN
+            case IE_RSN:
+                // There is no OUI for version anymore, check the group cipher OUI before copying
+                if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
+                {
+                    // Copy to pVIE which will report to microsoft bssid list.
+                    Ptr = (PUCHAR) pVIE;
+                    NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+                    *LengthVIE += (pEid->Len + 2);
+                }
+                break;
+#ifdef CONFIG_STA_SUPPORT
+#ifdef EXT_BUILD_CHANNEL_LIST
+                       case IE_COUNTRY:
+                               Ptr = (PUCHAR) pVIE;
+                NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+                *LengthVIE += (pEid->Len + 2);
+                               break;
+#endif // EXT_BUILD_CHANNEL_LIST //
+#endif // CONFIG_STA_SUPPORT //
+            default:
+                break;
+        }
+
+        Length = Length + 2 + pEid->Len;  // Eid[1] + Len[1]+ content[Len]
+        pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+    }
+
+    // For some 11a AP. it did not have the channel EID, patch here
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               UCHAR LatchRfChannel = MsgChannel;
+               if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0))
+               {
+                       if (CtrlChannel != 0)
+                               *pChannel = CtrlChannel;
+                       else
+                               *pChannel = LatchRfChannel;
+                       Sanity |= 0x4;
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       if (Sanity != 0x7)
+       {
+               DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - missing field, Sanity=0x%02x\n", Sanity));
+               return FALSE;
+       }
+       else
+       {
+               return TRUE;
+       }
+
+}
+
+#ifdef DOT11N_DRAFT3
+/*
+       ==========================================================================
+       Description:
+               MLME message sanity check for some IE addressed  in 802.11n d3.03.
+       Return:
+               TRUE if all parameters are OK, FALSE otherwise
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+BOOLEAN PeerBeaconAndProbeRspSanity2(
+       IN PRTMP_ADAPTER pAd,
+       IN VOID *Msg,
+       IN ULONG MsgLen,
+       OUT UCHAR       *RegClass)
+{
+       CHAR                            *Ptr;
+       PFRAME_802_11           pFrame;
+       PEID_STRUCT                     pEid;
+       ULONG                           Length = 0;
+
+       pFrame = (PFRAME_802_11)Msg;
+
+       *RegClass = 0;
+       Ptr = pFrame->Octet;
+       Length += LENGTH_802_11;
+
+       // get timestamp from payload and advance the pointer
+       Ptr += TIMESTAMP_LEN;
+       Length += TIMESTAMP_LEN;
+
+       // get beacon interval from payload and advance the pointer
+       Ptr += 2;
+       Length += 2;
+
+       // get capability info from payload and advance the pointer
+       Ptr += 2;
+       Length += 2;
+
+       pEid = (PEID_STRUCT) Ptr;
+
+       // get variable fields from payload and advance the pointer
+       while ((Length + 2 + pEid->Len) <= MsgLen)
+       {
+               switch(pEid->Eid)
+               {
+                       case IE_SUPP_REG_CLASS:
+                               if(pEid->Len > 0)
+                               {
+                                       *RegClass = *pEid->Octet;
+                               }
+                               else
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len));
+                                       return FALSE;
+                               }
+                               break;
+               }
+
+               Length = Length + 2 + pEid->Len;  // Eid[1] + Len[1]+ content[Len]
+               pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+       }
+
+       return TRUE;
+
+}
+#endif // DOT11N_DRAFT3 //
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+ */
+BOOLEAN MlmeScanReqSanity(
+       IN PRTMP_ADAPTER pAd,
+       IN VOID *Msg,
+       IN ULONG MsgLen,
+       OUT UCHAR *pBssType,
+       OUT CHAR Ssid[],
+       OUT UCHAR *pSsidLen,
+       OUT UCHAR *pScanType)
+{
+       MLME_SCAN_REQ_STRUCT *Info;
+
+       Info = (MLME_SCAN_REQ_STRUCT *)(Msg);
+       *pBssType = Info->BssType;
+       *pSsidLen = Info->SsidLen;
+       NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen);
+       *pScanType = Info->ScanType;
+
+       if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC || *pBssType == BSS_ANY)
+               && (*pScanType == SCAN_ACTIVE || *pScanType == SCAN_PASSIVE
+#ifdef CONFIG_STA_SUPPORT
+               || *pScanType == SCAN_CISCO_PASSIVE || *pScanType == SCAN_CISCO_ACTIVE
+               || *pScanType == SCAN_CISCO_CHANNEL_LOAD || *pScanType == SCAN_CISCO_NOISE
+#endif // CONFIG_STA_SUPPORT //
+               ))
+       {
+               return TRUE;
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqSanity fail - wrong BssType or ScanType\n"));
+               return FALSE;
+       }
+}
+
+// IRQL = DISPATCH_LEVEL
+UCHAR ChannelSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN UCHAR channel)
+{
+    int i;
+
+    for (i = 0; i < pAd->ChannelListNum; i ++)
+    {
+        if (channel == pAd->ChannelList[i].Channel)
+            return 1;
+    }
+    return 0;
+}
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+BOOLEAN PeerDeauthSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr2,
+    OUT USHORT *pReason)
+{
+    PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+
+    COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+    NdisMoveMemory(pReason, &pFrame->Octet[0], 2);
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+BOOLEAN PeerAuthSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr,
+    OUT USHORT *pAlg,
+    OUT USHORT *pSeq,
+    OUT USHORT *pStatus,
+    CHAR *pChlgText)
+{
+    PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+
+    COPY_MAC_ADDR(pAddr,   pFrame->Hdr.Addr2);
+    NdisMoveMemory(pAlg,    &pFrame->Octet[0], 2);
+    NdisMoveMemory(pSeq,    &pFrame->Octet[2], 2);
+    NdisMoveMemory(pStatus, &pFrame->Octet[4], 2);
+
+    if ((*pAlg == Ndis802_11AuthModeOpen)
+#ifdef LEAP_SUPPORT
+      || (*pAlg == CISCO_AuthModeLEAP)
+#endif // LEAP_SUPPORT //
+      )
+    {
+        if (*pSeq == 1 || *pSeq == 2)
+        {
+            return TRUE;
+        }
+        else
+        {
+            DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n"));
+            return FALSE;
+        }
+    }
+    else if (*pAlg == Ndis802_11AuthModeShared)
+    {
+        if (*pSeq == 1 || *pSeq == 4)
+        {
+            return TRUE;
+        }
+        else if (*pSeq == 2 || *pSeq == 3)
+        {
+            NdisMoveMemory(pChlgText, &pFrame->Octet[8], CIPHER_TEXT_LEN);
+            return TRUE;
+        }
+        else
+        {
+            DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n"));
+            return FALSE;
+        }
+    }
+    else
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong algorithm\n"));
+        return FALSE;
+    }
+}
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+ */
+BOOLEAN MlmeAuthReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr,
+    OUT ULONG *pTimeout,
+    OUT USHORT *pAlg)
+{
+    MLME_AUTH_REQ_STRUCT *pInfo;
+
+    pInfo  = (MLME_AUTH_REQ_STRUCT *)Msg;
+    COPY_MAC_ADDR(pAddr, pInfo->Addr);
+    *pTimeout = pInfo->Timeout;
+    *pAlg = pInfo->Alg;
+
+    if (((*pAlg == Ndis802_11AuthModeShared) ||(*pAlg == Ndis802_11AuthModeOpen)
+#ifdef LEAP_SUPPORT
+     || (*pAlg == CISCO_AuthModeLEAP)
+#endif // LEAP_SUPPORT //
+       ) &&
+        ((*pAddr & 0x01) == 0))
+    {
+        return TRUE;
+    }
+    else
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("MlmeAuthReqSanity fail - wrong algorithm\n"));
+        return FALSE;
+    }
+}
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+BOOLEAN MlmeAssocReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pApAddr,
+    OUT USHORT *pCapabilityInfo,
+    OUT ULONG *pTimeout,
+    OUT USHORT *pListenIntv)
+{
+    MLME_ASSOC_REQ_STRUCT *pInfo;
+
+    pInfo = (MLME_ASSOC_REQ_STRUCT *)Msg;
+    *pTimeout = pInfo->Timeout;                             // timeout
+    COPY_MAC_ADDR(pApAddr, pInfo->Addr);                   // AP address
+    *pCapabilityInfo = pInfo->CapabilityInfo;               // capability info
+    *pListenIntv = pInfo->ListenIntv;
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+BOOLEAN PeerDisassocSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr2,
+    OUT USHORT *pReason)
+{
+    PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+
+    COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+    NdisMoveMemory(pReason, &pFrame->Octet[0], 2);
+
+    return TRUE;
+}
+
+/*
+       ========================================================================
+       Routine Description:
+               Sanity check NetworkType (11b, 11g or 11a)
+
+       Arguments:
+               pBss - Pointer to BSS table.
+
+       Return Value:
+        Ndis802_11DS .......(11b)
+        Ndis802_11OFDM24....(11g)
+        Ndis802_11OFDM5.....(11a)
+
+       IRQL = DISPATCH_LEVEL
+
+       ========================================================================
+*/
+NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(
+    IN PBSS_ENTRY pBss)
+{
+       NDIS_802_11_NETWORK_TYPE        NetWorkType;
+       UCHAR                                           rate, i;
+
+       NetWorkType = Ndis802_11DS;
+
+       if (pBss->Channel <= 14)
+       {
+               //
+               // First check support Rate.
+               //
+               for (i = 0; i < pBss->SupRateLen; i++)
+               {
+                       rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit
+                       if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22))
+                       {
+                               continue;
+                       }
+                       else
+                       {
+                               //
+                               // Otherwise (even rate > 108) means Ndis802_11OFDM24
+                               //
+                               NetWorkType = Ndis802_11OFDM24;
+                               break;
+                       }
+               }
+
+               //
+               // Second check Extend Rate.
+               //
+               if (NetWorkType != Ndis802_11OFDM24)
+               {
+                       for (i = 0; i < pBss->ExtRateLen; i++)
+                       {
+                               rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit
+                               if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22))
+                               {
+                                       continue;
+                               }
+                               else
+                               {
+                                       //
+                                       // Otherwise (even rate > 108) means Ndis802_11OFDM24
+                                       //
+                                       NetWorkType = Ndis802_11OFDM24;
+                                       break;
+                               }
+                       }
+               }
+       }
+       else
+       {
+               NetWorkType = Ndis802_11OFDM5;
+       }
+
+    if (pBss->HtCapabilityLen != 0)
+    {
+        if (NetWorkType == Ndis802_11OFDM5)
+            NetWorkType = Ndis802_11OFDM5_N;
+        else
+            NetWorkType = Ndis802_11OFDM24_N;
+    }
+
+       return NetWorkType;
+}
+
+/*
+    ==========================================================================
+    Description:
+        WPA message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+ */
+BOOLEAN PeerWpaMessageSanity(
+    IN         PRTMP_ADAPTER           pAd,
+    IN         PEAPOL_PACKET           pMsg,
+    IN         ULONG                           MsgLen,
+    IN         UCHAR                           MsgType,
+    IN         MAC_TABLE_ENTRY         *pEntry)
+{
+       UCHAR                   mic[LEN_KEY_DESC_MIC], digest[80], KEYDATA[MAX_LEN_OF_RSNIE];
+       BOOLEAN                 bReplayDiff = FALSE;
+       BOOLEAN                 bWPA2 = FALSE;
+       KEY_INFO                EapolKeyInfo;
+       UCHAR                   GroupKeyIndex = 0;
+
+
+       NdisZeroMemory(mic, sizeof(mic));
+       NdisZeroMemory(digest, sizeof(digest));
+       NdisZeroMemory(KEYDATA, sizeof(KEYDATA));
+       NdisZeroMemory((PUCHAR)&EapolKeyInfo, sizeof(EapolKeyInfo));
+
+       NdisMoveMemory((PUCHAR)&EapolKeyInfo, (PUCHAR)&pMsg->KeyDesc.KeyInfo, sizeof(KEY_INFO));
+
+       *((USHORT *)&EapolKeyInfo) = cpu2le16(*((USHORT *)&EapolKeyInfo));
+
+       // Choose WPA2 or not
+       if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
+               bWPA2 = TRUE;
+
+       // 0. Check MsgType
+       if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("The message type is invalid(%d)! \n", MsgType));
+               return FALSE;
+       }
+
+       // 1. Replay counter check
+       if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) // For supplicant
+    {
+       // First validate replay counter, only accept message with larger replay counter.
+               // Let equal pass, some AP start with all zero replay counter
+               UCHAR   ZeroReplay[LEN_KEY_DESC_REPLAY];
+
+        NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
+               if ((RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY) != 1) &&
+                       (RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
+       {
+                       bReplayDiff = TRUE;
+       }
+       }
+       else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)    // For authenticator
+       {
+               // check Replay Counter coresponds to MSG from authenticator, otherwise discard
+       if (!NdisEqualMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY))
+       {
+                       bReplayDiff = TRUE;
+       }
+       }
+
+       // Replay Counter different condition
+       if (bReplayDiff)
+       {
+               // send wireless event - for replay counter different
+               if (pAd->CommonCfg.bWirelessEvent)
+                       RTMPSendWirelessEvent(pAd, IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+               if (MsgType < EAPOL_GROUP_MSG_1)
+               {
+               DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", MsgType));
+               }
+               else
+               {
+                       DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4)));
+               }
+
+               hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+               hex_dump("Current replay counter ", pEntry->R_Counter, LEN_KEY_DESC_REPLAY);
+        return FALSE;
+       }
+
+       // 2. Verify MIC except Pairwise Msg1
+       if (MsgType != EAPOL_PAIR_MSG_1)
+       {
+               UCHAR                   rcvd_mic[LEN_KEY_DESC_MIC];
+
+               // Record the received MIC for check later
+               NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+               NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+
+        if (pEntry->WepStatus == Ndis802_11Encryption2Enabled) // TKIP
+        {
+            hmac_md5(pEntry->PTK, LEN_EAP_MICK, (PUCHAR)pMsg, MsgLen, mic);
+        }
+        else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled)    // AES
+        {
+            HMAC_SHA1((PUCHAR)pMsg, MsgLen, pEntry->PTK, LEN_EAP_MICK, digest);
+            NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
+        }
+
+        if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC))
+        {
+                       // send wireless event - for MIC different
+                       if (pAd->CommonCfg.bWirelessEvent)
+                               RTMPSendWirelessEvent(pAd, IW_MIC_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+                       if (MsgType < EAPOL_GROUP_MSG_1)
+                       {
+               DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in pairwise msg %d of 4-way handshake!\n", MsgType));
+                       }
+                       else
+                       {
+                               DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4)));
+                       }
+
+                       hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC);
+                       hex_dump("Desired  MIC", mic, LEN_KEY_DESC_MIC);
+
+                       return FALSE;
+        }
+       }
+
+       // Extract the context of the Key Data field if it exist
+       // The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is un-encrypted.
+       // The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted.
+       if (pMsg->KeyDesc.KeyDataLen[1] > 0)
+       {
+               // Decrypt this field
+               if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
+               {
+                       if(pEntry->WepStatus == Ndis802_11Encryption3Enabled)
+                       {
+                               // AES
+                               AES_GTK_KEY_UNWRAP(&pEntry->PTK[16], KEYDATA, pMsg->KeyDesc.KeyDataLen[1],pMsg->KeyDesc.KeyData);
+                       }
+                       else
+                       {
+                               INT     i;
+                               UCHAR   Key[32];
+                               // Decrypt TKIP GTK
+                               // Construct 32 bytes RC4 Key
+                               NdisMoveMemory(Key, pMsg->KeyDesc.KeyIv, 16);
+                               NdisMoveMemory(&Key[16], &pEntry->PTK[16], 16);
+                               ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32);
+                               //discard first 256 bytes
+                               for(i = 0; i < 256; i++)
+                                       ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT);
+                               // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not
+                               ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pMsg->KeyDesc.KeyData, pMsg->KeyDesc.KeyDataLen[1]);
+                       }
+
+                       if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
+                               GroupKeyIndex = EapolKeyInfo.KeyIndex;
+
+               }
+               else if ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2))
+               {
+                       NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, pMsg->KeyDesc.KeyDataLen[1]);
+               }
+               else
+               {
+
+                       return TRUE;
+               }
+
+               // Parse Key Data field to
+               // 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2)
+               // 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2
+               // 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2)
+               if (!RTMPParseEapolKeyData(pAd, KEYDATA, pMsg->KeyDesc.KeyDataLen[1], GroupKeyIndex, MsgType, bWPA2, pEntry))
+               {
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+
+}
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+BOOLEAN MlmeDlsReqSanity(
+       IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PRT_802_11_DLS *pDLS,
+    OUT PUSHORT pReason)
+{
+       MLME_DLS_REQ_STRUCT *pInfo;
+
+    pInfo = (MLME_DLS_REQ_STRUCT *)Msg;
+
+       *pDLS = pInfo->pDLS;
+       *pReason = pInfo->Reason;
+
+       return TRUE;
+}
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef QOS_DLS_SUPPORT
+BOOLEAN PeerDlsReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pDA,
+    OUT PUCHAR pSA,
+    OUT USHORT *pCapabilityInfo,
+    OUT USHORT *pDlsTimeout,
+    OUT UCHAR *pRatesLen,
+    OUT UCHAR Rates[],
+       OUT UCHAR *pHtCapabilityLen,
+    OUT HT_CAPABILITY_IE *pHtCapability)
+{
+       CHAR            *Ptr;
+    PFRAME_802_11      Fr = (PFRAME_802_11)Msg;
+       PEID_STRUCT  eid_ptr;
+
+    // to prevent caller from using garbage output value
+    *pCapabilityInfo   = 0;
+    *pDlsTimeout       = 0;
+       *pHtCapabilityLen = 0;
+
+    Ptr = Fr->Octet;
+
+       // offset to destination MAC address (Category and Action field)
+    Ptr += 2;
+
+    // get DA from payload and advance the pointer
+    NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN);
+    Ptr += MAC_ADDR_LEN;
+
+    // get SA from payload and advance the pointer
+    NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN);
+    Ptr += MAC_ADDR_LEN;
+
+    // get capability info from payload and advance the pointer
+    NdisMoveMemory(pCapabilityInfo, Ptr, 2);
+    Ptr += 2;
+
+    // get capability info from payload and advance the pointer
+    NdisMoveMemory(pDlsTimeout, Ptr, 2);
+    Ptr += 2;
+
+       // Category and Action field + DA + SA + capability + Timeout
+       eid_ptr = (PEID_STRUCT) &Fr->Octet[18];
+
+       while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen))
+       {
+               switch(eid_ptr->Eid)
+               {
+                       case IE_SUPP_RATES:
+                if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0))
+                {
+                    NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len);
+                    DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0]));
+                    DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7]));
+                    *pRatesLen = eid_ptr->Len;
+                }
+                else
+                {
+                    *pRatesLen = 8;
+                                       Rates[0] = 0x82;
+                                       Rates[1] = 0x84;
+                                       Rates[2] = 0x8b;
+                                       Rates[3] = 0x96;
+                                       Rates[4] = 0x12;
+                                       Rates[5] = 0x24;
+                                       Rates[6] = 0x48;
+                                       Rates[7] = 0x6c;
+                    DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len));
+                }
+                               break;
+
+                       case IE_EXT_SUPP_RATES:
+                if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES)
+                {
+                    NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len);
+                    *pRatesLen = (*pRatesLen) + eid_ptr->Len;
+                }
+                else
+                {
+                    NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen));
+                    *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES;
+                }
+                               break;
+
+                       case IE_HT_CAP:
+                               if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE))
+                               {
+                                       NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE));
+
+                                       *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
+                                       *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
+                                       *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE);
+
+                                       DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_HT_CAP\n"));
+                               }
+                               else
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len));
+                               }
+                               break;
+
+                       default:
+                               break;
+               }
+
+               eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+       }
+
+    return TRUE;
+}
+
+BOOLEAN PeerDlsRspSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pDA,
+    OUT PUCHAR pSA,
+    OUT USHORT *pCapabilityInfo,
+    OUT USHORT *pStatus,
+    OUT UCHAR *pRatesLen,
+    OUT UCHAR Rates[],
+    OUT UCHAR *pHtCapabilityLen,
+    OUT HT_CAPABILITY_IE *pHtCapability)
+{
+    CHAR            *Ptr;
+    PFRAME_802_11      Fr = (PFRAME_802_11)Msg;
+       PEID_STRUCT  eid_ptr;
+
+    // to prevent caller from using garbage output value
+    *pStatus           = 0;
+    *pCapabilityInfo   = 0;
+       *pHtCapabilityLen = 0;
+
+    Ptr = Fr->Octet;
+
+       // offset to destination MAC address (Category and Action field)
+    Ptr += 2;
+
+       // get status code from payload and advance the pointer
+    NdisMoveMemory(pStatus, Ptr, 2);
+    Ptr += 2;
+
+    // get DA from payload and advance the pointer
+    NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN);
+    Ptr += MAC_ADDR_LEN;
+
+    // get SA from payload and advance the pointer
+    NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN);
+    Ptr += MAC_ADDR_LEN;
+
+       if (pStatus == 0)
+       {
+           // get capability info from payload and advance the pointer
+           NdisMoveMemory(pCapabilityInfo, Ptr, 2);
+           Ptr += 2;
+       }
+
+       // Category and Action field + status code + DA + SA + capability
+       eid_ptr = (PEID_STRUCT) &Fr->Octet[18];
+
+       while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen))
+       {
+               switch(eid_ptr->Eid)
+               {
+                       case IE_SUPP_RATES:
+                if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0))
+                {
+                    NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len);
+                    DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0]));
+                    DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7]));
+                    *pRatesLen = eid_ptr->Len;
+                }
+                else
+                {
+                    *pRatesLen = 8;
+                                       Rates[0] = 0x82;
+                                       Rates[1] = 0x84;
+                                       Rates[2] = 0x8b;
+                                       Rates[3] = 0x96;
+                                       Rates[4] = 0x12;
+                                       Rates[5] = 0x24;
+                                       Rates[6] = 0x48;
+                                       Rates[7] = 0x6c;
+                    DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len));
+                }
+                               break;
+
+                       case IE_EXT_SUPP_RATES:
+                if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES)
+                {
+                    NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len);
+                    *pRatesLen = (*pRatesLen) + eid_ptr->Len;
+                }
+                else
+                {
+                    NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen));
+                    *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES;
+                }
+                               break;
+
+                       case IE_HT_CAP:
+                               if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE))
+                               {
+                                       NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE));
+
+                                       *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
+                                       *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
+                                       *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE);
+
+                                       DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_HT_CAP\n"));
+                               }
+                               else
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len));
+                               }
+                               break;
+
+                       default:
+                               break;
+               }
+
+               eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+       }
+
+    return TRUE;
+}
+
+BOOLEAN PeerDlsTearDownSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pDA,
+    OUT PUCHAR pSA,
+    OUT USHORT *pReason)
+{
+    CHAR            *Ptr;
+    PFRAME_802_11      Fr = (PFRAME_802_11)Msg;
+
+    // to prevent caller from using garbage output value
+    *pReason   = 0;
+
+    Ptr = Fr->Octet;
+
+       // offset to destination MAC address (Category and Action field)
+    Ptr += 2;
+
+    // get DA from payload and advance the pointer
+    NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN);
+    Ptr += MAC_ADDR_LEN;
+
+    // get SA from payload and advance the pointer
+    NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN);
+    Ptr += MAC_ADDR_LEN;
+
+       // get reason code from payload and advance the pointer
+    NdisMoveMemory(pReason, Ptr, 2);
+    Ptr += 2;
+
+    return TRUE;
+}
+#endif // QOS_DLS_SUPPORT //
+
diff --git a/drivers/staging/rt2870/common/cmm_sync.c b/drivers/staging/rt2870/common/cmm_sync.c
new file mode 100644 (file)
index 0000000..2be7c77
--- /dev/null
@@ -0,0 +1,711 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       sync.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       John Chang      2004-09-01      modified for rt2561/2661
+*/
+#include "../rt_config.h"
+
+// 2.4 Ghz channel plan index in the TxPower arrays.
+#define        BG_BAND_REGION_0_START  0                       // 1,2,3,4,5,6,7,8,9,10,11
+#define        BG_BAND_REGION_0_SIZE   11
+#define        BG_BAND_REGION_1_START  0                       // 1,2,3,4,5,6,7,8,9,10,11,12,13
+#define        BG_BAND_REGION_1_SIZE   13
+#define        BG_BAND_REGION_2_START  9                       // 10,11
+#define        BG_BAND_REGION_2_SIZE   2
+#define        BG_BAND_REGION_3_START  9                       // 10,11,12,13
+#define        BG_BAND_REGION_3_SIZE   4
+#define        BG_BAND_REGION_4_START  13                      // 14
+#define        BG_BAND_REGION_4_SIZE   1
+#define        BG_BAND_REGION_5_START  0                       // 1,2,3,4,5,6,7,8,9,10,11,12,13,14
+#define        BG_BAND_REGION_5_SIZE   14
+#define        BG_BAND_REGION_6_START  2                       // 3,4,5,6,7,8,9
+#define        BG_BAND_REGION_6_SIZE   7
+#define        BG_BAND_REGION_7_START  4                       // 5,6,7,8,9,10,11,12,13
+#define        BG_BAND_REGION_7_SIZE   9
+#define        BG_BAND_REGION_31_START 0                       // 1,2,3,4,5,6,7,8,9,10,11,12,13,14
+#define        BG_BAND_REGION_31_SIZE  14
+
+// 5 Ghz channel plan index in the TxPower arrays.
+UCHAR A_BAND_REGION_0_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165};
+UCHAR A_BAND_REGION_1_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
+UCHAR A_BAND_REGION_2_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64};
+UCHAR A_BAND_REGION_3_CHANNEL_LIST[]={52, 56, 60, 64, 149, 153, 157, 161};
+UCHAR A_BAND_REGION_4_CHANNEL_LIST[]={149, 153, 157, 161, 165};
+UCHAR A_BAND_REGION_5_CHANNEL_LIST[]={149, 153, 157, 161};
+UCHAR A_BAND_REGION_6_CHANNEL_LIST[]={36, 40, 44, 48};
+UCHAR A_BAND_REGION_7_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165};
+UCHAR A_BAND_REGION_8_CHANNEL_LIST[]={52, 56, 60, 64};
+UCHAR A_BAND_REGION_9_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165};
+UCHAR A_BAND_REGION_10_CHANNEL_LIST[]={36, 40, 44, 48, 149, 153, 157, 161, 165};
+UCHAR A_BAND_REGION_11_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161};
+
+//BaSizeArray follows the 802.11n definition as MaxRxFactor.  2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8.
+UCHAR BaSizeArray[4] = {8,16,32,64};
+
+/*
+       ==========================================================================
+       Description:
+               Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type,
+               and 3) PHY-mode user selected.
+               The outcome is used by driver when doing site survey.
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID BuildChannelList(
+       IN PRTMP_ADAPTER pAd)
+{
+       UCHAR i, j, index=0, num=0;
+       PUCHAR  pChannelList = NULL;
+
+       NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER));
+
+       // if not 11a-only mode, channel list starts from 2.4Ghz band
+       if ((pAd->CommonCfg.PhyMode != PHY_11A)
+#ifdef DOT11_N_SUPPORT
+               && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) && (pAd->CommonCfg.PhyMode != PHY_11N_5G)
+#endif // DOT11_N_SUPPORT //
+       )
+       {
+               switch (pAd->CommonCfg.CountryRegion  & 0x7f)
+               {
+                       case REGION_0_BG_BAND:  // 1 -11
+                               NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_0_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_0_SIZE);
+                               index += BG_BAND_REGION_0_SIZE;
+                               break;
+                       case REGION_1_BG_BAND:  // 1 - 13
+                               NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_1_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_1_SIZE);
+                               index += BG_BAND_REGION_1_SIZE;
+                               break;
+                       case REGION_2_BG_BAND:  // 10 - 11
+                               NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_2_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_2_SIZE);
+                               index += BG_BAND_REGION_2_SIZE;
+                               break;
+                       case REGION_3_BG_BAND:  // 10 - 13
+                               NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_3_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_3_SIZE);
+                               index += BG_BAND_REGION_3_SIZE;
+                               break;
+                       case REGION_4_BG_BAND:  // 14
+                               NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_4_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_4_SIZE);
+                               index += BG_BAND_REGION_4_SIZE;
+                               break;
+                       case REGION_5_BG_BAND:  // 1 - 14
+                               NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_5_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_5_SIZE);
+                               index += BG_BAND_REGION_5_SIZE;
+                               break;
+                       case REGION_6_BG_BAND:  // 3 - 9
+                               NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_6_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_6_SIZE);
+                               index += BG_BAND_REGION_6_SIZE;
+                               break;
+                       case REGION_7_BG_BAND:  // 5 - 13
+                               NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_7_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_7_SIZE);
+                               index += BG_BAND_REGION_7_SIZE;
+                               break;
+                       case REGION_31_BG_BAND: // 1 - 14
+                               NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_31_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_31_SIZE);
+                               index += BG_BAND_REGION_31_SIZE;
+                               break;
+                       default:            // Error. should never happen
+                               break;
+               }
+               for (i=0; i<index; i++)
+                       pAd->ChannelList[i].MaxTxPwr = 20;
+       }
+
+       if ((pAd->CommonCfg.PhyMode == PHY_11A) || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED)
+#ifdef DOT11_N_SUPPORT
+               || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED)
+               || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)
+#endif // DOT11_N_SUPPORT //
+       )
+       {
+               switch (pAd->CommonCfg.CountryRegionForABand & 0x7f)
+               {
+                       case REGION_0_A_BAND:
+                               num = sizeof(A_BAND_REGION_0_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_0_CHANNEL_LIST;
+                               break;
+                       case REGION_1_A_BAND:
+                               num = sizeof(A_BAND_REGION_1_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_1_CHANNEL_LIST;
+                               break;
+                       case REGION_2_A_BAND:
+                               num = sizeof(A_BAND_REGION_2_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_2_CHANNEL_LIST;
+                               break;
+                       case REGION_3_A_BAND:
+                               num = sizeof(A_BAND_REGION_3_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_3_CHANNEL_LIST;
+                               break;
+                       case REGION_4_A_BAND:
+                               num = sizeof(A_BAND_REGION_4_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_4_CHANNEL_LIST;
+                               break;
+                       case REGION_5_A_BAND:
+                               num = sizeof(A_BAND_REGION_5_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_5_CHANNEL_LIST;
+                               break;
+                       case REGION_6_A_BAND:
+                               num = sizeof(A_BAND_REGION_6_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_6_CHANNEL_LIST;
+                               break;
+                       case REGION_7_A_BAND:
+                               num = sizeof(A_BAND_REGION_7_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_7_CHANNEL_LIST;
+                               break;
+                       case REGION_8_A_BAND:
+                               num = sizeof(A_BAND_REGION_8_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_8_CHANNEL_LIST;
+                               break;
+                       case REGION_9_A_BAND:
+                               num = sizeof(A_BAND_REGION_9_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_9_CHANNEL_LIST;
+                               break;
+
+                       case REGION_10_A_BAND:
+                               num = sizeof(A_BAND_REGION_10_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_10_CHANNEL_LIST;
+                               break;
+
+                       case REGION_11_A_BAND:
+                               num = sizeof(A_BAND_REGION_11_CHANNEL_LIST)/sizeof(UCHAR);
+                               pChannelList = A_BAND_REGION_11_CHANNEL_LIST;
+                               break;
+
+                       default:            // Error. should never happen
+                               DBGPRINT(RT_DEBUG_WARN,("countryregion=%d not support", pAd->CommonCfg.CountryRegionForABand));
+                               break;
+               }
+
+               if (num != 0)
+               {
+                       UCHAR RadarCh[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
+                       for (i=0; i<num; i++)
+                       {
+                               for (j=0; j<MAX_NUM_OF_CHANNELS; j++)
+                               {
+                                       if (pChannelList[i] == pAd->TxPower[j].Channel)
+                                               NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER));
+                                       }
+                               for (j=0; j<15; j++)
+                               {
+                                       if (pChannelList[i] == RadarCh[j])
+                                               pAd->ChannelList[index+i].DfsReq = TRUE;
+                               }
+                               pAd->ChannelList[index+i].MaxTxPwr = 20;
+                       }
+                       index += num;
+               }
+       }
+
+       pAd->ChannelListNum = index;
+       DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n",
+               pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum));
+#ifdef DBG
+       for (i=0;i<pAd->ChannelListNum;i++)
+       {
+               DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, \n ", pAd->ChannelList[i].Channel, pAd->ChannelList[i].Power, pAd->ChannelList[i].Power2));
+       }
+#endif
+}
+
+/*
+       ==========================================================================
+       Description:
+               This routine return the first channel number according to the country
+               code selection and RF IC selection (signal band or dual band). It is called
+               whenever driver need to start a site survey of all supported channels.
+       Return:
+               ch - the first channel number of current country code setting
+
+       IRQL = PASSIVE_LEVEL
+
+       ==========================================================================
+ */
+UCHAR FirstChannel(
+       IN PRTMP_ADAPTER pAd)
+{
+       return pAd->ChannelList[0].Channel;
+}
+
+/*
+       ==========================================================================
+       Description:
+               This routine returns the next channel number. This routine is called
+               during driver need to start a site survey of all supported channels.
+       Return:
+               next_channel - the next channel number valid in current country code setting.
+       Note:
+               return 0 if no more next channel
+       ==========================================================================
+ */
+UCHAR NextChannel(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR channel)
+{
+       int i;
+       UCHAR next_channel = 0;
+
+       for (i = 0; i < (pAd->ChannelListNum - 1); i++)
+               if (channel == pAd->ChannelList[i].Channel)
+               {
+                       next_channel = pAd->ChannelList[i+1].Channel;
+                       break;
+       }
+       return next_channel;
+}
+
+/*
+       ==========================================================================
+       Description:
+               This routine is for Cisco Compatible Extensions 2.X
+               Spec31. AP Control of Client Transmit Power
+       Return:
+               None
+       Note:
+          Required by Aironet dBm(mW)
+                  0dBm(1mW),   1dBm(5mW), 13dBm(20mW), 15dBm(30mW),
+                 17dBm(50mw), 20dBm(100mW)
+
+          We supported
+                  3dBm(Lowest), 6dBm(10%), 9dBm(25%), 12dBm(50%),
+                 14dBm(75%),   15dBm(100%)
+
+               The client station's actual transmit power shall be within +/- 5dB of
+               the minimum value or next lower value.
+       ==========================================================================
+ */
+VOID ChangeToCellPowerLimit(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR         AironetCellPowerLimit)
+{
+       //valud 0xFF means that hasn't found power limit information
+       //from the AP's Beacon/Probe response.
+       if (AironetCellPowerLimit == 0xFF)
+               return;
+
+       if (AironetCellPowerLimit < 6) //Used Lowest Power Percentage.
+               pAd->CommonCfg.TxPowerPercentage = 6;
+       else if (AironetCellPowerLimit < 9)
+               pAd->CommonCfg.TxPowerPercentage = 10;
+       else if (AironetCellPowerLimit < 12)
+               pAd->CommonCfg.TxPowerPercentage = 25;
+       else if (AironetCellPowerLimit < 14)
+               pAd->CommonCfg.TxPowerPercentage = 50;
+       else if (AironetCellPowerLimit < 15)
+               pAd->CommonCfg.TxPowerPercentage = 75;
+       else
+               pAd->CommonCfg.TxPowerPercentage = 100; //else used maximum
+
+       if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault)
+               pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
+
+}
+
+CHAR   ConvertToRssi(
+       IN PRTMP_ADAPTER pAd,
+       IN      CHAR                    Rssi,
+       IN  UCHAR   RssiNumber)
+{
+       UCHAR   RssiOffset, LNAGain;
+
+       // Rssi equals to zero should be an invalid value
+       if (Rssi == 0)
+               return -99;
+
+       LNAGain = GET_LNA_GAIN(pAd);
+    if (pAd->LatchRfRegs.Channel > 14)
+    {
+        if (RssiNumber == 0)
+                       RssiOffset = pAd->ARssiOffset0;
+               else if (RssiNumber == 1)
+                       RssiOffset = pAd->ARssiOffset1;
+               else
+                       RssiOffset = pAd->ARssiOffset2;
+    }
+    else
+    {
+        if (RssiNumber == 0)
+                       RssiOffset = pAd->BGRssiOffset0;
+               else if (RssiNumber == 1)
+                       RssiOffset = pAd->BGRssiOffset1;
+               else
+                       RssiOffset = pAd->BGRssiOffset2;
+    }
+
+    return (-12 - RssiOffset - LNAGain - Rssi);
+}
+
+/*
+       ==========================================================================
+       Description:
+               Scan next channel
+       ==========================================================================
+ */
+VOID ScanNextChannel(
+       IN PRTMP_ADAPTER pAd)
+{
+       HEADER_802_11   Hdr80211;
+       PUCHAR          pOutBuffer = NULL;
+       NDIS_STATUS     NStatus;
+       ULONG           FrameLen = 0;
+       UCHAR           SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0;
+#ifdef CONFIG_STA_SUPPORT
+       USHORT          Status;
+       PHEADER_802_11  pHdr80211;
+#endif // CONFIG_STA_SUPPORT //
+       UINT                    ScanTimeIn5gChannel = SHORT_CHANNEL_TIME;
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               if (MONITOR_ON(pAd))
+                       return;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef RALINK_ATE
+       // Nothing to do in ATE mode.
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+       if (pAd->MlmeAux.Channel == 0)
+       {
+               if ((pAd->CommonCfg.BBPCurrentBW == BW_40)
+#ifdef CONFIG_STA_SUPPORT
+                       && (INFRA_ON(pAd)
+                               || (pAd->OpMode == OPMODE_AP))
+#endif // CONFIG_STA_SUPPORT //
+                       )
+               {
+                       AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+                       AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+                       BBPValue &= (~0x18);
+                       BBPValue |= 0x10;
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+                       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr));
+               }
+               else
+               {
+                       AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+                       AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+                       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n",pAd->CommonCfg.Channel, pAd->ScanTab.BssNr));
+               }
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       //
+                       // To prevent data lost.
+                       // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress.
+                       // Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done
+                       //
+                       if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)))
+                       {
+                               NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);
+                               if (NStatus     == NDIS_STATUS_SUCCESS)
+                               {
+                                       pHdr80211 = (PHEADER_802_11) pOutBuffer;
+                                       MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
+                                       pHdr80211->Duration = 0;
+                                       pHdr80211->FC.Type = BTYPE_DATA;
+                                       pHdr80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
+
+                                       // Send using priority queue
+                                       MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
+                                       DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame\n"));
+                                       MlmeFreeMemory(pAd, pOutBuffer);
+                                       RTMPusecDelay(5000);
+                               }
+                       }
+
+                       pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+                       Status = MLME_SUCCESS;
+                       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+
+               RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+       }
+#ifdef RT2870
+#ifdef CONFIG_STA_SUPPORT
+       else if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->OpMode == OPMODE_STA))
+       {
+               pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+               MlmeCntlConfirm(pAd, MT2_SCAN_CONF, MLME_FAIL_NO_RESOURCE);
+       }
+#endif // CONFIG_STA_SUPPORT //
+#endif // RT2870 //
+       else
+       {
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+               // BBP and RF are not accessible in PS mode, we has to wake them up first
+               if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+                       AsicForceWakeup(pAd, TRUE);
+
+                       // leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON
+                       if (pAd->StaCfg.Psm == PWR_SAVE)
+                               MlmeSetPsmBit(pAd, PWR_ACTIVE);
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+               AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE);
+               AsicLockChannel(pAd, pAd->MlmeAux.Channel);
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       if (pAd->MlmeAux.Channel > 14)
+                       {
+                               if ((pAd->CommonCfg.bIEEE80211H == 1) && RadarChannelCheck(pAd, pAd->MlmeAux.Channel))
+                               {
+                                       ScanType = SCAN_PASSIVE;
+                                       ScanTimeIn5gChannel = MIN_CHANNEL_TIME;
+                               }
+                       }
+
+#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+                       // carrier detection
+                       if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+                       {
+                               ScanType = SCAN_PASSIVE;
+                               ScanTimeIn5gChannel = MIN_CHANNEL_TIME;
+                       }
+#endif // CARRIER_DETECTION_SUPPORT //
+               }
+
+#endif // CONFIG_STA_SUPPORT //
+
+               //Global country domain(ch1-11:active scan, ch12-14 passive scan)
+               if ((pAd->MlmeAux.Channel <= 14) && (pAd->MlmeAux.Channel >= 12) && ((pAd->CommonCfg.CountryRegion & 0x7f) == REGION_31_BG_BAND))
+               {
+                       ScanType = SCAN_PASSIVE;
+               }
+
+               // We need to shorten active scan time in order for WZC connect issue
+               // Chnage the channel scan time for CISCO stuff based on its IAPP announcement
+               if (ScanType == FAST_SCAN_ACTIVE)
+                       RTMPSetTimer(&pAd->MlmeAux.ScanTimer, FAST_ACTIVE_SCAN_TIME);
+#ifdef CONFIG_STA_SUPPORT
+               else if (((ScanType == SCAN_CISCO_ACTIVE) ||
+                               (ScanType == SCAN_CISCO_PASSIVE) ||
+                               (ScanType == SCAN_CISCO_CHANNEL_LOAD) ||
+                               (ScanType == SCAN_CISCO_NOISE)) && (pAd->OpMode == OPMODE_STA))
+               {
+                       if (pAd->StaCfg.CCXScanTime < 25)
+                               RTMPSetTimer(&pAd->MlmeAux.ScanTimer, pAd->StaCfg.CCXScanTime * 2);
+                       else
+                               RTMPSetTimer(&pAd->MlmeAux.ScanTimer, pAd->StaCfg.CCXScanTime);
+               }
+#endif // CONFIG_STA_SUPPORT //
+               else // must be SCAN_PASSIVE or SCAN_ACTIVE
+               {
+                       if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED)
+#ifdef DOT11_N_SUPPORT
+                               || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED)
+#endif // DOT11_N_SUPPORT //
+                       )
+                       {
+                               if (pAd->MlmeAux.Channel > 14)
+                                       RTMPSetTimer(&pAd->MlmeAux.ScanTimer, ScanTimeIn5gChannel);
+                               else
+                               RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MIN_CHANNEL_TIME);
+                       }
+                       else
+                               RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MAX_CHANNEL_TIME);
+               }
+
+               if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) ||
+                       (ScanType == SCAN_CISCO_ACTIVE))
+               {
+                       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+                       if (NStatus != NDIS_STATUS_SUCCESS)
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n"));
+#ifdef CONFIG_STA_SUPPORT
+                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               {
+                                       pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+                                       Status = MLME_FAIL_NO_RESOURCE;
+                                       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
+                               }
+#endif // CONFIG_STA_SUPPORT //
+
+                               return;
+                       }
+
+                       // There is no need to send broadcast probe request if active scan is in effect.
+                       if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE)
+                               )
+                               SsidLen = pAd->MlmeAux.SsidLen;
+                       else
+                               SsidLen = 0;
+
+                       MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
+                       MakeOutgoingFrame(pOutBuffer,               &FrameLen,
+                                                         sizeof(HEADER_802_11),    &Hdr80211,
+                                                         1,                        &SsidIe,
+                                                         1,                        &SsidLen,
+                                                         SsidLen,                              pAd->MlmeAux.Ssid,
+                                                         1,                        &SupRateIe,
+                                                         1,                        &pAd->CommonCfg.SupRateLen,
+                                                         pAd->CommonCfg.SupRateLen,  pAd->CommonCfg.SupRate,
+                                                         END_OF_ARGS);
+
+                       if (pAd->CommonCfg.ExtRateLen)
+                       {
+                               ULONG Tmp;
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,            &Tmp,
+                                                                 1,                                &ExtRateIe,
+                                                                 1,                                &pAd->CommonCfg.ExtRateLen,
+                                                                 pAd->CommonCfg.ExtRateLen,          pAd->CommonCfg.ExtRate,
+                                                                 END_OF_ARGS);
+                               FrameLen += Tmp;
+                       }
+
+#ifdef DOT11_N_SUPPORT
+                       if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+                       {
+                               ULONG   Tmp;
+                               UCHAR   HtLen;
+                               UCHAR   BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
+#ifdef RT_BIG_ENDIAN
+                               HT_CAPABILITY_IE HtCapabilityTmp;
+#endif
+                               if (pAd->bBroadComHT == TRUE)
+                               {
+                                       HtLen = pAd->MlmeAux.HtCapabilityLen + 4;
+#ifdef RT_BIG_ENDIAN
+                                       NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
+                                       *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+                                       *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+                                       MakeOutgoingFrame(pOutBuffer + FrameLen,          &Tmp,
+                                                                       1,                                &WpaIe,
+                                                                       1,                                &HtLen,
+                                                                       4,                                &BROADCOM[0],
+                                                                       pAd->MlmeAux.HtCapabilityLen,     &HtCapabilityTmp,
+                                                                       END_OF_ARGS);
+#else
+                                       MakeOutgoingFrame(pOutBuffer + FrameLen,          &Tmp,
+                                                                       1,                                &WpaIe,
+                                                                       1,                                &HtLen,
+                                                                       4,                                &BROADCOM[0],
+                                                                       pAd->MlmeAux.HtCapabilityLen,     &pAd->MlmeAux.HtCapability,
+                                                                       END_OF_ARGS);
+#endif // RT_BIG_ENDIAN //
+                               }
+                               else
+                               {
+                                       HtLen = pAd->MlmeAux.HtCapabilityLen;
+#ifdef RT_BIG_ENDIAN
+                                       NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE);
+                                       *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+                                       *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+                                       MakeOutgoingFrame(pOutBuffer + FrameLen,          &Tmp,
+                                                                       1,                                &HtCapIe,
+                                                                       1,                                &HtLen,
+                                                                       HtLen,                            &HtCapabilityTmp,
+                                                                       END_OF_ARGS);
+#else
+                                       MakeOutgoingFrame(pOutBuffer + FrameLen,          &Tmp,
+                                                                       1,                                &HtCapIe,
+                                                                       1,                                &HtLen,
+                                                                       HtLen,                            &pAd->CommonCfg.HtCapability,
+                                                                       END_OF_ARGS);
+#endif // RT_BIG_ENDIAN //
+                               }
+                               FrameLen += Tmp;
+
+#ifdef DOT11N_DRAFT3
+                               if (pAd->CommonCfg.BACapability.field.b2040CoexistScanSup == 1)
+                               {
+                                       ULONG           Tmp;
+                                       HtLen = 1;
+                                       MakeOutgoingFrame(pOutBuffer + FrameLen,            &Tmp,
+                                                                         1,                                    &ExtHtCapIe,
+                                                                         1,                                    &HtLen,
+                                                                         1,                            &pAd->CommonCfg.BSSCoexist2040.word,
+                                                                         END_OF_ARGS);
+
+                                       FrameLen += Tmp;
+                               }
+#endif // DOT11N_DRAFT3 //
+                       }
+#endif // DOT11_N_SUPPORT //
+
+
+                       MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+                       MlmeFreeMemory(pAd, pOutBuffer);
+               }
+
+               // For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN;
+#endif // CONFIG_STA_SUPPORT //
+
+       }
+}
+
+VOID MgtProbReqMacHeaderInit(
+       IN      PRTMP_ADAPTER   pAd,
+       IN OUT PHEADER_802_11 pHdr80211,
+       IN UCHAR SubType,
+       IN UCHAR ToDs,
+       IN PUCHAR pDA,
+       IN PUCHAR pBssid)
+{
+       NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
+
+       pHdr80211->FC.Type = BTYPE_MGMT;
+       pHdr80211->FC.SubType = SubType;
+       if (SubType == SUBTYPE_ACK)
+               pHdr80211->FC.Type = BTYPE_CNTL;
+       pHdr80211->FC.ToDs = ToDs;
+       COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
+       COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
+       COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
+}
+
+
diff --git a/drivers/staging/rt2870/common/cmm_wpa.c b/drivers/staging/rt2870/common/cmm_wpa.c
new file mode 100644 (file)
index 0000000..d2c24bd
--- /dev/null
@@ -0,0 +1,1654 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       wpa.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Jan     Lee             03-07-22                Initial
+       Paul Lin        03-11-28                Modify for supplicant
+*/
+#include "../rt_config.h"
+// WPA OUI
+UCHAR          OUI_WPA_NONE_AKM[4]             = {0x00, 0x50, 0xF2, 0x00};
+UCHAR       OUI_WPA_VERSION[4]      = {0x00, 0x50, 0xF2, 0x01};
+UCHAR       OUI_WPA_WEP40[4]      = {0x00, 0x50, 0xF2, 0x01};
+UCHAR       OUI_WPA_TKIP[4]     = {0x00, 0x50, 0xF2, 0x02};
+UCHAR       OUI_WPA_CCMP[4]     = {0x00, 0x50, 0xF2, 0x04};
+UCHAR       OUI_WPA_WEP104[4]      = {0x00, 0x50, 0xF2, 0x05};
+UCHAR       OUI_WPA_8021X_AKM[4]       = {0x00, 0x50, 0xF2, 0x01};
+UCHAR       OUI_WPA_PSK_AKM[4]      = {0x00, 0x50, 0xF2, 0x02};
+// WPA2 OUI
+UCHAR       OUI_WPA2_WEP40[4]   = {0x00, 0x0F, 0xAC, 0x01};
+UCHAR       OUI_WPA2_TKIP[4]        = {0x00, 0x0F, 0xAC, 0x02};
+UCHAR       OUI_WPA2_CCMP[4]        = {0x00, 0x0F, 0xAC, 0x04};
+UCHAR       OUI_WPA2_8021X_AKM[4]   = {0x00, 0x0F, 0xAC, 0x01};
+UCHAR       OUI_WPA2_PSK_AKM[4]        = {0x00, 0x0F, 0xAC, 0x02};
+UCHAR       OUI_WPA2_WEP104[4]   = {0x00, 0x0F, 0xAC, 0x05};
+// MSA OUI
+UCHAR          OUI_MSA_8021X_AKM[4]    = {0x00, 0x0F, 0xAC, 0x05};             // Not yet final - IEEE 802.11s-D1.06
+UCHAR          OUI_MSA_PSK_AKM[4]      = {0x00, 0x0F, 0xAC, 0x06};             // Not yet final - IEEE 802.11s-D1.06
+
+/*
+       ========================================================================
+
+       Routine Description:
+               The pseudo-random function(PRF) that hashes various inputs to
+               derive a pseudo-random value. To add liveness to the pseudo-random
+               value, a nonce should be one of the inputs.
+
+               It is used to generate PTK, GTK or some specific random value.
+
+       Arguments:
+               UCHAR   *key,           -       the key material for HMAC_SHA1 use
+               INT             key_len         -       the length of key
+               UCHAR   *prefix         -       a prefix label
+               INT             prefix_len      -       the length of the label
+               UCHAR   *data           -       a specific data with variable length
+               INT             data_len        -       the length of a specific data
+               INT             len                     -       the output lenght
+
+       Return Value:
+               UCHAR   *output         -       the calculated result
+
+       Note:
+               802.11i-2004    Annex H.3
+
+       ========================================================================
+*/
+VOID   PRF(
+       IN      UCHAR   *key,
+       IN      INT             key_len,
+       IN      UCHAR   *prefix,
+       IN      INT             prefix_len,
+       IN      UCHAR   *data,
+       IN      INT             data_len,
+       OUT     UCHAR   *output,
+       IN      INT             len)
+{
+       INT             i;
+    UCHAR   *input;
+       INT             currentindex = 0;
+       INT             total_len;
+
+       // Allocate memory for input
+       os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
+
+    if (input == NULL)
+    {
+        DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
+        return;
+    }
+
+       // Generate concatenation input
+       NdisMoveMemory(input, prefix, prefix_len);
+
+       // Concatenate a single octet containing 0
+       input[prefix_len] =     0;
+
+       // Concatenate specific data
+       NdisMoveMemory(&input[prefix_len + 1], data, data_len);
+       total_len =     prefix_len + 1 + data_len;
+
+       // Concatenate a single octet containing 0
+       // This octet shall be update later
+       input[total_len] = 0;
+       total_len++;
+
+       // Iterate to calculate the result by hmac-sha-1
+       // Then concatenate to last result
+       for     (i = 0; i <     (len + 19) / 20; i++)
+       {
+               HMAC_SHA1(input, total_len,     key, key_len, &output[currentindex]);
+               currentindex += 20;
+
+               // update the last octet
+               input[total_len - 1]++;
+       }
+    os_free_mem(NULL, input);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
+               It shall be called by 4-way handshake processing.
+
+       Arguments:
+               pAd     -       pointer to our pAdapter context
+               PMK             -       pointer to PMK
+               ANonce  -       pointer to ANonce
+               AA              -       pointer to Authenticator Address
+               SNonce  -       pointer to SNonce
+               SA              -       pointer to Supplicant Address
+               len             -       indicate the length of PTK (octet)
+
+       Return Value:
+               Output          pointer to the PTK
+
+       Note:
+               Refer to IEEE 802.11i-2004 8.5.1.2
+
+       ========================================================================
+*/
+VOID WpaCountPTK(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR   *PMK,
+       IN      UCHAR   *ANonce,
+       IN      UCHAR   *AA,
+       IN      UCHAR   *SNonce,
+       IN      UCHAR   *SA,
+       OUT     UCHAR   *output,
+       IN      UINT    len)
+{
+       UCHAR   concatenation[76];
+       UINT    CurrPos = 0;
+       UCHAR   temp[32];
+       UCHAR   Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
+                                               'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
+
+       // initiate the concatenation input
+       NdisZeroMemory(temp, sizeof(temp));
+       NdisZeroMemory(concatenation, 76);
+
+       // Get smaller address
+       if (RTMPCompareMemory(SA, AA, 6) == 1)
+               NdisMoveMemory(concatenation, AA, 6);
+       else
+               NdisMoveMemory(concatenation, SA, 6);
+       CurrPos += 6;
+
+       // Get larger address
+       if (RTMPCompareMemory(SA, AA, 6) == 1)
+               NdisMoveMemory(&concatenation[CurrPos], SA, 6);
+       else
+               NdisMoveMemory(&concatenation[CurrPos], AA, 6);
+
+       // store the larger mac address for backward compatible of
+       // ralink proprietary STA-key issue
+       NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
+       CurrPos += 6;
+
+       // Get smaller Nonce
+       if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
+               NdisMoveMemory(&concatenation[CurrPos], temp, 32);      // patch for ralink proprietary STA-key issue
+       else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
+               NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
+       else
+               NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
+       CurrPos += 32;
+
+       // Get larger Nonce
+       if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
+               NdisMoveMemory(&concatenation[CurrPos], temp, 32);      // patch for ralink proprietary STA-key issue
+       else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
+               NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
+       else
+               NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
+       CurrPos += 32;
+
+       hex_dump("concatenation=", concatenation, 76);
+
+       // Use PRF to generate PTK
+       PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Generate random number by software.
+
+       Arguments:
+               pAd             -       pointer to our pAdapter context
+               macAddr -       pointer to local MAC address
+
+       Return Value:
+
+       Note:
+               802.1ii-2004  Annex H.5
+
+       ========================================================================
+*/
+VOID   GenRandom(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   *macAddr,
+       OUT     UCHAR                   *random)
+{
+       INT             i, curr;
+       UCHAR   local[80], KeyCounter[32];
+       UCHAR   result[80];
+       ULONG   CurrentTime;
+       UCHAR   prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
+
+       // Zero the related information
+       NdisZeroMemory(result, 80);
+       NdisZeroMemory(local, 80);
+       NdisZeroMemory(KeyCounter, 32);
+
+       for     (i = 0; i <     32;     i++)
+       {
+               // copy the local MAC address
+               COPY_MAC_ADDR(local, macAddr);
+               curr =  MAC_ADDR_LEN;
+
+               // concatenate the current time
+               NdisGetSystemUpTime(&CurrentTime);
+               NdisMoveMemory(&local[curr],  &CurrentTime,     sizeof(CurrentTime));
+               curr += sizeof(CurrentTime);
+
+               // concatenate the last result
+               NdisMoveMemory(&local[curr],  result, 32);
+               curr += 32;
+
+               // concatenate a variable
+               NdisMoveMemory(&local[curr],  &i,  2);
+               curr += 2;
+
+               // calculate the result
+               PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
+       }
+
+       NdisMoveMemory(random, result,  32);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Build cipher suite in RSN-IE.
+               It only shall be called by RTMPMakeRSNIE.
+
+       Arguments:
+               pAd                     -       pointer to our pAdapter context
+       ElementID       -       indicate the WPA1 or WPA2
+       WepStatus       -       indicate the encryption type
+               bMixCipher      -       a boolean to indicate the pairwise cipher and group
+                                               cipher are the same or not
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+static VOID RTMPInsertRsnIeCipher(
+       IN  PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   ElementID,
+       IN      UINT                    WepStatus,
+       IN      BOOLEAN                 bMixCipher,
+       IN      UCHAR                   FlexibleCipher,
+       OUT     PUCHAR                  pRsnIe,
+       OUT     UCHAR                   *rsn_len)
+{
+       UCHAR   PairwiseCnt;
+
+       *rsn_len = 0;
+
+       // decide WPA2 or WPA1
+       if (ElementID == Wpa2Ie)
+       {
+               RSNIE2  *pRsnie_cipher = (RSNIE2*)pRsnIe;
+
+               // Assign the verson as 1
+               pRsnie_cipher->version = 1;
+
+        switch (WepStatus)
+        {
+               // TKIP mode
+            case Ndis802_11Encryption2Enabled:
+                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
+                pRsnie_cipher->ucount = 1;
+                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
+                *rsn_len = sizeof(RSNIE2);
+                break;
+
+                       // AES mode
+            case Ndis802_11Encryption3Enabled:
+                               if (bMixCipher)
+                                       NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
+                               else
+                                       NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4);
+                pRsnie_cipher->ucount = 1;
+                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
+                *rsn_len = sizeof(RSNIE2);
+                break;
+
+                       // TKIP-AES mix mode
+            case Ndis802_11Encryption4Enabled:
+                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
+
+                               PairwiseCnt = 1;
+                               // Insert WPA2 TKIP as the first pairwise cipher
+                               if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
+                               {
+                       NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
+                                       // Insert WPA2 AES as the secondary pairwise cipher
+                                       if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher))
+                                       {
+                               NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4);
+                                               PairwiseCnt = 2;
+                                       }
+                               }
+                               else
+                               {
+                                       // Insert WPA2 AES as the first pairwise cipher
+                                       NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
+                               }
+
+                pRsnie_cipher->ucount = PairwiseCnt;
+                *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
+                break;
+        }
+
+#ifdef CONFIG_STA_SUPPORT
+               if ((pAd->OpMode == OPMODE_STA) &&
+                       (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
+                       (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
+               {
+                       UINT GroupCipher = pAd->StaCfg.GroupCipher;
+                       switch(GroupCipher)
+                       {
+                               case Ndis802_11GroupWEP40Enabled:
+                                       NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4);
+                                       break;
+                               case Ndis802_11GroupWEP104Enabled:
+                                       NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4);
+                                       break;
+                       }
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+               // swap for big-endian platform
+               pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
+           pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
+       }
+       else
+       {
+               RSNIE   *pRsnie_cipher = (RSNIE*)pRsnIe;
+
+               // Assign OUI and version
+               NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
+        pRsnie_cipher->version = 1;
+
+               switch (WepStatus)
+               {
+                       // TKIP mode
+            case Ndis802_11Encryption2Enabled:
+                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
+                pRsnie_cipher->ucount = 1;
+                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
+                *rsn_len = sizeof(RSNIE);
+                break;
+
+                       // AES mode
+            case Ndis802_11Encryption3Enabled:
+                               if (bMixCipher)
+                                       NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
+                               else
+                                       NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
+                pRsnie_cipher->ucount = 1;
+                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
+                *rsn_len = sizeof(RSNIE);
+                break;
+
+                       // TKIP-AES mix mode
+            case Ndis802_11Encryption4Enabled:
+                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
+
+                               PairwiseCnt = 1;
+                               // Insert WPA TKIP as the first pairwise cipher
+                               if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
+                               {
+                       NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
+                                       // Insert WPA AES as the secondary pairwise cipher
+                                       if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
+                                       {
+                               NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
+                                               PairwiseCnt = 2;
+                                       }
+                               }
+                               else
+                               {
+                                       // Insert WPA AES as the first pairwise cipher
+                                       NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
+                               }
+
+                pRsnie_cipher->ucount = PairwiseCnt;
+                *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
+                break;
+        }
+
+#ifdef CONFIG_STA_SUPPORT
+               if ((pAd->OpMode == OPMODE_STA) &&
+                       (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
+                       (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
+               {
+                       UINT GroupCipher = pAd->StaCfg.GroupCipher;
+                       switch(GroupCipher)
+                       {
+                               case Ndis802_11GroupWEP40Enabled:
+                                       NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4);
+                                       break;
+                               case Ndis802_11GroupWEP104Enabled:
+                                       NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4);
+                                       break;
+                       }
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+               // swap for big-endian platform
+               pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
+           pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Build AKM suite in RSN-IE.
+               It only shall be called by RTMPMakeRSNIE.
+
+       Arguments:
+               pAd                     -       pointer to our pAdapter context
+       ElementID       -       indicate the WPA1 or WPA2
+       AuthMode        -       indicate the authentication mode
+               apidx           -       indicate the interface index
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+static VOID RTMPInsertRsnIeAKM(
+       IN  PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   ElementID,
+       IN      UINT                    AuthMode,
+       IN      UCHAR                   apidx,
+       OUT     PUCHAR                  pRsnIe,
+       OUT     UCHAR                   *rsn_len)
+{
+       RSNIE_AUTH              *pRsnie_auth;
+
+       pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
+
+       // decide WPA2 or WPA1
+       if (ElementID == Wpa2Ie)
+       {
+               switch (AuthMode)
+        {
+            case Ndis802_11AuthModeWPA2:
+            case Ndis802_11AuthModeWPA1WPA2:
+                pRsnie_auth->acount = 1;
+                       NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
+                break;
+
+            case Ndis802_11AuthModeWPA2PSK:
+            case Ndis802_11AuthModeWPA1PSKWPA2PSK:
+                pRsnie_auth->acount = 1;
+                       NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
+                break;
+        }
+       }
+       else
+       {
+               switch (AuthMode)
+        {
+            case Ndis802_11AuthModeWPA:
+            case Ndis802_11AuthModeWPA1WPA2:
+                pRsnie_auth->acount = 1;
+                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
+                break;
+
+            case Ndis802_11AuthModeWPAPSK:
+            case Ndis802_11AuthModeWPA1PSKWPA2PSK:
+                pRsnie_auth->acount = 1;
+                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
+                break;
+
+                       case Ndis802_11AuthModeWPANone:
+                pRsnie_auth->acount = 1;
+                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
+                break;
+        }
+       }
+
+       pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
+
+       (*rsn_len) += sizeof(RSNIE_AUTH);       // update current RSNIE length
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Build capability in RSN-IE.
+               It only shall be called by RTMPMakeRSNIE.
+
+       Arguments:
+               pAd                     -       pointer to our pAdapter context
+       ElementID       -       indicate the WPA1 or WPA2
+               apidx           -       indicate the interface index
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+static VOID RTMPInsertRsnIeCap(
+       IN  PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   ElementID,
+       IN      UCHAR                   apidx,
+       OUT     PUCHAR                  pRsnIe,
+       OUT     UCHAR                   *rsn_len)
+{
+       RSN_CAPABILITIES    *pRSN_Cap;
+
+       // it could be ignored in WPA1 mode
+       if (ElementID == WpaIe)
+               return;
+
+       pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
+
+
+       pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
+
+       (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
+
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Build RSN IE context. It is not included element-ID and length.
+
+       Arguments:
+               pAd                     -       pointer to our pAdapter context
+       AuthMode        -       indicate the authentication mode
+       WepStatus       -       indicate the encryption type
+               apidx           -       indicate the interface index
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID RTMPMakeRSNIE(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  UINT            AuthMode,
+    IN  UINT            WepStatus,
+       IN      UCHAR                   apidx)
+{
+       PUCHAR          pRsnIe = NULL;                  // primary RSNIE
+       UCHAR           *rsnielen_cur_p = 0;    // the length of the primary RSNIE
+       UCHAR           *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE
+       UCHAR           PrimaryRsnie;
+       BOOLEAN         bMixCipher = FALSE;     // indicate the pairwise and group cipher are different
+       UCHAR           p_offset;
+       WPA_MIX_PAIR_CIPHER             FlexibleCipher = MIX_CIPHER_NOTUSE;     // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
+
+       rsnielen_cur_p = NULL;
+       rsnielen_ex_cur_p = NULL;
+
+       {
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+#ifdef WPA_SUPPLICANT_SUPPORT
+                       if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+                       {
+                               if (AuthMode < Ndis802_11AuthModeWPA)
+                                       return;
+                       }
+                       else
+#endif // WPA_SUPPLICANT_SUPPORT //
+                       {
+                               // Support WPAPSK or WPA2PSK in STA-Infra mode
+                               // Support WPANone in STA-Adhoc mode
+                               if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
+                                       (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
+                                       (AuthMode != Ndis802_11AuthModeWPANone)
+                                       )
+                                       return;
+                       }
+
+                       DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
+
+                       // Zero RSNIE context
+                       pAd->StaCfg.RSNIE_Len = 0;
+                       NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
+
+                       // Pointer to RSNIE
+                       rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
+                       pRsnIe = pAd->StaCfg.RSN_IE;
+
+                       bMixCipher = pAd->StaCfg.bMixCipher;
+               }
+#endif // CONFIG_STA_SUPPORT //
+       }
+
+       // indicate primary RSNIE as WPA or WPA2
+       if ((AuthMode == Ndis802_11AuthModeWPA) ||
+               (AuthMode == Ndis802_11AuthModeWPAPSK) ||
+               (AuthMode == Ndis802_11AuthModeWPANone) ||
+               (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
+               (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
+               PrimaryRsnie = WpaIe;
+       else
+               PrimaryRsnie = Wpa2Ie;
+
+       {
+               // Build the primary RSNIE
+               // 1. insert cipher suite
+               RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
+
+               // 2. insert AKM
+               RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
+
+               // 3. insert capability
+               RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
+       }
+
+       // 4. update the RSNIE length
+       *rsnielen_cur_p = p_offset;
+
+       hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
+
+
+}
+
+/*
+    ==========================================================================
+    Description:
+               Check whether the received frame is EAP frame.
+
+       Arguments:
+               pAd                             -       pointer to our pAdapter context
+               pEntry                  -       pointer to active entry
+               pData                   -       the received frame
+               DataByteCount   -       the received frame's length
+               FromWhichBSSID  -       indicate the interface index
+
+    Return:
+         TRUE                  -       This frame is EAP frame
+         FALSE                         -       otherwise
+    ==========================================================================
+*/
+BOOLEAN RTMPCheckWPAframe(
+    IN PRTMP_ADAPTER    pAd,
+    IN PMAC_TABLE_ENTRY        pEntry,
+    IN PUCHAR           pData,
+    IN ULONG            DataByteCount,
+       IN UCHAR                        FromWhichBSSID)
+{
+       ULONG   Body_len;
+       BOOLEAN Cancelled;
+
+
+    if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
+        return FALSE;
+
+
+       // Skip LLC header
+    if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
+        // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
+        NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
+    {
+        pData += 6;
+    }
+       // Skip 2-bytes EAPoL type
+    if (NdisEqualMemory(EAPOL, pData, 2))
+    {
+        pData += 2;
+    }
+    else
+        return FALSE;
+
+    switch (*(pData+1))
+    {
+        case EAPPacket:
+                       Body_len = (*(pData+2)<<8) | (*(pData+3));
+            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
+            break;
+        case EAPOLStart:
+            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
+                       if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
+            {
+               DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
+                RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
+                pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+            }
+            break;
+        case EAPOLLogoff:
+            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
+            break;
+        case EAPOLKey:
+                       Body_len = (*(pData+2)<<8) | (*(pData+3));
+            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
+            break;
+        case EAPOLASFAlert:
+            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
+            break;
+        default:
+            return FALSE;
+
+    }
+    return TRUE;
+}
+
+
+/*
+    ==========================================================================
+    Description:
+        ENCRYPT AES GTK before sending in EAPOL frame.
+        AES GTK length = 128 bit,  so fix blocks for aes-key-wrap as 2 in this function.
+        This function references to RFC 3394 for aes key wrap algorithm.
+    Return:
+    ==========================================================================
+*/
+VOID AES_GTK_KEY_WRAP(
+    IN UCHAR    *key,
+    IN UCHAR    *plaintext,
+    IN UCHAR    p_len,
+    OUT UCHAR   *ciphertext)
+{
+    UCHAR       A[8], BIN[16], BOUT[16];
+    UCHAR       R[512];
+    INT         num_blocks = p_len/8;   // unit:64bits
+    INT         i, j;
+    aes_context aesctx;
+    UCHAR       xor;
+
+    rtmp_aes_set_key(&aesctx, key, 128);
+
+    // Init IA
+    for (i = 0; i < 8; i++)
+        A[i] = 0xa6;
+
+    //Input plaintext
+    for (i = 0; i < num_blocks; i++)
+    {
+        for (j = 0 ; j < 8; j++)
+            R[8 * (i + 1) + j] = plaintext[8 * i + j];
+    }
+
+    // Key Mix
+    for (j = 0; j < 6; j++)
+    {
+        for(i = 1; i <= num_blocks; i++)
+        {
+            //phase 1
+            NdisMoveMemory(BIN, A, 8);
+            NdisMoveMemory(&BIN[8], &R[8 * i], 8);
+            rtmp_aes_encrypt(&aesctx, BIN, BOUT);
+
+            NdisMoveMemory(A, &BOUT[0], 8);
+            xor = num_blocks * j + i;
+            A[7] = BOUT[7] ^ xor;
+            NdisMoveMemory(&R[8 * i], &BOUT[8], 8);
+        }
+    }
+
+    // Output ciphertext
+    NdisMoveMemory(ciphertext, A, 8);
+
+    for (i = 1; i <= num_blocks; i++)
+    {
+        for (j = 0 ; j < 8; j++)
+            ciphertext[8 * i + j] = R[8 * i + j];
+    }
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Misc function to decrypt AES body
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+               This function references to     RFC     3394 for aes key unwrap algorithm.
+
+       ========================================================================
+*/
+VOID   AES_GTK_KEY_UNWRAP(
+       IN      UCHAR   *key,
+       OUT     UCHAR   *plaintext,
+       IN      UCHAR    c_len,
+       IN      UCHAR   *ciphertext)
+
+{
+       UCHAR       A[8], BIN[16], BOUT[16];
+       UCHAR       xor;
+       INT         i, j;
+       aes_context aesctx;
+       UCHAR       *R;
+       INT         num_blocks = c_len/8;       // unit:64bits
+
+
+       os_alloc_mem(NULL, (PUCHAR *)&R, 512);
+
+       if (R == NULL)
+    {
+        DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));
+        return;
+    } /* End of if */
+
+       // Initialize
+       NdisMoveMemory(A, ciphertext, 8);
+       //Input plaintext
+       for(i = 0; i < (c_len-8); i++)
+       {
+               R[ i] = ciphertext[i + 8];
+       }
+
+       rtmp_aes_set_key(&aesctx, key, 128);
+
+       for(j = 5; j >= 0; j--)
+       {
+               for(i = (num_blocks-1); i > 0; i--)
+               {
+                       xor = (num_blocks -1 )* j + i;
+                       NdisMoveMemory(BIN, A, 8);
+                       BIN[7] = A[7] ^ xor;
+                       NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8);
+                       rtmp_aes_decrypt(&aesctx, BIN, BOUT);
+                       NdisMoveMemory(A, &BOUT[0], 8);
+                       NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8);
+               }
+       }
+
+       // OUTPUT
+       for(i = 0; i < c_len; i++)
+       {
+               plaintext[i] = R[i];
+       }
+
+
+       os_free_mem(NULL, R);
+}
+
+/*
+    ==========================================================================
+    Description:
+               Report the EAP message type
+
+       Arguments:
+               msg             -       EAPOL_PAIR_MSG_1
+                                       EAPOL_PAIR_MSG_2
+                                       EAPOL_PAIR_MSG_3
+                                       EAPOL_PAIR_MSG_4
+                                       EAPOL_GROUP_MSG_1
+                                       EAPOL_GROUP_MSG_2
+
+    Return:
+         message type string
+
+    ==========================================================================
+*/
+CHAR *GetEapolMsgType(CHAR msg)
+{
+    if(msg == EAPOL_PAIR_MSG_1)
+        return "Pairwise Message 1";
+    else if(msg == EAPOL_PAIR_MSG_2)
+        return "Pairwise Message 2";
+       else if(msg == EAPOL_PAIR_MSG_3)
+        return "Pairwise Message 3";
+       else if(msg == EAPOL_PAIR_MSG_4)
+        return "Pairwise Message 4";
+       else if(msg == EAPOL_GROUP_MSG_1)
+        return "Group Message 1";
+       else if(msg == EAPOL_GROUP_MSG_2)
+        return "Group Message 2";
+    else
+       return "Invalid Message";
+}
+
+
+/*
+    ========================================================================
+
+    Routine Description:
+    Check Sanity RSN IE of EAPoL message
+
+    Arguments:
+
+    Return Value:
+
+
+    ========================================================================
+*/
+BOOLEAN RTMPCheckRSNIE(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pData,
+       IN  UCHAR           DataLen,
+       IN  MAC_TABLE_ENTRY *pEntry,
+       OUT     UCHAR                   *Offset)
+{
+       PUCHAR              pVIE;
+       UCHAR               len;
+       PEID_STRUCT         pEid;
+       BOOLEAN                         result = FALSE;
+
+       pVIE = pData;
+       len      = DataLen;
+       *Offset = 0;
+
+       while (len > sizeof(RSNIE2))
+       {
+               pEid = (PEID_STRUCT) pVIE;
+               // WPA RSN IE
+               if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
+               {
+                       if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) &&
+                               (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
+                               (pEntry->RSNIE_Len == (pEid->Len + 2)))
+                       {
+                                       result = TRUE;
+                       }
+
+                       *Offset += (pEid->Len + 2);
+               }
+               // WPA2 RSN IE
+               else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
+               {
+                       if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) &&
+                               (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
+                               (pEntry->RSNIE_Len == (pEid->Len + 2))/* ToDo-AlbertY for mesh*/)
+                       {
+                                       result = TRUE;
+                       }
+
+                       *Offset += (pEid->Len + 2);
+               }
+               else
+               {
+                       break;
+               }
+
+               pVIE += (pEid->Len + 2);
+               len  -= (pEid->Len + 2);
+       }
+
+
+       return result;
+
+}
+
+
+/*
+    ========================================================================
+
+    Routine Description:
+    Parse KEYDATA field.  KEYDATA[] May contain 2 RSN IE and optionally GTK.
+    GTK  is encaptulated in KDE format at  p.83 802.11i D10
+
+    Arguments:
+
+    Return Value:
+
+    Note:
+        802.11i D10
+
+    ========================================================================
+*/
+BOOLEAN RTMPParseEapolKeyData(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pKeyData,
+       IN  UCHAR           KeyDataLen,
+       IN      UCHAR                   GroupKeyIndex,
+       IN      UCHAR                   MsgType,
+       IN      BOOLEAN                 bWPA2,
+       IN  MAC_TABLE_ENTRY *pEntry)
+{
+    PKDE_ENCAP          pKDE = NULL;
+    PUCHAR              pMyKeyData = pKeyData;
+    UCHAR               KeyDataLength = KeyDataLen;
+    UCHAR               GTKLEN = 0;
+       UCHAR                           DefaultIdx = 0;
+       UCHAR                           skip_offset;
+
+       // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it
+       if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3)
+    {
+               // Check RSN IE whether it is WPA2/WPA2PSK
+               if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset))
+               {
+                       // send wireless event - for RSN IE different
+                       if (pAd->CommonCfg.bWirelessEvent)
+                               RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+               DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType));
+                       hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
+                       hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len);
+
+                       return FALSE;
+       }
+       else
+               {
+                       if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)
+                       {
+                               // skip RSN IE
+                               pMyKeyData += skip_offset;
+                               KeyDataLength -= skip_offset;
+                               DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
+                       }
+                       else
+                               return TRUE;
+               }
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
+
+       // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2
+       if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1))
+       {
+               if (KeyDataLength >= 8) // KDE format exclude GTK length
+       {
+               pKDE = (PKDE_ENCAP) pMyKeyData;
+
+
+                       DefaultIdx = pKDE->GTKEncap.Kid;
+
+                       // Sanity check - KED length
+                       if (KeyDataLength < (pKDE->Len + 2))
+               {
+                       DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
+                       return FALSE;
+               }
+
+                       // Get GTK length - refer to IEEE 802.11i-2004 p.82
+                       GTKLEN = pKDE->Len -6;
+                       if (GTKLEN < LEN_AES_KEY)
+                       {
+                               DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
+                       return FALSE;
+                       }
+
+       }
+               else
+       {
+                       DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n"));
+               return FALSE;
+       }
+
+               DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
+               // skip it
+               pMyKeyData += 8;
+               KeyDataLength -= 8;
+
+       }
+       else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1)
+       {
+               DefaultIdx = GroupKeyIndex;
+               DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx));
+       }
+
+       // Sanity check - shared key index must be 1 ~ 3
+       if (DefaultIdx < 1 || DefaultIdx > 3)
+    {
+       DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
+        return FALSE;
+    }
+
+
+#ifdef CONFIG_STA_SUPPORT
+       // Todo
+#endif // CONFIG_STA_SUPPORT //
+
+       return TRUE;
+
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Construct EAPoL message for WPA handshaking
+               Its format is below,
+
+               +--------------------+
+               | Protocol Version       |  1 octet
+               +--------------------+
+               | Protocol Type          |      1 octet
+               +--------------------+
+               | Body Length            |  2 octets
+               +--------------------+
+               | Descriptor Type        |      1 octet
+               +--------------------+
+               | Key Information    |  2 octets
+               +--------------------+
+               | Key Length         |  1 octet
+               +--------------------+
+               | Key Repaly Counter |  8 octets
+               +--------------------+
+               | Key Nonce                  |  32 octets
+               +--------------------+
+               | Key IV                         |  16 octets
+               +--------------------+
+               | Key RSC                        |  8 octets
+               +--------------------+
+               | Key ID or Reserved |  8 octets
+               +--------------------+
+               | Key MIC                        |      16 octets
+               +--------------------+
+               | Key Data Length        |      2 octets
+               +--------------------+
+               | Key Data                       |      n octets
+               +--------------------+
+
+
+       Arguments:
+               pAd                     Pointer to our adapter
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   ConstructEapolMsg(
+       IN      PRTMP_ADAPTER           pAd,
+    IN         UCHAR                           AuthMode,
+    IN         UCHAR                           WepStatus,
+    IN         UCHAR                           GroupKeyWepStatus,
+    IN         UCHAR                           MsgType,
+    IN UCHAR                           DefaultKeyIdx,
+    IN         UCHAR                           *ReplayCounter,
+       IN      UCHAR                           *KeyNonce,
+       IN      UCHAR                           *TxRSC,
+       IN      UCHAR                           *PTK,
+       IN      UCHAR                           *GTK,
+       IN      UCHAR                           *RSNIE,
+       IN      UCHAR                           RSNIE_Len,
+    OUT PEAPOL_PACKET       pMsg)
+{
+       BOOLEAN bWPA2 = FALSE;
+
+       // Choose WPA2 or not
+       if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK))
+               bWPA2 = TRUE;
+
+    // Init Packet and Fill header
+    pMsg->ProVer = EAPOL_VER;
+    pMsg->ProType = EAPOLKey;
+
+       // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field
+       pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG;
+
+       // Fill in EAPoL descriptor
+       if (bWPA2)
+               pMsg->KeyDesc.Type = WPA2_KEY_DESC;
+       else
+               pMsg->KeyDesc.Type = WPA1_KEY_DESC;
+
+       // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78
+       // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used.
+       pMsg->KeyDesc.KeyInfo.KeyDescVer =
+               (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
+
+       // Specify Key Type as Group(0) or Pairwise(1)
+       if (MsgType >= EAPOL_GROUP_MSG_1)
+               pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
+       else
+               pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
+
+       // Specify Key Index, only group_msg1_WPA1
+       if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
+               pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
+
+       if (MsgType == EAPOL_PAIR_MSG_3)
+               pMsg->KeyDesc.KeyInfo.Install = 1;
+
+       if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
+               pMsg->KeyDesc.KeyInfo.KeyAck = 1;
+
+       if (MsgType != EAPOL_PAIR_MSG_1)
+               pMsg->KeyDesc.KeyInfo.KeyMic = 1;
+
+       if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
+    {
+               pMsg->KeyDesc.KeyInfo.Secure = 1;
+    }
+
+       if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
+    {
+        pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
+    }
+
+       // key Information element has done.
+       *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo));
+
+       // Fill in Key Length
+#if 0
+       if (bWPA2)
+       {
+               // In WPA2 mode, the field indicates the length of pairwise key cipher,
+               // so only pairwise_msg_1 and pairwise_msg_3 need to fill.
+               if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3))
+                       pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY);
+       }
+       else if (!bWPA2)
+#endif
+       {
+               if (MsgType >= EAPOL_GROUP_MSG_1)
+               {
+                       // the length of group key cipher
+                       pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY);
+               }
+               else
+               {
+                       // the length of pairwise key cipher
+                       pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY);
+               }
+       }
+
+       // Fill in replay counter
+    NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // Fill Key Nonce field
+       // ANonce : pairwise_msg1 & pairwise_msg3
+       // SNonce : pairwise_msg2
+       // GNonce : group_msg1_wpa1
+       if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
+       NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE);
+
+       // Fill key IV - WPA2 as 0, WPA1 as random
+       if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
+       {
+               // Suggest IV be random number plus some number,
+               NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV);
+        pMsg->KeyDesc.KeyIv[15] += 2;
+       }
+
+    // Fill Key RSC field
+    // It contains the RSC for the GTK being installed.
+       if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
+       {
+        NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
+       }
+
+       // Clear Key MIC field for MIC calculation later
+    NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+
+       ConstructEapolKeyData(pAd,
+                                                 AuthMode,
+                                                 WepStatus,
+                                                 GroupKeyWepStatus,
+                                                 MsgType,
+                                                 DefaultKeyIdx,
+                                                 bWPA2,
+                                                 PTK,
+                                                 GTK,
+                                                 RSNIE,
+                                                 RSNIE_Len,
+                                                 pMsg);
+
+       // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.
+       if (MsgType != EAPOL_PAIR_MSG_1)
+       {
+               CalculateMIC(pAd, WepStatus, PTK, pMsg);
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
+       DBGPRINT(RT_DEBUG_TRACE, ("          Body length = %d \n", pMsg->Body_Len[1]));
+       DBGPRINT(RT_DEBUG_TRACE, ("          Key length  = %d \n", pMsg->KeyDesc.KeyLength[1]));
+
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Construct the Key Data field of EAPoL message
+
+       Arguments:
+               pAd                     Pointer to our adapter
+               Elem            Message body
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   ConstructEapolKeyData(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   AuthMode,
+       IN      UCHAR                   WepStatus,
+       IN      UCHAR                   GroupKeyWepStatus,
+       IN      UCHAR                   MsgType,
+       IN      UCHAR                   DefaultKeyIdx,
+       IN      BOOLEAN                 bWPA2Capable,
+       IN      UCHAR                   *PTK,
+       IN      UCHAR                   *GTK,
+       IN      UCHAR                   *RSNIE,
+       IN      UCHAR                   RSNIE_LEN,
+       OUT PEAPOL_PACKET   pMsg)
+{
+       UCHAR           *mpool, *Key_Data, *Rc4GTK;
+       UCHAR       ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)];
+       UCHAR           data_offset;
+
+
+       if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
+               return;
+
+       // allocate memory pool
+       os_alloc_mem(pAd, (PUCHAR *)&mpool, 1500);
+
+    if (mpool == NULL)
+               return;
+
+       /* Rc4GTK Len = 512 */
+       Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4);
+       /* Key_Data Len = 512 */
+       Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4);
+
+       NdisZeroMemory(Key_Data, 512);
+       pMsg->KeyDesc.KeyDataLen[1] = 0;
+       data_offset = 0;
+
+       // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3
+       if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3)))
+       {
+               if (bWPA2Capable)
+                       Key_Data[data_offset + 0] = IE_WPA2;
+               else
+                       Key_Data[data_offset + 0] = IE_WPA;
+
+        Key_Data[data_offset + 1] = RSNIE_LEN;
+               NdisMoveMemory(&Key_Data[data_offset + 2], RSNIE, RSNIE_LEN);
+               data_offset += (2 + RSNIE_LEN);
+       }
+
+       // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2
+       if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
+       {
+               // Key Data Encapsulation (KDE) format - 802.11i-2004  Figure-43w and Table-20h
+        Key_Data[data_offset + 0] = 0xDD;
+
+               if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
+               {
+                       Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField)
+               }
+               else
+               {
+                       Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField)
+               }
+
+        Key_Data[data_offset + 2] = 0x00;
+        Key_Data[data_offset + 3] = 0x0F;
+        Key_Data[data_offset + 4] = 0xAC;
+        Key_Data[data_offset + 5] = 0x01;
+
+               // GTK KDE format - 802.11i-2004  Figure-43x
+        Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
+        Key_Data[data_offset + 7] = 0x00;      // Reserved Byte
+
+               data_offset += 8;
+       }
+
+
+       // Encapsulate GTK and encrypt the key-data field with KEK.
+       // Only for pairwise_msg3_WPA2 and group_msg1
+       if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
+       {
+               // Fill in GTK
+               if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
+               {
+                       NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY);
+                       data_offset += LEN_AES_KEY;
+               }
+               else
+               {
+                       NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH);
+                       data_offset += TKIP_GTK_LENGTH;
+               }
+
+               // Still dont know why, but if not append will occur "GTK not include in MSG3"
+               // Patch for compatibility between zero config and funk
+               if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
+               {
+                       if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
+                       {
+                               Key_Data[data_offset + 0] = 0xDD;
+                               Key_Data[data_offset + 1] = 0;
+                               data_offset += 2;
+                       }
+                       else
+                       {
+                               Key_Data[data_offset + 0] = 0xDD;
+                               Key_Data[data_offset + 1] = 0;
+                               Key_Data[data_offset + 2] = 0;
+                               Key_Data[data_offset + 3] = 0;
+                               Key_Data[data_offset + 4] = 0;
+                               Key_Data[data_offset + 5] = 0;
+                               data_offset += 6;
+                       }
+               }
+
+               // Encrypt the data material in key data field
+               if (WepStatus == Ndis802_11Encryption3Enabled)
+               {
+                       AES_GTK_KEY_WRAP(&PTK[16], Key_Data, data_offset, Rc4GTK);
+            // AES wrap function will grow 8 bytes in length
+            data_offset += 8;
+               }
+               else
+               {
+                       // PREPARE Encrypted  "Key DATA" field.  (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV)
+                       // put TxTsc in Key RSC field
+                       pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32;   //Init crc32.
+
+                       // ekey is the contanetion of IV-field, and PTK[16]->PTK[31]
+                       NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV);
+                       NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &PTK[16], LEN_EAP_EK);
+                       ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey));  //INIT SBOX, KEYLEN+3(IV)
+                       pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset);
+                       WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset);
+               }
+
+               NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
+       }
+       else
+       {
+               NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
+       }
+
+       // set key data length field and total length
+       pMsg->KeyDesc.KeyDataLen[1] = data_offset;
+    pMsg->Body_Len[1] += data_offset;
+
+       os_free_mem(pAd, mpool);
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Calcaulate MIC. It is used during 4-ways handsharking.
+
+       Arguments:
+               pAd                             -       pointer to our pAdapter context
+       PeerWepStatus   -       indicate the encryption type
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID   CalculateMIC(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   PeerWepStatus,
+       IN      UCHAR                   *PTK,
+       OUT PEAPOL_PACKET   pMsg)
+{
+    UCHAR   *OutBuffer;
+       ULONG   FrameLen = 0;
+       UCHAR   mic[LEN_KEY_DESC_MIC];
+       UCHAR   digest[80];
+
+       // allocate memory for MIC calculation
+       os_alloc_mem(pAd, (PUCHAR *)&OutBuffer, 512);
+
+    if (OutBuffer == NULL)
+    {
+               DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
+               return;
+    }
+
+       // make a frame for calculating MIC.
+    MakeOutgoingFrame(OutBuffer,               &FrameLen,
+                      pMsg->Body_Len[1] + 4,   pMsg,
+                      END_OF_ARGS);
+
+       NdisZeroMemory(mic, sizeof(mic));
+
+       // Calculate MIC
+    if (PeerWepStatus == Ndis802_11Encryption3Enabled)
+       {
+               HMAC_SHA1(OutBuffer,  FrameLen, PTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
+       }
+       else
+       {
+               hmac_md5(PTK,  LEN_EAP_MICK, OutBuffer, FrameLen, mic);
+       }
+
+       // store the calculated MIC
+       NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
+
+       os_free_mem(pAd, OutBuffer);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Some received frames can't decrypt by Asic, so decrypt them by software.
+
+       Arguments:
+               pAd                             -       pointer to our pAdapter context
+       PeerWepStatus   -       indicate the encryption type
+
+       Return Value:
+               NDIS_STATUS_SUCCESS             -       decryption successful
+               NDIS_STATUS_FAILURE             -       decryption failure
+
+       ========================================================================
+*/
+NDIS_STATUS    RTMPSoftDecryptBroadCastData(
+       IN      PRTMP_ADAPTER                                   pAd,
+       IN      RX_BLK                                                  *pRxBlk,
+       IN  NDIS_802_11_ENCRYPTION_STATUS       GroupCipher,
+       IN  PCIPHER_KEY                                         pShard_key)
+{
+       PRXWI_STRUC                     pRxWI = pRxBlk->pRxWI;
+
+
+
+       // handle WEP decryption
+       if (GroupCipher == Ndis802_11Encryption1Enabled)
+    {
+               if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key))
+               {
+
+                       //Minus IV[4] & ICV[4]
+                       pRxWI->MPDUtotalByteCount -= 8;
+               }
+               else
+               {
+                       DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n"));
+                       // give up this frame
+                       return NDIS_STATUS_FAILURE;
+               }
+       }
+       // handle TKIP decryption
+       else if (GroupCipher == Ndis802_11Encryption2Enabled)
+       {
+               if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key))
+               {
+
+                       //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV
+                       pRxWI->MPDUtotalByteCount -= 20;
+               }
+        else
+               {
+                       DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
+                       // give up this frame
+                       return NDIS_STATUS_FAILURE;
+        }
+       }
+       // handle AES decryption
+       else if (GroupCipher == Ndis802_11Encryption3Enabled)
+       {
+               if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key))
+               {
+
+                       //8 bytes MIC, 8 bytes IV/EIV (CCMP Header)
+                       pRxWI->MPDUtotalByteCount -= 16;
+               }
+               else
+               {
+                       DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n"));
+                       // give up this frame
+                       return NDIS_STATUS_FAILURE;
+               }
+       }
+       else
+       {
+               // give up this frame
+               return NDIS_STATUS_FAILURE;
+       }
+
+       return NDIS_STATUS_SUCCESS;
+
+}
+
diff --git a/drivers/staging/rt2870/common/dfs.c b/drivers/staging/rt2870/common/dfs.c
new file mode 100644 (file)
index 0000000..23cf151
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    ap_dfs.c
+
+    Abstract:
+    Support DFS function.
+
+    Revision History:
+    Who       When            What
+    --------  ----------      ----------------------------------------------
+    Fonchi    03-12-2007      created
+*/
+
+#include "../rt_config.h"
+
+typedef struct _RADAR_DURATION_TABLE
+{
+       ULONG RDDurRegion;
+       ULONG RadarSignalDuration;
+       ULONG Tolerance;
+} RADAR_DURATION_TABLE, *PRADAR_DURATION_TABLE;
+
+
+static UCHAR RdIdleTimeTable[MAX_RD_REGION][4] =
+{
+       {9, 250, 250, 250},             // CE
+       {4, 250, 250, 250},             // FCC
+       {4, 250, 250, 250},             // JAP
+       {15, 250, 250, 250},    // JAP_W53
+       {4, 250, 250, 250}              // JAP_W56
+};
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Bbp Radar detection routine
+
+       Arguments:
+               pAd     Pointer to our adapter
+
+       Return Value:
+
+       ========================================================================
+*/
+VOID BbpRadarDetectionStart(
+       IN PRTMP_ADAPTER pAd)
+{
+       UINT8 RadarPeriod;
+
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 114, 0x02);
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 121, 0x20);
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 122, 0x00);
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 123, 0x08/*0x80*/);
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 124, 0x28);
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 125, 0xff);
+
+#if 0
+       // toggle Rx enable bit for radar detection.
+       // it's Andy's recommand.
+       {
+               UINT32 Value;
+       RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+       Value |= (0x1 << 3);
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+       Value &= ~(0x1 << 3);
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+       }
+#endif
+       RadarPeriod = ((UINT)RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + (UINT)pAd->CommonCfg.RadarDetect.DfsSessionTime) < 250 ?
+                       (RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + pAd->CommonCfg.RadarDetect.DfsSessionTime) : 250;
+
+       RTMP_IO_WRITE8(pAd, 0x7020, 0x1d);
+       RTMP_IO_WRITE8(pAd, 0x7021, 0x40);
+
+       RadarDetectionStart(pAd, 0, RadarPeriod);
+       return;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Bbp Radar detection routine
+
+       Arguments:
+               pAd     Pointer to our adapter
+
+       Return Value:
+
+       ========================================================================
+*/
+VOID BbpRadarDetectionStop(
+       IN PRTMP_ADAPTER pAd)
+{
+       RTMP_IO_WRITE8(pAd, 0x7020, 0x1d);
+       RTMP_IO_WRITE8(pAd, 0x7021, 0x60);
+
+       RadarDetectionStop(pAd);
+       return;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Radar detection routine
+
+       Arguments:
+               pAd     Pointer to our adapter
+
+       Return Value:
+
+       ========================================================================
+*/
+VOID RadarDetectionStart(
+       IN PRTMP_ADAPTER pAd,
+       IN BOOLEAN CTSProtect,
+       IN UINT8 CTSPeriod)
+{
+       UINT8 DfsActiveTime = (pAd->CommonCfg.RadarDetect.DfsSessionTime & 0x1f);
+       UINT8 CtsProtect = (CTSProtect == 1) ? 0x02 : 0x01; // CTS protect.
+
+       if (CTSProtect != 0)
+       {
+               switch(pAd->CommonCfg.RadarDetect.RDDurRegion)
+               {
+               case FCC:
+               case JAP_W56:
+                       CtsProtect = 0x03;
+                       break;
+
+               case CE:
+               case JAP_W53:
+               default:
+                       CtsProtect = 0x02;
+                       break;
+               }
+       }
+       else
+               CtsProtect = 0x01;
+
+
+       // send start-RD with CTS protection command to MCU
+       // highbyte [7]         reserve
+       // highbyte [6:5]       0x: stop Carrier/Radar detection
+       // highbyte [10]:       Start Carrier/Radar detection without CTS protection, 11: Start Carrier/Radar detection with CTS protection
+       // highbyte [4:0]       Radar/carrier detection duration. In 1ms.
+
+       // lowbyte [7:0]        Radar/carrier detection period, in 1ms.
+       AsicSendCommandToMcu(pAd, 0x60, 0xff, CTSPeriod, DfsActiveTime | (CtsProtect << 5));
+       //AsicSendCommandToMcu(pAd, 0x63, 0xff, 10, 0);
+
+       return;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Radar detection routine
+
+       Arguments:
+               pAd     Pointer to our adapter
+
+       Return Value:
+               TRUE    Found radar signal
+               FALSE   Not found radar signal
+
+       ========================================================================
+*/
+VOID RadarDetectionStop(
+       IN PRTMP_ADAPTER        pAd)
+{
+       DBGPRINT(RT_DEBUG_TRACE,("RadarDetectionStop.\n"));
+       AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x00, 0x00);      // send start-RD with CTS protection command to MCU
+
+       return;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Radar channel check routine
+
+       Arguments:
+               pAd     Pointer to our adapter
+
+       Return Value:
+               TRUE    need to do radar detect
+               FALSE   need not to do radar detect
+
+       ========================================================================
+*/
+BOOLEAN RadarChannelCheck(
+       IN PRTMP_ADAPTER        pAd,
+       IN UCHAR                        Ch)
+{
+#if 1
+       INT             i;
+       BOOLEAN result = FALSE;
+
+       for (i=0; i<pAd->ChannelListNum; i++)
+       {
+               if (Ch == pAd->ChannelList[i].Channel)
+               {
+                       result = pAd->ChannelList[i].DfsReq;
+                       break;
+               }
+       }
+
+       return result;
+#else
+       INT             i;
+       UCHAR   Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
+
+       for (i=0; i<15; i++)
+       {
+               if (Ch == Channel[i])
+               {
+                       break;
+               }
+       }
+
+       if (i != 15)
+               return TRUE;
+       else
+               return FALSE;
+#endif
+}
+
+ULONG JapRadarType(
+       IN PRTMP_ADAPTER pAd)
+{
+       ULONG           i;
+       const UCHAR     Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
+
+       if (pAd->CommonCfg.RadarDetect.RDDurRegion != JAP)
+       {
+               return pAd->CommonCfg.RadarDetect.RDDurRegion;
+       }
+
+       for (i=0; i<15; i++)
+       {
+               if (pAd->CommonCfg.Channel == Channel[i])
+               {
+                       break;
+               }
+       }
+
+       if (i < 4)
+               return JAP_W53;
+       else if (i < 15)
+               return JAP_W56;
+       else
+               return JAP; // W52
+
+}
+
+ULONG RTMPBbpReadRadarDuration(
+       IN PRTMP_ADAPTER        pAd)
+{
+       UINT8 byteValue = 0;
+       ULONG result;
+
+       BBP_IO_READ8_BY_REG_ID(pAd, BBP_R115, &byteValue);
+
+       result = 0;
+       switch (byteValue)
+       {
+       case 1: // radar signal detected by pulse mode.
+       case 2: // radar signal detected by width mode.
+               result = RTMPReadRadarDuration(pAd);
+               break;
+
+       case 0: // No radar signal.
+       default:
+
+               result = 0;
+               break;
+       }
+
+       return result;
+}
+
+ULONG RTMPReadRadarDuration(
+       IN PRTMP_ADAPTER        pAd)
+{
+       ULONG result = 0;
+
+#ifdef DFS_SUPPORT
+       UINT8 duration1 = 0, duration2 = 0, duration3 = 0;
+
+       BBP_IO_READ8_BY_REG_ID(pAd, BBP_R116, &duration1);
+       BBP_IO_READ8_BY_REG_ID(pAd, BBP_R117, &duration2);
+       BBP_IO_READ8_BY_REG_ID(pAd, BBP_R118, &duration3);
+       result = (duration1 << 16) + (duration2 << 8) + duration3;
+#endif // DFS_SUPPORT //
+
+       return result;
+
+}
+
+VOID RTMPCleanRadarDuration(
+       IN PRTMP_ADAPTER        pAd)
+{
+       return;
+}
+
+/*
+    ========================================================================
+    Routine Description:
+        Radar wave detection. The API should be invoke each second.
+
+    Arguments:
+        pAd         - Adapter pointer
+
+    Return Value:
+        None
+
+    ========================================================================
+*/
+VOID ApRadarDetectPeriodic(
+       IN PRTMP_ADAPTER pAd)
+{
+       INT     i;
+
+       pAd->CommonCfg.RadarDetect.InServiceMonitorCount++;
+
+       for (i=0; i<pAd->ChannelListNum; i++)
+       {
+               if (pAd->ChannelList[i].RemainingTimeForUse > 0)
+               {
+                       pAd->ChannelList[i].RemainingTimeForUse --;
+                       if ((pAd->Mlme.PeriodicRound%5) == 0)
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n", pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse));
+                       }
+               }
+       }
+
+       //radar detect
+       if ((pAd->CommonCfg.Channel > 14)
+               && (pAd->CommonCfg.bIEEE80211H == 1)
+               && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
+       {
+               RadarDetectPeriodic(pAd);
+       }
+
+       return;
+}
+
+// Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt()
+// Before switch channel, driver needs doing channel switch announcement.
+VOID RadarDetectPeriodic(
+       IN PRTMP_ADAPTER        pAd)
+{
+       // need to check channel availability, after switch channel
+       if (pAd->CommonCfg.RadarDetect.RDMode != RD_SILENCE_MODE)
+                       return;
+
+       // channel availability check time is 60sec, use 65 for assurance
+       if (pAd->CommonCfg.RadarDetect.RDCount++ > pAd->CommonCfg.RadarDetect.ChMovingTime)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n"));
+                       BbpRadarDetectionStop(pAd);
+               AsicEnableBssSync(pAd);
+               pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE;
+
+
+               return;
+       }
+
+       return;
+}
+
+
+/*
+    ==========================================================================
+    Description:
+               change channel moving time for DFS testing.
+
+       Arguments:
+           pAdapter                    Pointer to our adapter
+           wrq                         Pointer to the ioctl argument
+
+    Return Value:
+        None
+
+    Note:
+        Usage:
+               1.) iwpriv ra0 set ChMovTime=[value]
+    ==========================================================================
+*/
+INT Set_ChMovingTime_Proc(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR arg)
+{
+       UINT8 Value;
+
+       Value = simple_strtol(arg, 0, 10);
+
+       pAd->CommonCfg.RadarDetect.ChMovingTime = Value;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __FUNCTION__,
+               pAd->CommonCfg.RadarDetect.ChMovingTime));
+
+       return TRUE;
+}
+
+INT Set_LongPulseRadarTh_Proc(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR arg)
+{
+       UINT8 Value;
+
+       Value = simple_strtol(arg, 0, 10) > 10 ? 10 : simple_strtol(arg, 0, 10);
+
+       pAd->CommonCfg.RadarDetect.LongPulseRadarTh = Value;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __FUNCTION__,
+               pAd->CommonCfg.RadarDetect.LongPulseRadarTh));
+
+       return TRUE;
+}
+
+
diff --git a/drivers/staging/rt2870/common/eeprom.c b/drivers/staging/rt2870/common/eeprom.c
new file mode 100644 (file)
index 0000000..33f16ed
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       eeprom.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Name            Date                    Modification logs
+*/
+#include "../rt_config.h"
+
+#if 0
+#define EEPROM_SIZE                                                            0x200
+#define NVRAM_OFFSET                   0x30000
+#define RF_OFFSET                              0x40000
+
+static UCHAR init_flag = 0;
+static PUCHAR nv_ee_start = 0;
+
+static UCHAR EeBuffer[EEPROM_SIZE];
+#endif
+// IRQL = PASSIVE_LEVEL
+VOID RaiseClock(
+    IN PRTMP_ADAPTER   pAd,
+    IN  UINT32 *x)
+{
+    *x = *x | EESK;
+    RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
+    RTMPusecDelay(1);                          // Max frequency = 1MHz in Spec. definition
+}
+
+// IRQL = PASSIVE_LEVEL
+VOID LowerClock(
+    IN PRTMP_ADAPTER   pAd,
+    IN  UINT32 *x)
+{
+    *x = *x & ~EESK;
+    RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
+    RTMPusecDelay(1);
+}
+
+// IRQL = PASSIVE_LEVEL
+USHORT ShiftInBits(
+    IN PRTMP_ADAPTER   pAd)
+{
+    UINT32             x,i;
+       USHORT      data=0;
+
+    RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+    x &= ~( EEDO | EEDI);
+
+    for(i=0; i<16; i++)
+    {
+        data = data << 1;
+        RaiseClock(pAd, &x);
+
+        RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+        x &= ~(EEDI);
+        if(x & EEDO)
+            data |= 1;
+
+        LowerClock(pAd, &x);
+    }
+
+    return data;
+}
+
+// IRQL = PASSIVE_LEVEL
+VOID ShiftOutBits(
+    IN PRTMP_ADAPTER   pAd,
+    IN  USHORT data,
+    IN  USHORT count)
+{
+    UINT32       x,mask;
+
+    mask = 0x01 << (count - 1);
+    RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+    x &= ~(EEDO | EEDI);
+
+    do
+    {
+        x &= ~EEDI;
+        if(data & mask)                x |= EEDI;
+
+        RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+        RaiseClock(pAd, &x);
+        LowerClock(pAd, &x);
+
+        mask = mask >> 1;
+    } while(mask);
+
+    x &= ~EEDI;
+    RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+}
+
+// IRQL = PASSIVE_LEVEL
+VOID EEpromCleanup(
+    IN PRTMP_ADAPTER   pAd)
+{
+    UINT32 x;
+
+    RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+    x &= ~(EECS | EEDI);
+    RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+    RaiseClock(pAd, &x);
+    LowerClock(pAd, &x);
+}
+
+VOID EWEN(
+       IN      PRTMP_ADAPTER   pAd)
+{
+    UINT32     x;
+
+    // reset bits and set EECS
+    RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+    x &= ~(EEDI | EEDO | EESK);
+    x |= EECS;
+    RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+       // kick a pulse
+       RaiseClock(pAd, &x);
+       LowerClock(pAd, &x);
+
+    // output the read_opcode and six pulse in that order
+    ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5);
+    ShiftOutBits(pAd, 0, 6);
+
+    EEpromCleanup(pAd);
+}
+
+VOID EWDS(
+       IN      PRTMP_ADAPTER   pAd)
+{
+    UINT32     x;
+
+    // reset bits and set EECS
+    RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+    x &= ~(EEDI | EEDO | EESK);
+    x |= EECS;
+    RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+       // kick a pulse
+       RaiseClock(pAd, &x);
+       LowerClock(pAd, &x);
+
+    // output the read_opcode and six pulse in that order
+    ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5);
+    ShiftOutBits(pAd, 0, 6);
+
+    EEpromCleanup(pAd);
+}
+
+// IRQL = PASSIVE_LEVEL
+USHORT RTMP_EEPROM_READ16(
+    IN PRTMP_ADAPTER   pAd,
+    IN  USHORT Offset)
+{
+    UINT32             x;
+    USHORT             data;
+
+    Offset /= 2;
+    // reset bits and set EECS
+    RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+    x &= ~(EEDI | EEDO | EESK);
+    x |= EECS;
+    RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+       // kick a pulse
+       RaiseClock(pAd, &x);
+       LowerClock(pAd, &x);
+
+    // output the read_opcode and register number in that order
+    ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3);
+    ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
+
+    // Now read the data (16 bits) in from the selected EEPROM word
+    data = ShiftInBits(pAd);
+
+    EEpromCleanup(pAd);
+
+    return data;
+}      //ReadEEprom
+
+VOID RTMP_EEPROM_WRITE16(
+    IN PRTMP_ADAPTER   pAd,
+    IN  USHORT Offset,
+    IN  USHORT Data)
+{
+    UINT32 x;
+
+       Offset /= 2;
+
+       EWEN(pAd);
+
+    // reset bits and set EECS
+    RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+    x &= ~(EEDI | EEDO | EESK);
+    x |= EECS;
+    RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+       // kick a pulse
+       RaiseClock(pAd, &x);
+       LowerClock(pAd, &x);
+
+    // output the read_opcode ,register number and data in that order
+    ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3);
+    ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
+       ShiftOutBits(pAd, Data, 16);            // 16-bit access
+
+    // read DO status
+    RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+       EEpromCleanup(pAd);
+
+       RTMPusecDelay(10000);   //delay for twp(MAX)=10ms
+
+       EWDS(pAd);
+
+    EEpromCleanup(pAd);
+}
+
diff --git a/drivers/staging/rt2870/common/firmware.h b/drivers/staging/rt2870/common/firmware.h
new file mode 100644 (file)
index 0000000..a406698
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+ Copyright (c) 2007, Ralink Technology Corporation
+ All rights reserved.
+
+ Redistribution.  Redistribution and use in binary form, without
+ modification, are permitted provided that the following conditions are
+ met:
+
+       * Redistributions must reproduce the above copyright notice and the
+       following disclaimer in the documentation and/or other materials
+       provided with the distribution.
+       * Neither the name of Ralink Technology Corporation nor the names of its
+       suppliers may be used to endorse or promote products derived from this
+       software without specific prior written permission.
+       * No reverse engineering, decompilation, or disassembly of this software
+       is permitted.
+
+ Limited patent license. Ralink Technology Corporation grants a world-wide,
+ royalty-free, non-exclusive license under patents it now or hereafter
+ owns or controls to make, have made, use, import, offer to sell and
+ sell ("Utilize") this software, but solely to the extent that any
+ such patent is necessary to Utilize the software alone, or in
+ combination with an operating system licensed under an approved Open
+ Source license as listed by the Open Source Initiative at
+ http://opensource.org/licenses.  The patent license shall not apply to
+ any other combinations which include this software.  No hardware per
+ se is licensed hereunder.
+
+ DISCLAIMER.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
+*/
+/* AUTO GEN PLEASE DO NOT MODIFY IT */
+/* AUTO GEN PLEASE DO NOT MODIFY IT */
+
+
+UCHAR FirmwareImage [] = {
+0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x12, 0x79, 0x02,
+0x12, 0x7a, 0x02, 0x12, 0x99, 0x02, 0x12, 0x9e, 0x12, 0x12, 0x9a, 0x22, 0x02, 0x16, 0x36, 0x02,
+0x17, 0x0c, 0x02, 0x13, 0x89, 0x02, 0x12, 0x9f, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x17,
+0xae, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40,
+0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4,
+0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4,
+0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01,
+0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xc8, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02,
+0x12, 0x6e, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0x9d, 0x10,
+0xb7, 0x31, 0x10, 0xe2, 0x50, 0x11, 0x08, 0x51, 0x11, 0x13, 0x52, 0x11, 0x13, 0x53, 0x11, 0x13,
+0x54, 0x11, 0x54, 0x55, 0x11, 0x79, 0x70, 0x11, 0xa4, 0x71, 0x11, 0xd2, 0x72, 0x12, 0x25, 0x73,
+0x12, 0x46, 0x80, 0x00, 0x00, 0x12, 0x6e, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf,
+0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
+0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x6e, 0x02, 0x12, 0x67, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x02,
+0x12, 0x6e, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60, 0x03, 0x02, 0x12, 0x6e, 0x90,
+0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60, 0x03, 0x02, 0x12, 0x6e, 0x75,
+0x4e, 0x03, 0x75, 0x4f, 0x20, 0x02, 0x12, 0x6e, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x47,
+0x02, 0x12, 0x6e, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10,
+0xe0, 0xff, 0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74,
+0x48, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04,
+0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12,
+0x6e, 0x02, 0x12, 0x67, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x05,
+0xe5, 0x47, 0xb4, 0x09, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe4, 0xfd, 0xaf,
+0x56, 0x12, 0x0b, 0x91, 0xd2, 0x04, 0x02, 0x12, 0x6e, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70,
+0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04,
+0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12,
+0x6e, 0x02, 0x12, 0x67, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf5,
+0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74,
+0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x6e, 0x02,
+0x12, 0x67, 0x90, 0x10, 0x02, 0xe0, 0xb4, 0x70, 0x1e, 0xa3, 0xe0, 0xb4, 0x30, 0x19, 0x90, 0x05,
+0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd, 0x90, 0x05, 0x05, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x04, 0xf0,
+0xed, 0x54, 0xfe, 0x90, 0x05, 0x08, 0xf0, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x3a, 0xff, 0xad,
+0x57, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13,
+0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x70, 0x40,
+0xe5, 0x3a, 0xf0, 0x80, 0x49, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf,
+0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
+0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05,
+0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70,
+0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x70,
+0x42, 0xe5, 0x3a, 0xf0, 0xa3, 0x74, 0xab, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60,
+0x09, 0xb2, 0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04, 0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08,
+0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, 0xc2, 0x42, 0xd3, 0x22, 0x22, 0xc2,
+0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x0a, 0x9d, 0x12, 0xc1, 0x00, 0x13, 0x54, 0x04, 0x13, 0x50,
+0x08, 0x13, 0x2b, 0x10, 0x12, 0xd5, 0x20, 0x12, 0xf5, 0x60, 0x13, 0x06, 0xa0, 0x00, 0x00, 0x13,
+0x56, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03,
+0x02, 0x13, 0x56, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54,
+0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x66,
+0x53, 0x43, 0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47,
+0x64, 0x06, 0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4,
+0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70,
+0x35, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04, 0x06,
+0x53, 0x5e, 0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75, 0x42,
+0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80, 0x06,
+0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff, 0xe5,
+0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3, 0xe5,
+0x4a, 0xf0, 0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3, 0xe5,
+0x42, 0xf0, 0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0, 0x70,
+0x03, 0x12, 0x16, 0x16, 0x12, 0x13, 0x9e, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf,
+0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f,
+0x24, 0xff, 0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, 0x1e,
+0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, 0x5f,
+0x20, 0xe5, 0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, 0x25,
+0x70, 0x05, 0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5,
+0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47,
+0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25, 0x70,
+0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02, 0x15,
+0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, 0xe5,
+0x3a, 0x64, 0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0x90, 0x70,
+0x46, 0xe5, 0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b,
+0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02,
+0xb2, 0x6c, 0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68,
+0x80, 0x26, 0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04,
+0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01,
+0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2,
+0x6a, 0x80, 0x26, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0,
+0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e,
+0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04,
+0xa2, 0x6c, 0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20,
+0xe1, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04,
+0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x71, 0x92, 0x70, 0x90, 0x10,
+0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4c, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfe,
+0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe, 0x60, 0x23, 0x24, 0x03, 0x60,
+0x03, 0x02, 0x16, 0x05, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0f, 0x80, 0x07, 0x90, 0x02, 0x28,
+0xe0, 0x20, 0x47, 0x06, 0x54, 0xfe, 0xf0, 0x02, 0x16, 0x05, 0x44, 0x01, 0xf0, 0x02, 0x16, 0x05,
+0xe5, 0x46, 0x30, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x02, 0x28, 0xe0, 0x54,
+0xfe, 0x4f, 0xf0, 0x02, 0x16, 0x05, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x0f, 0xe5, 0x47, 0x64, 0x08,
+0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02, 0x16, 0x05, 0xe4, 0xf5, 0x27, 0x90, 0x02,
+0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x2e, 0x14, 0x60, 0x36,
+0x24, 0xfc, 0x60, 0x5f, 0x24, 0xf9, 0x60, 0x1f, 0x24, 0x0e, 0x70, 0x69, 0xe5, 0x46, 0x13, 0x13,
+0x54, 0x3f, 0x75, 0xf0, 0x01, 0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e,
+0x00, 0xef, 0x6e, 0x24, 0xff, 0x80, 0x45, 0xa2, 0x47, 0x80, 0x41, 0xe5, 0x46, 0x30, 0xe2, 0x03,
+0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30,
+0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, 0x47, 0x04, 0x7d,
+0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2, 0x47, 0xb3, 0x92,
+0x39, 0x80, 0x19, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0xa2, 0x47,
+0xb3, 0x92, 0x38, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90, 0x02, 0x28, 0xe0,
+0x54, 0xfc, 0x45, 0x27, 0xf0, 0x90, 0x70, 0x9c, 0xe5, 0x3a, 0xf0, 0xa3, 0xe5, 0x47, 0xf0, 0x90,
+0x70, 0x41, 0xe5, 0x3a, 0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45,
+0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59,
+0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, 0x62, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x46,
+0x14, 0x60, 0x62, 0x24, 0x02, 0x60, 0x03, 0x02, 0x16, 0xf0, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x90,
+0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0, 0x20, 0xe7, 0x22, 0x90, 0x04, 0x34, 0xe0, 0xb4,
+0x02, 0x1b, 0xa3, 0xe0, 0xb4, 0x02, 0x16, 0xa3, 0xe0, 0xb4, 0x02, 0x11, 0x7f, 0x20, 0x12, 0x16,
+0x2c, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x80, 0x73, 0xe5, 0x50, 0x70,
+0x05, 0x75, 0x62, 0x03, 0x80, 0x6a, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x11, 0x7f, 0x20,
+0x12, 0x16, 0x2c, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02, 0x80, 0x51, 0xe5,
+0x50, 0x70, 0x02, 0x80, 0x46, 0x90, 0x02, 0xa3, 0xe0, 0x20, 0xe6, 0x3b, 0x90, 0x04, 0x37, 0xe0,
+0x64, 0x22, 0x70, 0x33, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96, 0xf0, 0x90, 0x12,
+0x04, 0x74, 0x0a, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xf0, 0xf0,
+0xa3, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54, 0xf9, 0xf0, 0x75, 0x62, 0x01, 0x75,
+0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x62, 0x03, 0xf5, 0x51,
+0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xad, 0x62, 0xaf, 0x40, 0x12,
+0x17, 0x7a, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01,
+0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40,
+0x12, 0x17, 0x7a, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70, 0x4c, 0x75, 0x52, 0x01, 0x75, 0x55,
+0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44, 0x0f, 0xf0, 0xa3,
+0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, 0x03, 0xf0, 0x90,
+0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x0c, 0xf0, 0xe4, 0xf5, 0x52,
+0xf5, 0x55, 0x30, 0x02, 0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41, 0x12, 0x17, 0x7a, 0x80, 0x02,
+0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe,
+0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14,
+0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4,
+0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, 0x22, 0x90, 0x70,
+0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90,
+0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90,
+0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0,
+0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0,
+0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01, 0xf0, 0xc2, 0x05,
+0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x69, 0x77,
+0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x12, 0x25, 0x02,
+0x12, 0x26, 0x02, 0x12, 0x39, 0x02, 0x12, 0x3e, 0x12, 0x12, 0x3a, 0x22, 0x02, 0x15, 0x72, 0x02,
+0x16, 0x48, 0x02, 0x13, 0x29, 0x02, 0x12, 0x3f, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x16,
+0xea, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40,
+0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4,
+0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4,
+0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01,
+0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xdd, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02,
+0x12, 0x1a, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0xb6, 0x10,
+0xb4, 0x31, 0x10, 0xdf, 0x50, 0x11, 0x05, 0x51, 0x11, 0x10, 0x52, 0x11, 0x10, 0x53, 0x11, 0x10,
+0x54, 0x11, 0x51, 0x55, 0x11, 0x70, 0x70, 0x11, 0x9a, 0x71, 0x11, 0xc4, 0x72, 0x11, 0xf2, 0x80,
+0x00, 0x00, 0x12, 0x1a, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf, 0x56, 0x12, 0x0b,
+0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70,
+0x03, 0x02, 0x12, 0x1a, 0x02, 0x12, 0x13, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x02, 0x12, 0x1a, 0x90,
+0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60, 0x03, 0x02, 0x12, 0x1a, 0x90, 0x70, 0x11, 0xe0,
+0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60, 0x03, 0x02, 0x12, 0x1a, 0x75, 0x4e, 0x03, 0x75,
+0x4f, 0x20, 0x02, 0x12, 0x1a, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x47, 0x02, 0x12, 0x1a,
+0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, 0xff, 0x74,
+0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, 0x25, 0x57,
+0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80,
+0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x1a, 0x02, 0x12,
+0x13, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x08, 0x08, 0x90, 0x70, 0x11, 0xe0,
+0x54, 0x07, 0xf5, 0x3a, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0xd2, 0x04, 0x02, 0x12, 0x1a,
+0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd,
+0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0,
+0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x1a, 0x80, 0x79, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90,
+0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12,
+0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4,
+0x60, 0x58, 0x80, 0x4f, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x3a, 0xff, 0xad, 0x57, 0xaf, 0x56,
+0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56,
+0xf4, 0x60, 0x07, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x70, 0x40, 0xe5, 0x3a, 0xf0,
+0x80, 0x28, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56,
+0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56,
+0xf4, 0x60, 0x07, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x70, 0x42, 0xe5, 0x3a, 0xf0,
+0xa3, 0x74, 0xab, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x70, 0x0e, 0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08,
+0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, 0xc2, 0x42, 0xd3, 0x22, 0x22, 0xc2,
+0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x0a, 0xb6, 0x12, 0x61, 0x00, 0x12, 0xf4, 0x04, 0x12, 0xf0,
+0x08, 0x12, 0xcb, 0x10, 0x12, 0x75, 0x20, 0x12, 0x95, 0x60, 0x12, 0xa6, 0xa0, 0x00, 0x00, 0x12,
+0xf6, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03,
+0x02, 0x12, 0xf6, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54,
+0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x66,
+0x53, 0x43, 0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47,
+0x64, 0x06, 0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4,
+0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70,
+0x35, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04, 0x06,
+0x53, 0x5e, 0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75, 0x42,
+0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80, 0x06,
+0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff, 0xe5,
+0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3, 0xe5,
+0x4a, 0xf0, 0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3, 0xe5,
+0x42, 0xf0, 0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0, 0x70,
+0x03, 0x12, 0x15, 0x52, 0x12, 0x13, 0x3e, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf,
+0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f,
+0x24, 0xff, 0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, 0x1e,
+0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, 0x5f,
+0x20, 0xe5, 0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, 0x25,
+0x70, 0x05, 0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5,
+0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47,
+0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25, 0x70,
+0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02, 0x15,
+0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x90, 0x70, 0x46, 0xe5, 0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5, 0x5e,
+0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20,
+0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0, 0x75,
+0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x15, 0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe3,
+0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x73,
+0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x15, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe3,
+0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x75,
+0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80, 0x15, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe3,
+0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x71,
+0x92, 0x70, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4c, 0x90, 0x02,
+0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe, 0x60,
+0x23, 0x24, 0x03, 0x60, 0x03, 0x02, 0x15, 0x41, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0f, 0x80,
+0x07, 0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x06, 0x54, 0xfe, 0xf0, 0x02, 0x15, 0x41, 0x44, 0x01,
+0xf0, 0x02, 0x15, 0x41, 0xe5, 0x46, 0x30, 0xe3, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90,
+0x02, 0x28, 0xe0, 0x54, 0xfe, 0x4f, 0xf0, 0x02, 0x15, 0x41, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x09,
+0xe5, 0x47, 0x64, 0x08, 0x60, 0x03, 0x02, 0x15, 0x41, 0xe4, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0,
+0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x26, 0x14, 0x60, 0x2e, 0x14, 0x60, 0x36, 0x24, 0x03,
+0x70, 0x5f, 0xe5, 0x46, 0x13, 0x13, 0x13, 0x54, 0x1f, 0x75, 0xf0, 0x03, 0x84, 0xaf, 0xf0, 0x20,
+0x47, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff, 0x80, 0x02, 0xa2, 0x47,
+0x92, 0x39, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x3f, 0xe5, 0x46, 0x30, 0xe3, 0x03, 0xd3, 0x80,
+0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe3, 0x0d, 0x54, 0x70, 0xc3, 0x94, 0x60, 0x50, 0x06,
+0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, 0x47, 0x04, 0x7d, 0x01, 0x80,
+0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2, 0x47, 0xb3, 0x92, 0x39, 0x80,
+0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90, 0x02, 0x28, 0xe0, 0x54, 0xfc, 0x45, 0x27,
+0xf0, 0x90, 0x70, 0x9c, 0xe5, 0x3a, 0xf0, 0xa3, 0xe5, 0x47, 0xf0, 0x90, 0x70, 0x41, 0xe5, 0x3a,
+0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45,
+0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2,
+0x58, 0x22, 0xe4, 0xf5, 0x62, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x46, 0x14, 0x60, 0x62, 0x24,
+0x02, 0x60, 0x03, 0x02, 0x16, 0x2c, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54,
+0x7f, 0xf0, 0xa3, 0xe0, 0x20, 0xe7, 0x22, 0x90, 0x04, 0x34, 0xe0, 0xb4, 0x02, 0x1b, 0xa3, 0xe0,
+0xb4, 0x02, 0x16, 0xa3, 0xe0, 0xb4, 0x02, 0x11, 0x7f, 0x20, 0x12, 0x15, 0x68, 0x90, 0x10, 0x04,
+0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x80, 0x73, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x62, 0x03,
+0x80, 0x6a, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x11, 0x7f, 0x20, 0x12, 0x15, 0x68, 0x90,
+0x02, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02, 0x80, 0x51, 0xe5, 0x50, 0x70, 0x02, 0x80,
+0x46, 0x90, 0x02, 0xa3, 0xe0, 0x20, 0xe6, 0x3b, 0x90, 0x04, 0x37, 0xe0, 0x64, 0x22, 0x70, 0x33,
+0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96, 0xf0, 0x90, 0x12, 0x04, 0x74, 0x0a, 0xf0,
+0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xfa,
+0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54, 0xf9, 0xf0, 0x75, 0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5,
+0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x62, 0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15,
+0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xad, 0x62, 0xaf, 0x40, 0x12, 0x16, 0xb6, 0xe5, 0x62,
+0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01,
+0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x16, 0xb6, 0xe5,
+0x52, 0x14, 0x60, 0x09, 0x04, 0x70, 0x4c, 0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01,
+0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0,
+0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, 0x03, 0xf0, 0x90, 0x02, 0xa2, 0xe0, 0x44,
+0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02,
+0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41, 0x12, 0x16, 0xb6, 0x80, 0x02, 0xc2, 0x03, 0xe4, 0x90,
+0x01, 0x96, 0xf0, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5,
+0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4,
+0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83,
+0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, 0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1,
+0x4d, 0xc2, 0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90,
+0x10, 0x1d, 0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5,
+0x62, 0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0,
+0x90, 0x10, 0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0,
+0x30, 0x4a, 0x07, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01, 0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22,
+0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe9, 0x00, } ;
diff --git a/drivers/staging/rt2870/common/md5.c b/drivers/staging/rt2870/common/md5.c
new file mode 100644 (file)
index 0000000..774776b
--- /dev/null
@@ -0,0 +1,1427 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    md5.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Name            Date                    Modification logs
+       jan                     10-28-03                Initial
+       Rita            11-23-04                Modify MD5 and SHA-1
+       Rita            10-14-05                Modify SHA-1 in big-endian platform
+ */
+#include "../rt_config.h"
+
+/**
+ * md5_mac:
+ * @key: pointer to    the     key     used for MAC generation
+ * @key_len: length    of the key in bytes
+ * @data: pointer to the data area for which the MAC is        generated
+ * @data_len: length of        the     data in bytes
+ * @mac: pointer to    the     buffer holding space for the MAC; the buffer should
+ * have        space for 128-bit (16 bytes) MD5 hash value
+ *
+ * md5_mac() determines        the     message authentication code     by using secure hash
+ * MD5(key | data |    key).
+ */
+void md5_mac(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac)
+{
+       MD5_CTX context;
+
+       MD5Init(&context);
+       MD5Update(&context,     key, key_len);
+       MD5Update(&context,     data, data_len);
+       MD5Update(&context,     key, key_len);
+       MD5Final(mac, &context);
+}
+
+/**
+ * hmac_md5:
+ * @key: pointer to    the     key     used for MAC generation
+ * @key_len: length    of the key in bytes
+ * @data: pointer to the data area for which the MAC is        generated
+ * @data_len: length of        the     data in bytes
+ * @mac: pointer to    the     buffer holding space for the MAC; the buffer should
+ * have        space for 128-bit (16 bytes) MD5 hash value
+ *
+ * hmac_md5() determines the message authentication    code using HMAC-MD5.
+ * This        implementation is based on the sample code presented in RFC     2104.
+ */
+void hmac_md5(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac)
+{
+       MD5_CTX context;
+    u8 k_ipad[65]; /* inner padding - key XORd with ipad */
+    u8 k_opad[65]; /* outer padding - key XORd with opad */
+    u8 tk[16];
+       int     i;
+
+       //assert(key != NULL && data != NULL && mac != NULL);
+
+       /* if key is longer     than 64 bytes reset     it to key =     MD5(key) */
+       if (key_len     > 64) {
+               MD5_CTX ttcontext;
+
+               MD5Init(&ttcontext);
+               MD5Update(&ttcontext, key, key_len);
+               MD5Final(tk, &ttcontext);
+               //key=(PUCHAR)ttcontext.buf;
+               key     = tk;
+               key_len = 16;
+       }
+
+       /* the HMAC_MD5 transform looks like:
+        *
+        * MD5(K XOR opad, MD5(K XOR ipad, text))
+        *
+        * where K is an n byte key
+        * ipad is the byte     0x36 repeated 64 times
+        * opad is the byte     0x5c repeated 64 times
+        * and text     is the data     being protected */
+
+       /* start out by storing key     in pads */
+       NdisZeroMemory(k_ipad, sizeof(k_ipad));
+       NdisZeroMemory(k_opad,  sizeof(k_opad));
+       //assert(key_len < sizeof(k_ipad));
+       NdisMoveMemory(k_ipad, key,     key_len);
+       NdisMoveMemory(k_opad, key,     key_len);
+
+       /* XOR key with ipad and opad values */
+       for     (i = 0; i <     64;     i++) {
+               k_ipad[i] ^= 0x36;
+               k_opad[i] ^= 0x5c;
+       }
+
+       /* perform inner MD5 */
+       MD5Init(&context);                                       /*     init context for 1st pass */
+       MD5Update(&context,     k_ipad, 64);     /*     start with inner pad */
+       MD5Update(&context,     data, data_len); /*     then text of datagram */
+       MD5Final(mac, &context);                         /*     finish up 1st pass */
+
+       /* perform outer MD5 */
+       MD5Init(&context);                                       /*     init context for 2nd pass */
+       MD5Update(&context,     k_opad, 64);     /*     start with outer pad */
+       MD5Update(&context,     mac, 16);                /*     then results of 1st     hash */
+       MD5Final(mac, &context);                         /*     finish up 2nd pass */
+}
+
+#ifndef RT_BIG_ENDIAN
+#define byteReverse(buf, len)   /* Nothing */
+#else
+void byteReverse(unsigned char *buf, unsigned longs);
+void byteReverse(unsigned char *buf, unsigned longs)
+{
+    do {
+        *(UINT32 *)buf = SWAP32(*(UINT32 *)buf);
+        buf += 4;
+    } while (--longs);
+}
+#endif
+
+
+/* ==========================  MD5 implementation =========================== */
+// four base functions for MD5
+#define MD5_F1(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define MD5_F2(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define MD5_F3(x, y, z) ((x) ^ (y) ^ (z))
+#define MD5_F4(x, y, z) ((y) ^ ((x) | (~z)))
+#define CYCLIC_LEFT_SHIFT(w, s) (((w) << (s)) | ((w) >> (32-(s))))
+
+#define        MD5Step(f, w, x, y,     z, data, t, s)  \
+       ( w     += f(x, y, z) + data + t,  w = (CYCLIC_LEFT_SHIFT(w, s)) & 0xffffffff, w +=     x )
+
+
+/*
+ *  Function Description:
+ *      Initiate MD5 Context satisfied in RFC 1321
+ *
+ *  Arguments:
+ *      pCtx        Pointer    to MD5 context
+ *
+ *  Return Value:
+ *      None
+ */
+VOID MD5Init(MD5_CTX *pCtx)
+{
+    pCtx->Buf[0]=0x67452301;
+    pCtx->Buf[1]=0xefcdab89;
+    pCtx->Buf[2]=0x98badcfe;
+    pCtx->Buf[3]=0x10325476;
+
+    pCtx->LenInBitCount[0]=0;
+    pCtx->LenInBitCount[1]=0;
+}
+
+
+/*
+ *  Function Description:
+ *      Update MD5 Context, allow of an arrary of octets as the next portion
+ *      of the message
+ *
+ *  Arguments:
+ *      pCtx           Pointer to MD5 context
+ *         pData       Pointer to input data
+ *      LenInBytes  The length of input data (unit: byte)
+ *
+ *  Return Value:
+ *      None
+ *
+ *  Note:
+ *      Called after MD5Init or MD5Update(itself)
+ */
+VOID MD5Update(MD5_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes)
+{
+
+    UINT32 TfTimes;
+    UINT32 temp;
+       unsigned int i;
+
+    temp = pCtx->LenInBitCount[0];
+
+    pCtx->LenInBitCount[0] = (UINT32) (pCtx->LenInBitCount[0] + (LenInBytes << 3));
+
+    if (pCtx->LenInBitCount[0] < temp)
+        pCtx->LenInBitCount[1]++;   //carry in
+
+    pCtx->LenInBitCount[1] += LenInBytes >> 29;
+
+    // mod 64 bytes
+    temp = (temp >> 3) & 0x3f;
+
+    // process lacks of 64-byte data
+    if (temp)
+    {
+        UCHAR *pAds = (UCHAR *) pCtx->Input + temp;
+
+        if ((temp+LenInBytes) < 64)
+        {
+            NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes);
+            return;
+        }
+
+        NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp);
+        byteReverse(pCtx->Input, 16);
+        MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input);
+
+        pData += 64-temp;
+        LenInBytes -= 64-temp;
+    } // end of if (temp)
+
+
+    TfTimes = (LenInBytes >> 6);
+
+    for (i=TfTimes; i>0; i--)
+    {
+        NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64);
+        byteReverse(pCtx->Input, 16);
+        MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input);
+        pData += 64;
+        LenInBytes -= 64;
+    } // end of for
+
+    // buffering lacks of 64-byte data
+    if(LenInBytes)
+        NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes);
+
+}
+
+
+/*
+ *  Function Description:
+ *      Append padding bits and length of original message in the tail
+ *      The message digest has to be completed in the end
+ *
+ *  Arguments:
+ *      Digest         Output of Digest-Message for MD5
+ *     pCtx        Pointer     to MD5 context
+ *
+ *  Return Value:
+ *      None
+ *
+ *  Note:
+ *      Called after MD5Update
+ */
+VOID MD5Final(UCHAR Digest[16], MD5_CTX *pCtx)
+{
+    UCHAR Remainder;
+    UCHAR PadLenInBytes;
+    UCHAR *pAppend=0;
+    unsigned int i;
+
+    Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f);
+
+    PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder);
+
+    pAppend = (UCHAR *)pCtx->Input + Remainder;
+
+    // padding bits without crossing block(64-byte based) boundary
+    if (Remainder < 56)
+    {
+        *pAppend = 0x80;
+        PadLenInBytes --;
+
+        NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes);
+
+               // add data-length field, from low to high
+               for (i=0; i<4; i++)
+        {
+               pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff);
+               pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff);
+       }
+
+        byteReverse(pCtx->Input, 16);
+        MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input);
+    } // end of if
+
+    // padding bits with crossing block(64-byte based) boundary
+    else
+    {
+        // the first block ===
+        *pAppend = 0x80;
+        PadLenInBytes --;
+
+        NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1));
+        PadLenInBytes -= (64 - Remainder - 1);
+
+        byteReverse(pCtx->Input, 16);
+        MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input);
+
+
+        // the second block ===
+        NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes);
+
+        // add data-length field
+        for (i=0; i<4; i++)
+        {
+               pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff);
+               pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff);
+       }
+
+        byteReverse(pCtx->Input, 16);
+        MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input);
+    } // end of else
+
+
+    NdisMoveMemory((UCHAR *)Digest, (UINT32 *)pCtx->Buf, 16); // output
+    byteReverse((UCHAR *)Digest, 4);
+    NdisZeroMemory(pCtx, sizeof(pCtx)); // memory free
+}
+
+
+/*
+ *  Function Description:
+ *      The central algorithm of MD5, consists of four rounds and sixteen
+ *     steps per round
+ *
+ *  Arguments:
+ *      Buf     Buffers of four states (output: 16 bytes)
+ *         Mes     Input data (input: 64 bytes)
+ *
+ *  Return Value:
+ *      None
+ *
+ *  Note:
+ *      Called by MD5Update or MD5Final
+ */
+VOID MD5Transform(UINT32 Buf[4], UINT32 Mes[16])
+{
+    UINT32 Reg[4], Temp;
+       unsigned int i;
+
+    static UCHAR LShiftVal[16] =
+    {
+        7, 12, 17, 22,
+               5, 9 , 14, 20,
+               4, 11, 16, 23,
+               6, 10, 15, 21,
+       };
+
+
+       // [equal to 4294967296*abs(sin(index))]
+    static UINT32 MD5Table[64] =
+       {
+               0xd76aa478,     0xe8c7b756,     0x242070db,     0xc1bdceee,
+               0xf57c0faf,     0x4787c62a,     0xa8304613, 0xfd469501,
+               0x698098d8,     0x8b44f7af,     0xffff5bb1,     0x895cd7be,
+       0x6b901122,     0xfd987193,     0xa679438e,     0x49b40821,
+
+       0xf61e2562,     0xc040b340,     0x265e5a51,     0xe9b6c7aa,
+       0xd62f105d,     0x02441453,     0xd8a1e681,     0xe7d3fbc8,
+       0x21e1cde6,     0xc33707d6,     0xf4d50d87,     0x455a14ed,
+       0xa9e3e905,     0xfcefa3f8,     0x676f02d9,     0x8d2a4c8a,
+
+       0xfffa3942,     0x8771f681,     0x6d9d6122,     0xfde5380c,
+       0xa4beea44,     0x4bdecfa9,     0xf6bb4b60,     0xbebfbc70,
+       0x289b7ec6,     0xeaa127fa,     0xd4ef3085,     0x04881d05,
+       0xd9d4d039,     0xe6db99e5,     0x1fa27cf8,     0xc4ac5665,
+
+       0xf4292244,     0x432aff97,     0xab9423a7,     0xfc93a039,
+               0x655b59c3,     0x8f0ccc92,     0xffeff47d,     0x85845dd1,
+       0x6fa87e4f,     0xfe2ce6e0,     0xa3014314,     0x4e0811a1,
+       0xf7537e82,     0xbd3af235,     0x2ad7d2bb,     0xeb86d391
+       };
+
+
+    for (i=0; i<4; i++)
+        Reg[i]=Buf[i];
+
+
+    // 64 steps in MD5 algorithm
+    for (i=0; i<16; i++)
+    {
+        MD5Step(MD5_F1, Reg[0], Reg[1], Reg[2], Reg[3], Mes[i],
+                MD5Table[i], LShiftVal[i & 0x3]);
+
+        // one-word right shift
+        Temp   = Reg[3];
+        Reg[3] = Reg[2];
+        Reg[2] = Reg[1];
+        Reg[1] = Reg[0];
+        Reg[0] = Temp;
+    }
+    for (i=16; i<32; i++)
+    {
+        MD5Step(MD5_F2, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(5*(i & 0xf)+1) & 0xf],
+                MD5Table[i], LShiftVal[(0x1 << 2)+(i & 0x3)]);
+
+        // one-word right shift
+        Temp   = Reg[3];
+        Reg[3] = Reg[2];
+        Reg[2] = Reg[1];
+        Reg[1] = Reg[0];
+        Reg[0] = Temp;
+    }
+    for (i=32; i<48; i++)
+    {
+        MD5Step(MD5_F3, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(3*(i & 0xf)+5) & 0xf],
+                MD5Table[i], LShiftVal[(0x1 << 3)+(i & 0x3)]);
+
+        // one-word right shift
+        Temp   = Reg[3];
+        Reg[3] = Reg[2];
+        Reg[2] = Reg[1];
+        Reg[1] = Reg[0];
+        Reg[0] = Temp;
+    }
+    for (i=48; i<64; i++)
+    {
+        MD5Step(MD5_F4, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(7*(i & 0xf)) & 0xf],
+                MD5Table[i], LShiftVal[(0x3 << 2)+(i & 0x3)]);
+
+        // one-word right shift
+        Temp   = Reg[3];
+        Reg[3] = Reg[2];
+        Reg[2] = Reg[1];
+        Reg[1] = Reg[0];
+        Reg[0] = Temp;
+    }
+
+
+    // (temporary)output
+    for (i=0; i<4; i++)
+        Buf[i] += Reg[i];
+
+}
+
+
+
+/* =========================  SHA-1 implementation ========================== */
+// four base functions for SHA-1
+#define SHA1_F1(b, c, d)    (((b) & (c)) | ((~b) & (d)))
+#define SHA1_F2(b, c, d)    ((b) ^ (c) ^ (d))
+#define SHA1_F3(b, c, d)    (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
+
+
+#define SHA1Step(f, a, b, c, d, e, w, k)    \
+    ( e        += ( f(b, c, d) + w + k + CYCLIC_LEFT_SHIFT(a, 5)) & 0xffffffff, \
+      b = CYCLIC_LEFT_SHIFT(b, 30) )
+
+//Initiate SHA-1 Context satisfied in RFC 3174
+VOID SHAInit(SHA_CTX *pCtx)
+{
+    pCtx->Buf[0]=0x67452301;
+    pCtx->Buf[1]=0xefcdab89;
+    pCtx->Buf[2]=0x98badcfe;
+    pCtx->Buf[3]=0x10325476;
+    pCtx->Buf[4]=0xc3d2e1f0;
+
+    pCtx->LenInBitCount[0]=0;
+    pCtx->LenInBitCount[1]=0;
+}
+
+/*
+ *  Function Description:
+ *      Update SHA-1 Context, allow of an arrary of octets as the next
+ *      portion of the message
+ *
+ *  Arguments:
+ *      pCtx           Pointer to SHA-1 context
+ *         pData       Pointer to input data
+ *      LenInBytes  The length of input data (unit: byte)
+ *
+ *  Return Value:
+ *      error       indicate more than pow(2,64) bits of data
+ *
+ *  Note:
+ *      Called after SHAInit or SHAUpdate(itself)
+ */
+UCHAR SHAUpdate(SHA_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes)
+{
+    UINT32 TfTimes;
+    UINT32 temp1,temp2;
+       unsigned int i;
+       UCHAR err=1;
+
+    temp1 = pCtx->LenInBitCount[0];
+    temp2 = pCtx->LenInBitCount[1];
+
+    pCtx->LenInBitCount[0] = (UINT32) (pCtx->LenInBitCount[0] + (LenInBytes << 3));
+    if (pCtx->LenInBitCount[0] < temp1)
+        pCtx->LenInBitCount[1]++;   //carry in
+
+
+    pCtx->LenInBitCount[1] = (UINT32) (pCtx->LenInBitCount[1] +(LenInBytes >> 29));
+    if (pCtx->LenInBitCount[1] < temp2)
+        return (err);   //check total length of original data
+
+
+    // mod 64 bytes
+    temp1 = (temp1 >> 3) & 0x3f;
+
+    // process lacks of 64-byte data
+    if (temp1)
+    {
+        UCHAR *pAds = (UCHAR *) pCtx->Input + temp1;
+
+        if ((temp1+LenInBytes) < 64)
+        {
+            NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes);
+            return (0);
+        }
+
+        NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp1);
+        byteReverse((UCHAR *)pCtx->Input, 16);
+
+        NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
+        SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input);
+
+        pData += 64-temp1;
+        LenInBytes -= 64-temp1;
+    } // end of if (temp1)
+
+
+    TfTimes = (LenInBytes >> 6);
+
+    for (i=TfTimes; i>0; i--)
+    {
+        NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64);
+        byteReverse((UCHAR *)pCtx->Input, 16);
+
+        NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
+        SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input);
+        pData += 64;
+        LenInBytes -= 64;
+    } // end of for
+
+    // buffering lacks of 64-byte data
+    if(LenInBytes)
+        NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes);
+
+       return (0);
+
+}
+
+// Append padding bits and length of original message in the tail
+// The message digest has to be completed in the end
+VOID SHAFinal(SHA_CTX *pCtx, UCHAR Digest[20])
+{
+    UCHAR Remainder;
+    UCHAR PadLenInBytes;
+    UCHAR *pAppend=0;
+    unsigned int i;
+
+    Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f);
+
+    pAppend = (UCHAR *)pCtx->Input + Remainder;
+
+    PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder);
+
+    // padding bits without crossing block(64-byte based) boundary
+    if (Remainder < 56)
+    {
+        *pAppend = 0x80;
+        PadLenInBytes --;
+
+        NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes);
+
+               // add data-length field, from high to low
+        for (i=0; i<4; i++)
+        {
+               pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff);
+               pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff);
+       }
+
+        byteReverse((UCHAR *)pCtx->Input, 16);
+        NdisZeroMemory((UCHAR *)pCtx->Input + 64, 14);
+        SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input);
+    } // end of if
+
+    // padding bits with crossing block(64-byte based) boundary
+    else
+    {
+        // the first block ===
+        *pAppend = 0x80;
+        PadLenInBytes --;
+
+        NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1));
+        PadLenInBytes -= (64 - Remainder - 1);
+
+        byteReverse((UCHAR *)pCtx->Input, 16);
+        NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
+        SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input);
+
+
+        // the second block ===
+        NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes);
+
+               // add data-length field
+               for (i=0; i<4; i++)
+        {
+               pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff);
+               pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff);
+       }
+
+        byteReverse((UCHAR *)pCtx->Input, 16);
+        NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
+        SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input);
+    } // end of else
+
+
+    //Output, bytereverse
+    for (i=0; i<20; i++)
+    {
+        Digest [i] = (UCHAR)(pCtx->Buf[i>>2] >> 8*(3-(i & 0x3)));
+    }
+
+    NdisZeroMemory(pCtx, sizeof(pCtx)); // memory free
+}
+
+
+// The central algorithm of SHA-1, consists of four rounds and
+// twenty steps per round
+VOID SHATransform(UINT32 Buf[5], UINT32 Mes[20])
+{
+    UINT32 Reg[5],Temp;
+       unsigned int i;
+    UINT32 W[80];
+
+    static UINT32 SHA1Table[4] = { 0x5a827999, 0x6ed9eba1,
+                                  0x8f1bbcdc, 0xca62c1d6 };
+
+    Reg[0]=Buf[0];
+       Reg[1]=Buf[1];
+       Reg[2]=Buf[2];
+       Reg[3]=Buf[3];
+       Reg[4]=Buf[4];
+
+    //the first octet of a word is stored in the 0th element, bytereverse
+       for(i = 0; i < 16; i++)
+    {
+       W[i]  = (Mes[i] >> 24) & 0xff;
+        W[i] |= (Mes[i] >> 8 ) & 0xff00;
+        W[i] |= (Mes[i] << 8 ) & 0xff0000;
+        W[i] |= (Mes[i] << 24) & 0xff000000;
+    }
+
+
+    for        (i = 0; i < 64; i++)
+           W[16+i] = CYCLIC_LEFT_SHIFT(W[i] ^ W[2+i] ^ W[8+i] ^ W[13+i], 1);
+
+
+    // 80 steps in SHA-1 algorithm
+    for (i=0; i<80; i++)
+    {
+        if (i<20)
+            SHA1Step(SHA1_F1, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
+                     W[i], SHA1Table[0]);
+
+        else if (i>=20 && i<40)
+            SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
+                     W[i], SHA1Table[1]);
+
+               else if (i>=40 && i<60)
+            SHA1Step(SHA1_F3, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
+                      W[i], SHA1Table[2]);
+
+        else
+            SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
+                     W[i], SHA1Table[3]);
+
+
+       // one-word right shift
+               Temp   = Reg[4];
+        Reg[4] = Reg[3];
+        Reg[3] = Reg[2];
+        Reg[2] = Reg[1];
+        Reg[1] = Reg[0];
+        Reg[0] = Temp;
+
+    } // end of for-loop
+
+
+    // (temporary)output
+    for (i=0; i<5; i++)
+        Buf[i] += Reg[i];
+
+}
+
+
+/* =========================  AES En/Decryption ========================== */
+
+/* forward S-box */
+static uint32 FSb[256] =
+{
+       0x63, 0x7C,     0x77, 0x7B,     0xF2, 0x6B,     0x6F, 0xC5,
+       0x30, 0x01,     0x67, 0x2B,     0xFE, 0xD7,     0xAB, 0x76,
+       0xCA, 0x82,     0xC9, 0x7D,     0xFA, 0x59,     0x47, 0xF0,
+       0xAD, 0xD4,     0xA2, 0xAF,     0x9C, 0xA4,     0x72, 0xC0,
+       0xB7, 0xFD,     0x93, 0x26,     0x36, 0x3F,     0xF7, 0xCC,
+       0x34, 0xA5,     0xE5, 0xF1,     0x71, 0xD8,     0x31, 0x15,
+       0x04, 0xC7,     0x23, 0xC3,     0x18, 0x96,     0x05, 0x9A,
+       0x07, 0x12,     0x80, 0xE2,     0xEB, 0x27,     0xB2, 0x75,
+       0x09, 0x83,     0x2C, 0x1A,     0x1B, 0x6E,     0x5A, 0xA0,
+       0x52, 0x3B,     0xD6, 0xB3,     0x29, 0xE3,     0x2F, 0x84,
+       0x53, 0xD1,     0x00, 0xED,     0x20, 0xFC,     0xB1, 0x5B,
+       0x6A, 0xCB,     0xBE, 0x39,     0x4A, 0x4C,     0x58, 0xCF,
+       0xD0, 0xEF,     0xAA, 0xFB,     0x43, 0x4D,     0x33, 0x85,
+       0x45, 0xF9,     0x02, 0x7F,     0x50, 0x3C,     0x9F, 0xA8,
+       0x51, 0xA3,     0x40, 0x8F,     0x92, 0x9D,     0x38, 0xF5,
+       0xBC, 0xB6,     0xDA, 0x21,     0x10, 0xFF,     0xF3, 0xD2,
+       0xCD, 0x0C,     0x13, 0xEC,     0x5F, 0x97,     0x44, 0x17,
+       0xC4, 0xA7,     0x7E, 0x3D,     0x64, 0x5D,     0x19, 0x73,
+       0x60, 0x81,     0x4F, 0xDC,     0x22, 0x2A,     0x90, 0x88,
+       0x46, 0xEE,     0xB8, 0x14,     0xDE, 0x5E,     0x0B, 0xDB,
+       0xE0, 0x32,     0x3A, 0x0A,     0x49, 0x06,     0x24, 0x5C,
+       0xC2, 0xD3,     0xAC, 0x62,     0x91, 0x95,     0xE4, 0x79,
+       0xE7, 0xC8,     0x37, 0x6D,     0x8D, 0xD5,     0x4E, 0xA9,
+       0x6C, 0x56,     0xF4, 0xEA,     0x65, 0x7A,     0xAE, 0x08,
+       0xBA, 0x78,     0x25, 0x2E,     0x1C, 0xA6,     0xB4, 0xC6,
+       0xE8, 0xDD,     0x74, 0x1F,     0x4B, 0xBD,     0x8B, 0x8A,
+       0x70, 0x3E,     0xB5, 0x66,     0x48, 0x03,     0xF6, 0x0E,
+       0x61, 0x35,     0x57, 0xB9,     0x86, 0xC1,     0x1D, 0x9E,
+       0xE1, 0xF8,     0x98, 0x11,     0x69, 0xD9,     0x8E, 0x94,
+       0x9B, 0x1E,     0x87, 0xE9,     0xCE, 0x55,     0x28, 0xDF,
+       0x8C, 0xA1,     0x89, 0x0D,     0xBF, 0xE6,     0x42, 0x68,
+       0x41, 0x99,     0x2D, 0x0F,     0xB0, 0x54,     0xBB, 0x16
+};
+
+/* forward table */
+#define        FT \
+\
+       V(C6,63,63,A5), V(F8,7C,7C,84), V(EE,77,77,99), V(F6,7B,7B,8D), \
+       V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(91,C5,C5,54), \
+       V(60,30,30,50), V(02,01,01,03), V(CE,67,67,A9), V(56,2B,2B,7D), \
+       V(E7,FE,FE,19), V(B5,D7,D7,62), V(4D,AB,AB,E6), V(EC,76,76,9A), \
+       V(8F,CA,CA,45), V(1F,82,82,9D), V(89,C9,C9,40), V(FA,7D,7D,87), \
+       V(EF,FA,FA,15), V(B2,59,59,EB), V(8E,47,47,C9), V(FB,F0,F0,0B), \
+       V(41,AD,AD,EC), V(B3,D4,D4,67), V(5F,A2,A2,FD), V(45,AF,AF,EA), \
+       V(23,9C,9C,BF), V(53,A4,A4,F7), V(E4,72,72,96), V(9B,C0,C0,5B), \
+       V(75,B7,B7,C2), V(E1,FD,FD,1C), V(3D,93,93,AE), V(4C,26,26,6A), \
+       V(6C,36,36,5A), V(7E,3F,3F,41), V(F5,F7,F7,02), V(83,CC,CC,4F), \
+       V(68,34,34,5C), V(51,A5,A5,F4), V(D1,E5,E5,34), V(F9,F1,F1,08), \
+       V(E2,71,71,93), V(AB,D8,D8,73), V(62,31,31,53), V(2A,15,15,3F), \
+       V(08,04,04,0C), V(95,C7,C7,52), V(46,23,23,65), V(9D,C3,C3,5E), \
+       V(30,18,18,28), V(37,96,96,A1), V(0A,05,05,0F), V(2F,9A,9A,B5), \
+       V(0E,07,07,09), V(24,12,12,36), V(1B,80,80,9B), V(DF,E2,E2,3D), \
+       V(CD,EB,EB,26), V(4E,27,27,69), V(7F,B2,B2,CD), V(EA,75,75,9F), \
+       V(12,09,09,1B), V(1D,83,83,9E), V(58,2C,2C,74), V(34,1A,1A,2E), \
+       V(36,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \
+       V(A4,52,52,F6), V(76,3B,3B,4D), V(B7,D6,D6,61), V(7D,B3,B3,CE), \
+       V(52,29,29,7B), V(DD,E3,E3,3E), V(5E,2F,2F,71), V(13,84,84,97), \
+       V(A6,53,53,F5), V(B9,D1,D1,68), V(00,00,00,00), V(C1,ED,ED,2C), \
+       V(40,20,20,60), V(E3,FC,FC,1F), V(79,B1,B1,C8), V(B6,5B,5B,ED), \
+       V(D4,6A,6A,BE), V(8D,CB,CB,46), V(67,BE,BE,D9), V(72,39,39,4B), \
+       V(94,4A,4A,DE), V(98,4C,4C,D4), V(B0,58,58,E8), V(85,CF,CF,4A), \
+       V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,16), \
+       V(86,43,43,C5), V(9A,4D,4D,D7), V(66,33,33,55), V(11,85,85,94), \
+       V(8A,45,45,CF), V(E9,F9,F9,10), V(04,02,02,06), V(FE,7F,7F,81), \
+       V(A0,50,50,F0), V(78,3C,3C,44), V(25,9F,9F,BA), V(4B,A8,A8,E3), \
+       V(A2,51,51,F3), V(5D,A3,A3,FE), V(80,40,40,C0), V(05,8F,8F,8A), \
+       V(3F,92,92,AD), V(21,9D,9D,BC), V(70,38,38,48), V(F1,F5,F5,04), \
+       V(63,BC,BC,DF), V(77,B6,B6,C1), V(AF,DA,DA,75), V(42,21,21,63), \
+       V(20,10,10,30), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \
+       V(81,CD,CD,4C), V(18,0C,0C,14), V(26,13,13,35), V(C3,EC,EC,2F), \
+       V(BE,5F,5F,E1), V(35,97,97,A2), V(88,44,44,CC), V(2E,17,17,39), \
+       V(93,C4,C4,57), V(55,A7,A7,F2), V(FC,7E,7E,82), V(7A,3D,3D,47), \
+       V(C8,64,64,AC), V(BA,5D,5D,E7), V(32,19,19,2B), V(E6,73,73,95), \
+       V(C0,60,60,A0), V(19,81,81,98), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \
+       V(44,22,22,66), V(54,2A,2A,7E), V(3B,90,90,AB), V(0B,88,88,83), \
+       V(8C,46,46,CA), V(C7,EE,EE,29), V(6B,B8,B8,D3), V(28,14,14,3C), \
+       V(A7,DE,DE,79), V(BC,5E,5E,E2), V(16,0B,0B,1D), V(AD,DB,DB,76), \
+       V(DB,E0,E0,3B), V(64,32,32,56), V(74,3A,3A,4E), V(14,0A,0A,1E), \
+       V(92,49,49,DB), V(0C,06,06,0A), V(48,24,24,6C), V(B8,5C,5C,E4), \
+       V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(43,AC,AC,EF), V(C4,62,62,A6), \
+       V(39,91,91,A8), V(31,95,95,A4), V(D3,E4,E4,37), V(F2,79,79,8B), \
+       V(D5,E7,E7,32), V(8B,C8,C8,43), V(6E,37,37,59), V(DA,6D,6D,B7), \
+       V(01,8D,8D,8C), V(B1,D5,D5,64), V(9C,4E,4E,D2), V(49,A9,A9,E0), \
+       V(D8,6C,6C,B4), V(AC,56,56,FA), V(F3,F4,F4,07), V(CF,EA,EA,25), \
+       V(CA,65,65,AF), V(F4,7A,7A,8E), V(47,AE,AE,E9), V(10,08,08,18), \
+       V(6F,BA,BA,D5), V(F0,78,78,88), V(4A,25,25,6F), V(5C,2E,2E,72), \
+       V(38,1C,1C,24), V(57,A6,A6,F1), V(73,B4,B4,C7), V(97,C6,C6,51), \
+       V(CB,E8,E8,23), V(A1,DD,DD,7C), V(E8,74,74,9C), V(3E,1F,1F,21), \
+       V(96,4B,4B,DD), V(61,BD,BD,DC), V(0D,8B,8B,86), V(0F,8A,8A,85), \
+       V(E0,70,70,90), V(7C,3E,3E,42), V(71,B5,B5,C4), V(CC,66,66,AA), \
+       V(90,48,48,D8), V(06,03,03,05), V(F7,F6,F6,01), V(1C,0E,0E,12), \
+       V(C2,61,61,A3), V(6A,35,35,5F), V(AE,57,57,F9), V(69,B9,B9,D0), \
+       V(17,86,86,91), V(99,C1,C1,58), V(3A,1D,1D,27), V(27,9E,9E,B9), \
+       V(D9,E1,E1,38), V(EB,F8,F8,13), V(2B,98,98,B3), V(22,11,11,33), \
+       V(D2,69,69,BB), V(A9,D9,D9,70), V(07,8E,8E,89), V(33,94,94,A7), \
+       V(2D,9B,9B,B6), V(3C,1E,1E,22), V(15,87,87,92), V(C9,E9,E9,20), \
+       V(87,CE,CE,49), V(AA,55,55,FF), V(50,28,28,78), V(A5,DF,DF,7A), \
+       V(03,8C,8C,8F), V(59,A1,A1,F8), V(09,89,89,80), V(1A,0D,0D,17), \
+       V(65,BF,BF,DA), V(D7,E6,E6,31), V(84,42,42,C6), V(D0,68,68,B8), \
+       V(82,41,41,C3), V(29,99,99,B0), V(5A,2D,2D,77), V(1E,0F,0F,11), \
+       V(7B,B0,B0,CB), V(A8,54,54,FC), V(6D,BB,BB,D6), V(2C,16,16,3A)
+
+#define        V(a,b,c,d) 0x##a##b##c##d
+static uint32 FT0[256] = { FT };
+#undef V
+
+#define        V(a,b,c,d) 0x##d##a##b##c
+static uint32 FT1[256] = { FT };
+#undef V
+
+#define        V(a,b,c,d) 0x##c##d##a##b
+static uint32 FT2[256] = { FT };
+#undef V
+
+#define        V(a,b,c,d) 0x##b##c##d##a
+static uint32 FT3[256] = { FT };
+#undef V
+
+#undef FT
+
+/* reverse S-box */
+
+static uint32 RSb[256] =
+{
+       0x52, 0x09,     0x6A, 0xD5,     0x30, 0x36,     0xA5, 0x38,
+       0xBF, 0x40,     0xA3, 0x9E,     0x81, 0xF3,     0xD7, 0xFB,
+       0x7C, 0xE3,     0x39, 0x82,     0x9B, 0x2F,     0xFF, 0x87,
+       0x34, 0x8E,     0x43, 0x44,     0xC4, 0xDE,     0xE9, 0xCB,
+       0x54, 0x7B,     0x94, 0x32,     0xA6, 0xC2,     0x23, 0x3D,
+       0xEE, 0x4C,     0x95, 0x0B,     0x42, 0xFA,     0xC3, 0x4E,
+       0x08, 0x2E,     0xA1, 0x66,     0x28, 0xD9,     0x24, 0xB2,
+       0x76, 0x5B,     0xA2, 0x49,     0x6D, 0x8B,     0xD1, 0x25,
+       0x72, 0xF8,     0xF6, 0x64,     0x86, 0x68,     0x98, 0x16,
+       0xD4, 0xA4,     0x5C, 0xCC,     0x5D, 0x65,     0xB6, 0x92,
+       0x6C, 0x70,     0x48, 0x50,     0xFD, 0xED,     0xB9, 0xDA,
+       0x5E, 0x15,     0x46, 0x57,     0xA7, 0x8D,     0x9D, 0x84,
+       0x90, 0xD8,     0xAB, 0x00,     0x8C, 0xBC,     0xD3, 0x0A,
+       0xF7, 0xE4,     0x58, 0x05,     0xB8, 0xB3,     0x45, 0x06,
+       0xD0, 0x2C,     0x1E, 0x8F,     0xCA, 0x3F,     0x0F, 0x02,
+       0xC1, 0xAF,     0xBD, 0x03,     0x01, 0x13,     0x8A, 0x6B,
+       0x3A, 0x91,     0x11, 0x41,     0x4F, 0x67,     0xDC, 0xEA,
+       0x97, 0xF2,     0xCF, 0xCE,     0xF0, 0xB4,     0xE6, 0x73,
+       0x96, 0xAC,     0x74, 0x22,     0xE7, 0xAD,     0x35, 0x85,
+       0xE2, 0xF9,     0x37, 0xE8,     0x1C, 0x75,     0xDF, 0x6E,
+       0x47, 0xF1,     0x1A, 0x71,     0x1D, 0x29,     0xC5, 0x89,
+       0x6F, 0xB7,     0x62, 0x0E,     0xAA, 0x18,     0xBE, 0x1B,
+       0xFC, 0x56,     0x3E, 0x4B,     0xC6, 0xD2,     0x79, 0x20,
+       0x9A, 0xDB,     0xC0, 0xFE,     0x78, 0xCD,     0x5A, 0xF4,
+       0x1F, 0xDD,     0xA8, 0x33,     0x88, 0x07,     0xC7, 0x31,
+       0xB1, 0x12,     0x10, 0x59,     0x27, 0x80,     0xEC, 0x5F,
+       0x60, 0x51,     0x7F, 0xA9,     0x19, 0xB5,     0x4A, 0x0D,
+       0x2D, 0xE5,     0x7A, 0x9F,     0x93, 0xC9,     0x9C, 0xEF,
+       0xA0, 0xE0,     0x3B, 0x4D,     0xAE, 0x2A,     0xF5, 0xB0,
+       0xC8, 0xEB,     0xBB, 0x3C,     0x83, 0x53,     0x99, 0x61,
+       0x17, 0x2B,     0x04, 0x7E,     0xBA, 0x77,     0xD6, 0x26,
+       0xE1, 0x69,     0x14, 0x63,     0x55, 0x21,     0x0C, 0x7D
+};
+
+/* reverse table */
+
+#define        RT \
+\
+       V(51,F4,A7,50), V(7E,41,65,53), V(1A,17,A4,C3), V(3A,27,5E,96), \
+       V(3B,AB,6B,CB), V(1F,9D,45,F1), V(AC,FA,58,AB), V(4B,E3,03,93), \
+       V(20,30,FA,55), V(AD,76,6D,F6), V(88,CC,76,91), V(F5,02,4C,25), \
+       V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(26,35,44,80), V(B5,62,A3,8F), \
+       V(DE,B1,5A,49), V(25,BA,1B,67), V(45,EA,0E,98), V(5D,FE,C0,E1), \
+       V(C3,2F,75,02), V(81,4C,F0,12), V(8D,46,97,A3), V(6B,D3,F9,C6), \
+       V(03,8F,5F,E7), V(15,92,9C,95), V(BF,6D,7A,EB), V(95,52,59,DA), \
+       V(D4,BE,83,2D), V(58,74,21,D3), V(49,E0,69,29), V(8E,C9,C8,44), \
+       V(75,C2,89,6A), V(F4,8E,79,78), V(99,58,3E,6B), V(27,B9,71,DD), \
+       V(BE,E1,4F,B6), V(F0,88,AD,17), V(C9,20,AC,66), V(7D,CE,3A,B4), \
+       V(63,DF,4A,18), V(E5,1A,31,82), V(97,51,33,60), V(62,53,7F,45), \
+       V(B1,64,77,E0), V(BB,6B,AE,84), V(FE,81,A0,1C), V(F9,08,2B,94), \
+       V(70,48,68,58), V(8F,45,FD,19), V(94,DE,6C,87), V(52,7B,F8,B7), \
+       V(AB,73,D3,23), V(72,4B,02,E2), V(E3,1F,8F,57), V(66,55,AB,2A), \
+       V(B2,EB,28,07), V(2F,B5,C2,03), V(86,C5,7B,9A), V(D3,37,08,A5), \
+       V(30,28,87,F2), V(23,BF,A5,B2), V(02,03,6A,BA), V(ED,16,82,5C), \
+       V(8A,CF,1C,2B), V(A7,79,B4,92), V(F3,07,F2,F0), V(4E,69,E2,A1), \
+       V(65,DA,F4,CD), V(06,05,BE,D5), V(D1,34,62,1F), V(C4,A6,FE,8A), \
+       V(34,2E,53,9D), V(A2,F3,55,A0), V(05,8A,E1,32), V(A4,F6,EB,75), \
+       V(0B,83,EC,39), V(40,60,EF,AA), V(5E,71,9F,06), V(BD,6E,10,51), \
+       V(3E,21,8A,F9), V(96,DD,06,3D), V(DD,3E,05,AE), V(4D,E6,BD,46), \
+       V(91,54,8D,B5), V(71,C4,5D,05), V(04,06,D4,6F), V(60,50,15,FF), \
+       V(19,98,FB,24), V(D6,BD,E9,97), V(89,40,43,CC), V(67,D9,9E,77), \
+       V(B0,E8,42,BD), V(07,89,8B,88), V(E7,19,5B,38), V(79,C8,EE,DB), \
+       V(A1,7C,0A,47), V(7C,42,0F,E9), V(F8,84,1E,C9), V(00,00,00,00), \
+       V(09,80,86,83), V(32,2B,ED,48), V(1E,11,70,AC), V(6C,5A,72,4E), \
+       V(FD,0E,FF,FB), V(0F,85,38,56), V(3D,AE,D5,1E), V(36,2D,39,27), \
+       V(0A,0F,D9,64), V(68,5C,A6,21), V(9B,5B,54,D1), V(24,36,2E,3A), \
+       V(0C,0A,67,B1), V(93,57,E7,0F), V(B4,EE,96,D2), V(1B,9B,91,9E), \
+       V(80,C0,C5,4F), V(61,DC,20,A2), V(5A,77,4B,69), V(1C,12,1A,16), \
+       V(E2,93,BA,0A), V(C0,A0,2A,E5), V(3C,22,E0,43), V(12,1B,17,1D), \
+       V(0E,09,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(14,1E,A9,C8), \
+       V(57,F1,19,85), V(AF,75,07,4C), V(EE,99,DD,BB), V(A3,7F,60,FD), \
+       V(F7,01,26,9F), V(5C,72,F5,BC), V(44,66,3B,C5), V(5B,FB,7E,34), \
+       V(8B,43,29,76), V(CB,23,C6,DC), V(B6,ED,FC,68), V(B8,E4,F1,63), \
+       V(D7,31,DC,CA), V(42,63,85,10), V(13,97,22,40), V(84,C6,11,20), \
+       V(85,4A,24,7D), V(D2,BB,3D,F8), V(AE,F9,32,11), V(C7,29,A1,6D), \
+       V(1D,9E,2F,4B), V(DC,B2,30,F3), V(0D,86,52,EC), V(77,C1,E3,D0), \
+       V(2B,B3,16,6C), V(A9,70,B9,99), V(11,94,48,FA), V(47,E9,64,22), \
+       V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(56,7D,2C,D8), V(22,33,90,EF), \
+       V(87,49,4E,C7), V(D9,38,D1,C1), V(8C,CA,A2,FE), V(98,D4,0B,36), \
+       V(A6,F5,81,CF), V(A5,7A,DE,28), V(DA,B7,8E,26), V(3F,AD,BF,A4), \
+       V(2C,3A,9D,E4), V(50,78,92,0D), V(6A,5F,CC,9B), V(54,7E,46,62), \
+       V(F6,8D,13,C2), V(90,D8,B8,E8), V(2E,39,F7,5E), V(82,C3,AF,F5), \
+       V(9F,5D,80,BE), V(69,D0,93,7C), V(6F,D5,2D,A9), V(CF,25,12,B3), \
+       V(C8,AC,99,3B), V(10,18,7D,A7), V(E8,9C,63,6E), V(DB,3B,BB,7B), \
+       V(CD,26,78,09), V(6E,59,18,F4), V(EC,9A,B7,01), V(83,4F,9A,A8), \
+       V(E6,95,6E,65), V(AA,FF,E6,7E), V(21,BC,CF,08), V(EF,15,E8,E6), \
+       V(BA,E7,9B,D9), V(4A,6F,36,CE), V(EA,9F,09,D4), V(29,B0,7C,D6), \
+       V(31,A4,B2,AF), V(2A,3F,23,31), V(C6,A5,94,30), V(35,A2,66,C0), \
+       V(74,4E,BC,37), V(FC,82,CA,A6), V(E0,90,D0,B0), V(33,A7,D8,15), \
+       V(F1,04,98,4A), V(41,EC,DA,F7), V(7F,CD,50,0E), V(17,91,F6,2F), \
+       V(76,4D,D6,8D), V(43,EF,B0,4D), V(CC,AA,4D,54), V(E4,96,04,DF), \
+       V(9E,D1,B5,E3), V(4C,6A,88,1B), V(C1,2C,1F,B8), V(46,65,51,7F), \
+       V(9D,5E,EA,04), V(01,8C,35,5D), V(FA,87,74,73), V(FB,0B,41,2E), \
+       V(B3,67,1D,5A), V(92,DB,D2,52), V(E9,10,56,33), V(6D,D6,47,13), \
+       V(9A,D7,61,8C), V(37,A1,0C,7A), V(59,F8,14,8E), V(EB,13,3C,89), \
+       V(CE,A9,27,EE), V(B7,61,C9,35), V(E1,1C,E5,ED), V(7A,47,B1,3C), \
+       V(9C,D2,DF,59), V(55,F2,73,3F), V(18,14,CE,79), V(73,C7,37,BF), \
+       V(53,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,14), V(78,44,DB,86), \
+       V(CA,AF,F3,81), V(B9,68,C4,3E), V(38,24,34,2C), V(C2,A3,40,5F), \
+       V(16,1D,C3,72), V(BC,E2,25,0C), V(28,3C,49,8B), V(FF,0D,95,41), \
+       V(39,A8,01,71), V(08,0C,B3,DE), V(D8,B4,E4,9C), V(64,56,C1,90), \
+       V(7B,CB,84,61), V(D5,32,B6,70), V(48,6C,5C,74), V(D0,B8,57,42)
+
+#define        V(a,b,c,d) 0x##a##b##c##d
+static uint32 RT0[256] = { RT };
+#undef V
+
+#define        V(a,b,c,d) 0x##d##a##b##c
+static uint32 RT1[256] = { RT };
+#undef V
+
+#define        V(a,b,c,d) 0x##c##d##a##b
+static uint32 RT2[256] = { RT };
+#undef V
+
+#define        V(a,b,c,d) 0x##b##c##d##a
+static uint32 RT3[256] = { RT };
+#undef V
+
+#undef RT
+
+/* round constants */
+
+static uint32 RCON[10] =
+{
+       0x01000000,     0x02000000,     0x04000000,     0x08000000,
+       0x10000000,     0x20000000,     0x40000000,     0x80000000,
+       0x1B000000,     0x36000000
+};
+
+/* key schedule        tables */
+
+static int KT_init = 1;
+
+static uint32 KT0[256];
+static uint32 KT1[256];
+static uint32 KT2[256];
+static uint32 KT3[256];
+
+/* platform-independant        32-bit integer manipulation     macros */
+
+#define        GET_UINT32(n,b,i)                                               \
+{                                                                                              \
+       (n)     = (     (uint32) (b)[(i)        ] << 24 )               \
+               | (     (uint32) (b)[(i) + 1] << 16     )               \
+               | (     (uint32) (b)[(i) + 2] <<  8     )               \
+               | (     (uint32) (b)[(i) + 3]           );              \
+}
+
+#define        PUT_UINT32(n,b,i)                                               \
+{                                                                                              \
+       (b)[(i)    ] = (uint8) ( (n) >> 24 );           \
+       (b)[(i) + 1] = (uint8) ( (n) >> 16 );           \
+       (b)[(i) + 2] = (uint8) ( (n) >>  8 );           \
+       (b)[(i) + 3] = (uint8) ( (n)       );           \
+}
+
+/* AES key scheduling routine */
+
+int    rtmp_aes_set_key( aes_context *ctx, uint8 *key, int nbits )
+{
+       int     i;
+       uint32 *RK,     *SK;
+
+       switch( nbits )
+       {
+               case 128: ctx->nr =     10;     break;
+               case 192: ctx->nr =     12;     break;
+               case 256: ctx->nr =     14;     break;
+               default : return( 1     );
+       }
+
+       RK = ctx->erk;
+
+       for( i = 0;     i <     (nbits >> 5); i++ )
+       {
+               GET_UINT32(     RK[i], key,     i *     4 );
+       }
+
+       /* setup encryption     round keys */
+
+       switch( nbits )
+       {
+       case 128:
+
+               for( i = 0;     i <     10;     i++, RK += 4 )
+               {
+                       RK[4]  = RK[0] ^ RCON[i] ^
+                                               ( FSb[ (uint8) ( RK[3] >> 16 ) ] <<     24 ) ^
+                                               ( FSb[ (uint8) ( RK[3] >>  8 ) ] <<     16 ) ^
+                                               ( FSb[ (uint8) ( RK[3]           ) ] <<  8 ) ^
+                                               ( FSb[ (uint8) ( RK[3] >> 24 ) ]           );
+
+                       RK[5]  = RK[1] ^ RK[4];
+                       RK[6]  = RK[2] ^ RK[5];
+                       RK[7]  = RK[3] ^ RK[6];
+               }
+               break;
+
+       case 192:
+
+               for( i = 0;     i <     8; i++, RK += 6 )
+               {
+                       RK[6]  = RK[0] ^ RCON[i] ^
+                                               ( FSb[ (uint8) ( RK[5] >> 16 ) ] <<     24 ) ^
+                                               ( FSb[ (uint8) ( RK[5] >>  8 ) ] <<     16 ) ^
+                                               ( FSb[ (uint8) ( RK[5]           ) ] <<  8 ) ^
+                                               ( FSb[ (uint8) ( RK[5] >> 24 ) ]           );
+
+                       RK[7]  = RK[1] ^ RK[6];
+                       RK[8]  = RK[2] ^ RK[7];
+                       RK[9]  = RK[3] ^ RK[8];
+                       RK[10] = RK[4] ^ RK[9];
+                       RK[11] = RK[5] ^ RK[10];
+               }
+               break;
+
+       case 256:
+
+               for( i = 0;     i <     7; i++, RK += 8 )
+               {
+                       RK[8]  = RK[0] ^ RCON[i] ^
+                                               ( FSb[ (uint8) ( RK[7] >> 16 ) ] <<     24 ) ^
+                                               ( FSb[ (uint8) ( RK[7] >>  8 ) ] <<     16 ) ^
+                                               ( FSb[ (uint8) ( RK[7]           ) ] <<  8 ) ^
+                                               ( FSb[ (uint8) ( RK[7] >> 24 ) ]           );
+
+                       RK[9]  = RK[1] ^ RK[8];
+                       RK[10] = RK[2] ^ RK[9];
+                       RK[11] = RK[3] ^ RK[10];
+
+                       RK[12] = RK[4] ^
+                                               ( FSb[ (uint8) ( RK[11] >> 24 ) ] << 24 ) ^
+                                               ( FSb[ (uint8) ( RK[11] >> 16 ) ] << 16 ) ^
+                                               ( FSb[ (uint8) ( RK[11] >>      8 )     ] <<  8 ) ^
+                                               ( FSb[ (uint8) ( RK[11]           )     ]               );
+
+                       RK[13] = RK[5] ^ RK[12];
+                       RK[14] = RK[6] ^ RK[13];
+                       RK[15] = RK[7] ^ RK[14];
+               }
+               break;
+       }
+
+       /* setup decryption     round keys */
+
+       if(     KT_init )
+       {
+               for( i = 0;     i <     256; i++ )
+               {
+                       KT0[i] = RT0[ FSb[i] ];
+                       KT1[i] = RT1[ FSb[i] ];
+                       KT2[i] = RT2[ FSb[i] ];
+                       KT3[i] = RT3[ FSb[i] ];
+               }
+
+               KT_init = 0;
+       }
+
+       SK = ctx->drk;
+
+       *SK++ = *RK++;
+       *SK++ = *RK++;
+       *SK++ = *RK++;
+       *SK++ = *RK++;
+
+       for( i = 1;     i <     ctx->nr; i++ )
+       {
+               RK -= 8;
+
+               *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
+                               KT1[ (uint8) ( *RK >> 16 ) ] ^
+                               KT2[ (uint8) ( *RK >>  8 ) ] ^
+                               KT3[ (uint8) ( *RK               ) ]; RK++;
+
+               *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
+                               KT1[ (uint8) ( *RK >> 16 ) ] ^
+                               KT2[ (uint8) ( *RK >>  8 ) ] ^
+                               KT3[ (uint8) ( *RK               ) ]; RK++;
+
+               *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
+                               KT1[ (uint8) ( *RK >> 16 ) ] ^
+                               KT2[ (uint8) ( *RK >>  8 ) ] ^
+                               KT3[ (uint8) ( *RK               ) ]; RK++;
+
+               *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
+                               KT1[ (uint8) ( *RK >> 16 ) ] ^
+                               KT2[ (uint8) ( *RK >>  8 ) ] ^
+                               KT3[ (uint8) ( *RK               ) ]; RK++;
+       }
+
+       RK -= 8;
+
+       *SK++ = *RK++;
+       *SK++ = *RK++;
+       *SK++ = *RK++;
+       *SK++ = *RK++;
+
+       return( 0 );
+}
+
+/* AES 128-bit block encryption        routine */
+
+void rtmp_aes_encrypt(aes_context *ctx, uint8 input[16],       uint8 output[16] )
+{
+       uint32 *RK,     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3;
+
+       RK = ctx->erk;
+       GET_UINT32(     X0,     input,  0 ); X0 ^= RK[0];
+       GET_UINT32(     X1,     input,  4 ); X1 ^= RK[1];
+       GET_UINT32(     X2,     input,  8 ); X2 ^= RK[2];
+       GET_UINT32(     X3,     input, 12 ); X3 ^= RK[3];
+
+#define        AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)             \
+{                                                                                              \
+       RK += 4;                                                                        \
+                                                                                               \
+       X0 = RK[0] ^ FT0[ (uint8) (     Y0 >> 24 ) ] ^  \
+                                FT1[ (uint8) ( Y1 >> 16 ) ] ^  \
+                                FT2[ (uint8) ( Y2 >>  8 ) ] ^  \
+                                FT3[ (uint8) ( Y3               ) ];   \
+                                                                                               \
+       X1 = RK[1] ^ FT0[ (uint8) (     Y1 >> 24 ) ] ^  \
+                                FT1[ (uint8) ( Y2 >> 16 ) ] ^  \
+                                FT2[ (uint8) ( Y3 >>  8 ) ] ^  \
+                                FT3[ (uint8) ( Y0               ) ];   \
+                                                                                               \
+       X2 = RK[2] ^ FT0[ (uint8) (     Y2 >> 24 ) ] ^  \
+                                FT1[ (uint8) ( Y3 >> 16 ) ] ^  \
+                                FT2[ (uint8) ( Y0 >>  8 ) ] ^  \
+                                FT3[ (uint8) ( Y1               ) ];   \
+                                                                                               \
+       X3 = RK[3] ^ FT0[ (uint8) (     Y3 >> 24 ) ] ^  \
+                                FT1[ (uint8) ( Y0 >> 16 ) ] ^  \
+                                FT2[ (uint8) ( Y1 >>  8 ) ] ^  \
+                                FT3[ (uint8) ( Y2               ) ];   \
+}
+
+       AES_FROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );           /* round 1 */
+       AES_FROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );           /* round 2 */
+       AES_FROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );           /* round 3 */
+       AES_FROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );           /* round 4 */
+       AES_FROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );           /* round 5 */
+       AES_FROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );           /* round 6 */
+       AES_FROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );           /* round 7 */
+       AES_FROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );           /* round 8 */
+       AES_FROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );           /* round 9 */
+
+       if(     ctx->nr > 10 )
+       {
+               AES_FROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );   /* round 10     */
+               AES_FROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );   /* round 11     */
+       }
+
+       if(     ctx->nr > 12 )
+       {
+               AES_FROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );   /* round 12     */
+               AES_FROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );   /* round 13     */
+       }
+
+       /* last round */
+
+       RK += 4;
+
+       X0 = RK[0] ^ ( FSb[     (uint8) ( Y0 >> 24 ) ] << 24 ) ^
+                                ( FSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^
+                                ( FSb[ (uint8) ( Y2 >>  8 ) ] <<  8 ) ^
+                                ( FSb[ (uint8) ( Y3       ) ]           );
+
+       X1 = RK[1] ^ ( FSb[     (uint8) ( Y1 >> 24 ) ] << 24 ) ^
+                                ( FSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^
+                                ( FSb[ (uint8) ( Y3 >>  8 ) ] <<  8 ) ^
+                                ( FSb[ (uint8) ( Y0       ) ]           );
+
+       X2 = RK[2] ^ ( FSb[     (uint8) ( Y2 >> 24 ) ] << 24 ) ^
+                                ( FSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^
+                                ( FSb[ (uint8) ( Y0 >>  8 ) ] <<  8 ) ^
+                                ( FSb[ (uint8) ( Y1       ) ]           );
+
+       X3 = RK[3] ^ ( FSb[     (uint8) ( Y3 >> 24 ) ] << 24 ) ^
+                                ( FSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^
+                                ( FSb[ (uint8) ( Y1 >>  8 ) ] <<  8 ) ^
+                                ( FSb[ (uint8) ( Y2       ) ]           );
+
+       PUT_UINT32(     X0,     output,  0 );
+       PUT_UINT32(     X1,     output,  4 );
+       PUT_UINT32(     X2,     output,  8 );
+       PUT_UINT32(     X3,     output, 12 );
+}
+
+/* AES 128-bit block decryption        routine */
+
+void rtmp_aes_decrypt( aes_context *ctx,       uint8 input[16], uint8 output[16] )
+{
+       uint32 *RK,     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3;
+
+       RK = ctx->drk;
+
+       GET_UINT32(     X0,     input,  0 ); X0 ^= RK[0];
+       GET_UINT32(     X1,     input,  4 ); X1 ^= RK[1];
+       GET_UINT32(     X2,     input,  8 ); X2 ^= RK[2];
+       GET_UINT32(     X3,     input, 12 ); X3 ^= RK[3];
+
+#define        AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)             \
+{                                                                                              \
+       RK += 4;                                                                        \
+                                                                                               \
+       X0 = RK[0] ^ RT0[ (uint8) (     Y0 >> 24 ) ] ^  \
+                                RT1[ (uint8) ( Y3 >> 16 ) ] ^  \
+                                RT2[ (uint8) ( Y2 >>  8 ) ] ^  \
+                                RT3[ (uint8) ( Y1               ) ];   \
+                                                                                               \
+       X1 = RK[1] ^ RT0[ (uint8) (     Y1 >> 24 ) ] ^  \
+                                RT1[ (uint8) ( Y0 >> 16 ) ] ^  \
+                                RT2[ (uint8) ( Y3 >>  8 ) ] ^  \
+                                RT3[ (uint8) ( Y2               ) ];   \
+                                                                                               \
+       X2 = RK[2] ^ RT0[ (uint8) (     Y2 >> 24 ) ] ^  \
+                                RT1[ (uint8) ( Y1 >> 16 ) ] ^  \
+                                RT2[ (uint8) ( Y0 >>  8 ) ] ^  \
+                                RT3[ (uint8) ( Y3               ) ];   \
+                                                                                               \
+       X3 = RK[3] ^ RT0[ (uint8) (     Y3 >> 24 ) ] ^  \
+                                RT1[ (uint8) ( Y2 >> 16 ) ] ^  \
+                                RT2[ (uint8) ( Y1 >>  8 ) ] ^  \
+                                RT3[ (uint8) ( Y0               ) ];   \
+}
+
+       AES_RROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );           /* round 1 */
+       AES_RROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );           /* round 2 */
+       AES_RROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );           /* round 3 */
+       AES_RROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );           /* round 4 */
+       AES_RROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );           /* round 5 */
+       AES_RROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );           /* round 6 */
+       AES_RROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );           /* round 7 */
+       AES_RROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );           /* round 8 */
+       AES_RROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );           /* round 9 */
+
+       if(     ctx->nr > 10 )
+       {
+               AES_RROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );   /* round 10     */
+               AES_RROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );   /* round 11     */
+       }
+
+       if(     ctx->nr > 12 )
+       {
+               AES_RROUND(     X0,     X1,     X2,     X3,     Y0,     Y1,     Y2,     Y3 );   /* round 12     */
+               AES_RROUND(     Y0,     Y1,     Y2,     Y3,     X0,     X1,     X2,     X3 );   /* round 13     */
+       }
+
+       /* last round */
+
+       RK += 4;
+
+       X0 = RK[0] ^ ( RSb[     (uint8) ( Y0 >> 24 ) ] << 24 ) ^
+                                ( RSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^
+                                ( RSb[ (uint8) ( Y2 >>  8 ) ] <<  8 ) ^
+                                ( RSb[ (uint8) ( Y1       ) ]           );
+
+       X1 = RK[1] ^ ( RSb[     (uint8) ( Y1 >> 24 ) ] << 24 ) ^
+                                ( RSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^
+                                ( RSb[ (uint8) ( Y3 >>  8 ) ] <<  8 ) ^
+                                ( RSb[ (uint8) ( Y2       ) ]           );
+
+       X2 = RK[2] ^ ( RSb[     (uint8) ( Y2 >> 24 ) ] << 24 ) ^
+                                ( RSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^
+                                ( RSb[ (uint8) ( Y0 >>  8 ) ] <<  8 ) ^
+                                ( RSb[ (uint8) ( Y3       ) ]           );
+
+       X3 = RK[3] ^ ( RSb[     (uint8) ( Y3 >> 24 ) ] << 24 ) ^
+                                ( RSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^
+                                ( RSb[ (uint8) ( Y1 >>  8 ) ] <<  8 ) ^
+                                ( RSb[ (uint8) ( Y0       ) ]           );
+
+       PUT_UINT32(     X0,     output,  0 );
+       PUT_UINT32(     X1,     output,  4 );
+       PUT_UINT32(     X2,     output,  8 );
+       PUT_UINT32(     X3,     output, 12 );
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               SHA1 function
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID   HMAC_SHA1(
+       IN      UCHAR   *text,
+       IN      UINT    text_len,
+       IN      UCHAR   *key,
+       IN      UINT    key_len,
+       IN      UCHAR   *digest)
+{
+       SHA_CTX context;
+       UCHAR   k_ipad[65]; /* inner padding - key XORd with ipad       */
+       UCHAR   k_opad[65]; /* outer padding - key XORd with opad       */
+       INT             i;
+
+       // if key is longer     than 64 bytes reset     it to key=SHA1(key)
+       if (key_len     > 64)
+       {
+               SHA_CTX          tctx;
+               SHAInit(&tctx);
+               SHAUpdate(&tctx, key, key_len);
+               SHAFinal(&tctx, key);
+               key_len = 20;
+       }
+       NdisZeroMemory(k_ipad, sizeof(k_ipad));
+       NdisZeroMemory(k_opad, sizeof(k_opad));
+       NdisMoveMemory(k_ipad, key,     key_len);
+       NdisMoveMemory(k_opad, key,     key_len);
+
+       // XOR key with ipad and opad values
+       for     (i = 0; i <     64;     i++)
+       {
+               k_ipad[i] ^= 0x36;
+               k_opad[i] ^= 0x5c;
+       }
+
+       // perform inner SHA1
+       SHAInit(&context);                                              /* init context for 1st pass */
+       SHAUpdate(&context,     k_ipad, 64);            /*      start with inner pad */
+       SHAUpdate(&context,     text, text_len);        /*      then text of datagram */
+       SHAFinal(&context, digest);                             /* finish up 1st pass */
+
+       //perform outer SHA1
+       SHAInit(&context);                                      /* init context for 2nd pass */
+       SHAUpdate(&context,     k_opad, 64);    /*      start with outer pad */
+       SHAUpdate(&context,     digest, 20);    /*      then results of 1st     hash */
+       SHAFinal(&context, digest);                     /* finish up 2nd pass */
+
+}
+
+/*
+* F(P, S, c, i) = U1 xor U2 xor ... Uc
+* U1 = PRF(P, S || Int(i))
+* U2 = PRF(P, U1)
+* Uc = PRF(P, Uc-1)
+*/
+
+void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output)
+{
+    unsigned char digest[36], digest1[SHA_DIGEST_LEN];
+    int i, j;
+
+    /* U1 = PRF(P, S || int(i)) */
+    memcpy(digest, ssid, ssidlength);
+    digest[ssidlength] = (unsigned char)((count>>24) & 0xff);
+    digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff);
+    digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff);
+    digest[ssidlength+3] = (unsigned char)(count & 0xff);
+    HMAC_SHA1(digest, ssidlength+4, (unsigned char*) password, (int) strlen(password), digest1); // for WPA update
+
+    /* output = U1 */
+    memcpy(output, digest1, SHA_DIGEST_LEN);
+
+    for (i = 1; i < iterations; i++)
+    {
+        /* Un = PRF(P, Un-1) */
+        HMAC_SHA1(digest1, SHA_DIGEST_LEN, (unsigned char*) password, (int) strlen(password), digest); // for WPA update
+        memcpy(digest1, digest, SHA_DIGEST_LEN);
+
+        /* output = output xor Un */
+        for (j = 0; j < SHA_DIGEST_LEN; j++)
+        {
+            output[j] ^= digest[j];
+        }
+    }
+}
+/*
+* password - ascii string up to 63 characters in length
+* ssid - octet string up to 32 octets
+* ssidlength - length of ssid in octets
+* output must be 40 octets in length and outputs 256 bits of key
+*/
+int PasswordHash(char *password, unsigned char *ssid, int ssidlength, unsigned char *output)
+{
+    if ((strlen(password) > 63) || (ssidlength > 32))
+        return 0;
+
+    F(password, ssid, ssidlength, 4096, 1, output);
+    F(password, ssid, ssidlength, 4096, 2, &output[SHA_DIGEST_LEN]);
+    return 1;
+}
+
+
diff --git a/drivers/staging/rt2870/common/mlme.c b/drivers/staging/rt2870/common/mlme.c
new file mode 100644 (file)
index 0000000..8a82cee
--- /dev/null
@@ -0,0 +1,8609 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       mlme.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       John Chang      2004-08-25              Modify from RT2500 code base
+       John Chang      2004-09-06              modified for RT2600
+*/
+
+#include "../rt_config.h"
+#include <stdarg.h>
+
+UCHAR  CISCO_OUI[] = {0x00, 0x40, 0x96};
+
+UCHAR  WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
+UCHAR  RSN_OUI[] = {0x00, 0x0f, 0xac};
+UCHAR  WAPI_OUI[] = {0x00, 0x14, 0x72};
+UCHAR   WME_INFO_ELEM[]  = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
+UCHAR   WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
+UCHAR  Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
+UCHAR   RALINK_OUI[]  = {0x00, 0x0c, 0x43};
+UCHAR   BROADCOM_OUI[]  = {0x00, 0x90, 0x4c};
+UCHAR   WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
+#ifdef CONFIG_STA_SUPPORT
+#ifdef DOT11_N_SUPPORT
+UCHAR  PRE_N_HT_OUI[]  = {0x00, 0x90, 0x4c};
+#endif // DOT11_N_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+UCHAR RateSwitchTable[] = {
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x11, 0x00,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x00,  0, 40, 101,
+    0x01, 0x00,  1, 40, 50,
+    0x02, 0x00,  2, 35, 45,
+    0x03, 0x00,  3, 20, 45,
+    0x04, 0x21,  0, 30, 50,
+    0x05, 0x21,  1, 20, 50,
+    0x06, 0x21,  2, 20, 50,
+    0x07, 0x21,  3, 15, 50,
+    0x08, 0x21,  4, 15, 30,
+    0x09, 0x21,  5, 10, 25,
+    0x0a, 0x21,  6,  8, 25,
+    0x0b, 0x21,  7,  8, 25,
+    0x0c, 0x20, 12,  15, 30,
+    0x0d, 0x20, 13,  8, 20,
+    0x0e, 0x20, 14,  8, 20,
+    0x0f, 0x20, 15,  8, 25,
+    0x10, 0x22, 15,  8, 25,
+    0x11, 0x00,  0,  0,  0,
+    0x12, 0x00,  0,  0,  0,
+    0x13, 0x00,  0,  0,  0,
+    0x14, 0x00,  0,  0,  0,
+    0x15, 0x00,  0,  0,  0,
+    0x16, 0x00,  0,  0,  0,
+    0x17, 0x00,  0,  0,  0,
+    0x18, 0x00,  0,  0,  0,
+    0x19, 0x00,  0,  0,  0,
+    0x1a, 0x00,  0,  0,  0,
+    0x1b, 0x00,  0,  0,  0,
+    0x1c, 0x00,  0,  0,  0,
+    0x1d, 0x00,  0,  0,  0,
+    0x1e, 0x00,  0,  0,  0,
+    0x1f, 0x00,  0,  0,  0,
+};
+
+UCHAR RateSwitchTable11B[] = {
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x04, 0x03,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x00,  0, 40, 101,
+    0x01, 0x00,  1, 40, 50,
+    0x02, 0x00,  2, 35, 45,
+    0x03, 0x00,  3, 20, 45,
+};
+
+UCHAR RateSwitchTable11BG[] = {
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x0a, 0x00,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x00,  0, 40, 101,
+    0x01, 0x00,  1, 40, 50,
+    0x02, 0x00,  2, 35, 45,
+    0x03, 0x00,  3, 20, 45,
+    0x04, 0x10,  2, 20, 35,
+    0x05, 0x10,  3, 16, 35,
+    0x06, 0x10,  4, 10, 25,
+    0x07, 0x10,  5, 16, 25,
+    0x08, 0x10,  6, 10, 25,
+    0x09, 0x10,  7, 10, 13,
+};
+
+UCHAR RateSwitchTable11G[] = {
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x08, 0x00,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x10,  0, 20, 101,
+    0x01, 0x10,  1, 20, 35,
+    0x02, 0x10,  2, 20, 35,
+    0x03, 0x10,  3, 16, 35,
+    0x04, 0x10,  4, 10, 25,
+    0x05, 0x10,  5, 16, 25,
+    0x06, 0x10,  6, 10, 25,
+    0x07, 0x10,  7, 10, 13,
+};
+
+#ifdef DOT11_N_SUPPORT
+UCHAR RateSwitchTable11N1S[] = {
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x09, 0x00,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x21,  0, 30, 101,
+    0x01, 0x21,  1, 20, 50,
+    0x02, 0x21,  2, 20, 50,
+    0x03, 0x21,  3, 15, 50,
+    0x04, 0x21,  4, 15, 30,
+    0x05, 0x21,  5, 10, 25,
+    0x06, 0x21,  6,  8, 14,
+    0x07, 0x21,  7,  8, 14,
+    0x08, 0x23,  7,  8, 14,
+};
+
+UCHAR RateSwitchTable11N2S[] = {
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x0a, 0x00,  0,  0,  0,      // Initial used item after association
+    0x00, 0x21,  0, 30, 101,
+    0x01, 0x21,  1, 20, 50,
+    0x02, 0x21,  2, 20, 50,
+    0x03, 0x21,  3, 15, 50,
+    0x04, 0x21,  4, 15, 30,
+    0x05, 0x20, 12,  15, 30,
+    0x06, 0x20, 13,  8, 20,
+    0x07, 0x20, 14,  8, 20,
+    0x08, 0x20, 15,  8, 25,
+    0x09, 0x22, 15,  8, 25,
+};
+
+UCHAR RateSwitchTable11N3S[] = {
+// Item No.    Mode    Curr-MCS        TrainUp TrainDown       // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x0a, 0x00,  0,  0,  0,      // Initial used item after association
+    0x00, 0x21,  0, 30, 101,
+    0x01, 0x21,  1, 20, 50,
+    0x02, 0x21,  2, 20, 50,
+    0x03, 0x21,  3, 15, 50,
+    0x04, 0x21,  4, 15, 30,
+    0x05, 0x20, 12,  15, 30,
+    0x06, 0x20, 13,  8, 20,
+    0x07, 0x20, 14,  8, 20,
+    0x08, 0x20, 15,  8, 25,
+    0x09, 0x22, 15,  8, 25,
+};
+
+UCHAR RateSwitchTable11N2SForABand[] = {
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x0b, 0x09,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x21,  0, 30, 101,
+    0x01, 0x21,  1, 20, 50,
+    0x02, 0x21,  2, 20, 50,
+    0x03, 0x21,  3, 15, 50,
+    0x04, 0x21,  4, 15, 30,
+    0x05, 0x21,  5, 15, 30,
+    0x06, 0x20, 12,  15, 30,
+    0x07, 0x20, 13,  8, 20,
+    0x08, 0x20, 14,  8, 20,
+    0x09, 0x20, 15,  8, 25,
+    0x0a, 0x22, 15,  8, 25,
+};
+
+UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x0b, 0x09,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x21,  0, 30, 101,
+    0x01, 0x21,  1, 20, 50,
+    0x02, 0x21,  2, 20, 50,
+    0x03, 0x21,  3, 15, 50,
+    0x04, 0x21,  4, 15, 30,
+    0x05, 0x21,  5, 15, 30,
+    0x06, 0x20, 12,  15, 30,
+    0x07, 0x20, 13,  8, 20,
+    0x08, 0x20, 14,  8, 20,
+    0x09, 0x20, 15,  8, 25,
+    0x0a, 0x22, 15,  8, 25,
+};
+
+UCHAR RateSwitchTable11BGN1S[] = {
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x0d, 0x00,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x00,  0, 40, 101,
+    0x01, 0x00,  1, 40, 50,
+    0x02, 0x00,  2, 35, 45,
+    0x03, 0x00,  3, 20, 45,
+    0x04, 0x21,  0, 30,101,    //50
+    0x05, 0x21,  1, 20, 50,
+    0x06, 0x21,  2, 20, 50,
+    0x07, 0x21,  3, 15, 50,
+    0x08, 0x21,  4, 15, 30,
+    0x09, 0x21,  5, 10, 25,
+    0x0a, 0x21,  6,  8, 14,
+    0x0b, 0x21,  7,  8, 14,
+       0x0c, 0x23,  7,  8, 14,
+};
+
+UCHAR RateSwitchTable11BGN2S[] = {
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x0a, 0x00,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x21,  0, 30,101,    //50
+    0x01, 0x21,  1, 20, 50,
+    0x02, 0x21,  2, 20, 50,
+    0x03, 0x21,  3, 15, 50,
+    0x04, 0x21,  4, 15, 30,
+    0x05, 0x20, 12, 15, 30,
+    0x06, 0x20, 13,  8, 20,
+    0x07, 0x20, 14,  8, 20,
+    0x08, 0x20, 15,  8, 25,
+    0x09, 0x22, 15,  8, 25,
+};
+
+UCHAR RateSwitchTable11BGN3S[] = { // 3*3
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x0a, 0x00,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x21,  0, 30,101,    //50
+    0x01, 0x21,  1, 20, 50,
+    0x02, 0x21,  2, 20, 50,
+    0x03, 0x21,  3, 20, 50,
+    0x04, 0x21,  4, 15, 50,
+#if 1
+    0x05, 0x20, 20, 15, 30,
+    0x06, 0x20, 21,  8, 20,
+    0x07, 0x20, 22,  8, 20,
+    0x08, 0x20, 23,  8, 25,
+    0x09, 0x22, 23,  8, 25,
+#else // for RT2860 2*3 test
+    0x05, 0x20, 12, 15, 30,
+    0x06, 0x20, 13,  8, 20,
+    0x07, 0x20, 14,  8, 20,
+    0x08, 0x20, 15,  8, 25,
+    0x09, 0x22, 15,  8, 25,
+#endif
+};
+
+UCHAR RateSwitchTable11BGN2SForABand[] = {
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x0b, 0x09,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x21,  0, 30,101,    //50
+    0x01, 0x21,  1, 20, 50,
+    0x02, 0x21,  2, 20, 50,
+    0x03, 0x21,  3, 15, 50,
+    0x04, 0x21,  4, 15, 30,
+    0x05, 0x21,  5, 15, 30,
+    0x06, 0x20, 12, 15, 30,
+    0x07, 0x20, 13,  8, 20,
+    0x08, 0x20, 14,  8, 20,
+    0x09, 0x20, 15,  8, 25,
+    0x0a, 0x22, 15,  8, 25,
+};
+
+UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
+// Item No.   Mode   Curr-MCS   TrainUp   TrainDown            // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+    0x0c, 0x09,  0,  0,  0,                                            // Initial used item after association
+    0x00, 0x21,  0, 30,101,    //50
+    0x01, 0x21,  1, 20, 50,
+    0x02, 0x21,  2, 20, 50,
+    0x03, 0x21,  3, 15, 50,
+    0x04, 0x21,  4, 15, 30,
+    0x05, 0x21,  5, 15, 30,
+    0x06, 0x21, 12, 15, 30,
+    0x07, 0x20, 20, 15, 30,
+    0x08, 0x20, 21,  8, 20,
+    0x09, 0x20, 22,  8, 20,
+    0x0a, 0x20, 23,  8, 25,
+    0x0b, 0x22, 23,  8, 25,
+};
+#endif // DOT11_N_SUPPORT //
+
+PUCHAR ReasonString[] = {
+       /* 0  */         "Reserved",
+       /* 1  */         "Unspecified Reason",
+       /* 2  */         "Previous Auth no longer valid",
+       /* 3  */         "STA is leaving / has left",
+       /* 4  */         "DIS-ASSOC due to inactivity",
+       /* 5  */         "AP unable to hanle all associations",
+       /* 6  */         "class 2 error",
+       /* 7  */         "class 3 error",
+       /* 8  */         "STA is leaving / has left",
+       /* 9  */         "require auth before assoc/re-assoc",
+       /* 10 */         "Reserved",
+       /* 11 */         "Reserved",
+       /* 12 */         "Reserved",
+       /* 13 */         "invalid IE",
+       /* 14 */         "MIC error",
+       /* 15 */         "4-way handshake timeout",
+       /* 16 */         "2-way (group key) handshake timeout",
+       /* 17 */         "4-way handshake IE diff among AssosReq/Rsp/Beacon",
+       /* 18 */
+};
+
+extern UCHAR    OfdmRateToRxwiMCS[];
+// since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
+// otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
+ULONG BasicRateMask[12]                                = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
+                                                                         0xfffff01f /* 6 */     , 0xfffff03f /* 9 */     , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
+                                                                         0xfffff1ff /* 24 */    , 0xfffff3ff /* 36 */    , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
+
+UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1,  0x00, 0x00, 0x00, 0x00, 0x00};
+UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]  = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+// e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
+//             this value, then it's quaranteed capable of operating in 36 mbps TX rate in
+//             clean environment.
+//                                                               TxRate: 1   2   5.5   11       6        9    12       18       24   36   48   54       72  100
+CHAR RssiSafeLevelForTxRate[] ={  -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
+
+UCHAR  RateIdToMbps[]   = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
+USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
+
+UCHAR  SsidIe   = IE_SSID;
+UCHAR  SupRateIe = IE_SUPP_RATES;
+UCHAR  ExtRateIe = IE_EXT_SUPP_RATES;
+#ifdef DOT11_N_SUPPORT
+UCHAR  HtCapIe = IE_HT_CAP;
+UCHAR  AddHtInfoIe = IE_ADD_HT;
+UCHAR  NewExtChanIe = IE_SECONDARY_CH_OFFSET;
+#ifdef DOT11N_DRAFT3
+UCHAR  ExtHtCapIe = IE_EXT_CAPABILITY;
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+UCHAR  ErpIe    = IE_ERP;
+UCHAR  DsIe     = IE_DS_PARM;
+UCHAR  TimIe    = IE_TIM;
+UCHAR  WpaIe    = IE_WPA;
+UCHAR  Wpa2Ie   = IE_WPA2;
+UCHAR  IbssIe   = IE_IBSS_PARM;
+UCHAR  Ccx2Ie   = IE_CCX_V2;
+UCHAR  WapiIe   = IE_WAPI;
+
+extern UCHAR   WPA_OUI[];
+
+UCHAR  SES_OUI[] = {0x00, 0x90, 0x4c};
+
+UCHAR  ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+
+// Reset the RFIC setting to new series
+RTMP_RF_REGS RF2850RegTable[] = {
+//             ch       R1              R2              R3(TX0~4=0) R4
+               {1,  0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
+               {2,  0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
+               {3,  0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
+               {4,  0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
+               {5,  0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
+               {6,  0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
+               {7,  0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
+               {8,  0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
+               {9,  0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
+               {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
+               {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
+               {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
+               {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
+               {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
+
+               // 802.11 UNI / HyperLan 2
+               {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
+               {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
+               {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
+               {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
+               {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
+               {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
+               {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
+               {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
+               {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
+               {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
+               {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
+               {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
+
+               // 802.11 HyperLan 2
+               {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
+
+               // 2008.04.30 modified
+               // The system team has AN to improve the EVM value
+               // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
+               {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
+               {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
+               {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
+
+               {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
+               {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
+               {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
+               {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
+               {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
+               {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
+               {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
+               {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
+               {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
+               {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
+               {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
+               {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
+
+               // 802.11 UNII
+               {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
+               {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
+               {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
+               {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
+               {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
+               {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
+               {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
+
+               // Japan
+               {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
+               {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
+               {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
+               {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
+               {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
+               {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
+               {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
+
+               // still lack of MMAC(Japan) ch 34,38,42,46
+};
+UCHAR  NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
+
+FREQUENCY_ITEM FreqItems3020[] =
+{
+       /**************************************************/
+       // ISM : 2.4 to 2.483 GHz                         //
+       /**************************************************/
+       // 11g
+       /**************************************************/
+       //-CH---N-------R---K-----------
+       {1,    241,  2,  2},
+       {2,    241,      2,  7},
+       {3,    242,      2,  2},
+       {4,    242,      2,  7},
+       {5,    243,      2,  2},
+       {6,    243,      2,  7},
+       {7,    244,      2,  2},
+       {8,    244,      2,  7},
+       {9,    245,      2,  2},
+       {10,   245,      2,  7},
+       {11,   246,      2,  2},
+       {12,   246,      2,  7},
+       {13,   247,      2,  2},
+       {14,   248,      2,  4},
+};
+#define        NUM_OF_3020_CHNL        (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
+
+/*
+       ==========================================================================
+       Description:
+               initialize the MLME task and its data structure (queue, spinlock,
+               timer, state machines).
+
+       IRQL = PASSIVE_LEVEL
+
+       Return:
+               always return NDIS_STATUS_SUCCESS
+
+       ==========================================================================
+*/
+NDIS_STATUS MlmeInit(
+       IN PRTMP_ADAPTER pAd)
+{
+       NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
+
+       do
+       {
+               Status = MlmeQueueInit(&pAd->Mlme.Queue);
+               if(Status != NDIS_STATUS_SUCCESS)
+                       break;
+
+               pAd->Mlme.bRunning = FALSE;
+               NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       BssTableInit(&pAd->ScanTab);
+
+                       // init STA state machines
+                       AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
+                       AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
+                       AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
+                       SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
+                       WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
+                       AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
+
+#ifdef QOS_DLS_SUPPORT
+                       DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc);
+#endif // QOS_DLS_SUPPORT //
+
+
+                       // Since we are using switch/case to implement it, the init is different from the above
+                       // state machine init
+                       MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+
+
+               ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
+
+               // Init mlme periodic timer
+               RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
+
+               // Set mlme periodic timer
+               RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
+
+               // software-based RX Antenna diversity
+               RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
+
+       } while (FALSE);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
+
+       return Status;
+}
+
+/*
+       ==========================================================================
+       Description:
+               main loop of the MLME
+       Pre:
+               Mlme has to be initialized, and there are something inside the queue
+       Note:
+               This function is invoked from MPSetInformation and MPReceive;
+               This task guarantee only one MlmeHandler will run.
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID MlmeHandler(
+       IN PRTMP_ADAPTER pAd)
+{
+       MLME_QUEUE_ELEM            *Elem = NULL;
+#ifdef APCLI_SUPPORT
+       SHORT apcliIfIndex;
+#endif
+
+       // Only accept MLME and Frame from peer side, no other (control/data) frame should
+       // get into this state machine
+
+       NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
+       if(pAd->Mlme.bRunning)
+       {
+               NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+               return;
+       }
+       else
+       {
+               pAd->Mlme.bRunning = TRUE;
+       }
+       NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+
+       while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
+       {
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
+                       RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
+                       RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
+                       break;
+               }
+
+#ifdef RALINK_ATE
+               if(ATE_ON(pAd))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n"));
+                       break;
+               }
+#endif // RALINK_ATE //
+
+               //From message type, determine which state machine I should drive
+               if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
+               {
+#ifdef RT2870
+                       if (Elem->MsgType == MT2_RESET_CONF)
+                       {
+                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
+                               MlmeRestartStateMachine(pAd);
+                               Elem->Occupied = FALSE;
+                               Elem->MsgLen = 0;
+                               continue;
+                       }
+#endif // RT2870 //
+
+                       // if dequeue success
+                       switch (Elem->Machine)
+                       {
+                               // STA state machines
+#ifdef CONFIG_STA_SUPPORT
+                               case ASSOC_STATE_MACHINE:
+                                       StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
+                                       break;
+                               case AUTH_STATE_MACHINE:
+                                       StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
+                                       break;
+                               case AUTH_RSP_STATE_MACHINE:
+                                       StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
+                                       break;
+                               case SYNC_STATE_MACHINE:
+                                       StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
+                                       break;
+                               case MLME_CNTL_STATE_MACHINE:
+                                       MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
+                                       break;
+                               case WPA_PSK_STATE_MACHINE:
+                                       StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
+                                       break;
+#ifdef LEAP_SUPPORT
+                               case LEAP_STATE_MACHINE:
+                                       LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
+                                       break;
+#endif
+                               case AIRONET_STATE_MACHINE:
+                                       StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
+                                       break;
+
+#ifdef QOS_DLS_SUPPORT
+                               case DLS_STATE_MACHINE:
+                                       StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem);
+                                       break;
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+                               case ACTION_STATE_MACHINE:
+                                       StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
+                                       break;
+
+
+
+
+                               default:
+                                       DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
+                                       break;
+                       } // end of switch
+
+                       // free MLME element
+                       Elem->Occupied = FALSE;
+                       Elem->MsgLen = 0;
+
+               }
+               else {
+                       DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
+               }
+       }
+
+       NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
+       pAd->Mlme.bRunning = FALSE;
+       NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+}
+
+/*
+       ==========================================================================
+       Description:
+               Destructor of MLME (Destroy queue, state machine, spin lock and timer)
+       Parameters:
+               Adapter - NIC Adapter pointer
+       Post:
+               The MLME task will no longer work properly
+
+       IRQL = PASSIVE_LEVEL
+
+       ==========================================================================
+ */
+VOID MlmeHalt(
+       IN PRTMP_ADAPTER pAd)
+{
+       BOOLEAN           Cancelled;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
+
+       if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+       {
+               // disable BEACON generation and other BEACON related hardware timers
+               AsicDisableSync(pAd);
+       }
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+#ifdef QOS_DLS_SUPPORT
+               UCHAR           i;
+#endif // QOS_DLS_SUPPORT //
+               // Cancel pending timers
+               RTMPCancelTimer(&pAd->MlmeAux.AssocTimer,               &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer,             &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer,    &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.AuthTimer,                &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer,              &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.ScanTimer,                &Cancelled);
+
+#ifdef QOS_DLS_SUPPORT
+               for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
+               {
+                       RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
+               }
+#endif // QOS_DLS_SUPPORT //
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       RTMPCancelTimer(&pAd->Mlme.PeriodicTimer,               &Cancelled);
+       RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer,              &Cancelled);
+
+
+
+       if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+       {
+               // Set LED
+               RTMPSetLED(pAd, LED_HALT);
+        RTMPSetSignalLED(pAd, -100);   // Force signal strength Led to be turned off, firmware is not done it.
+#ifdef RT2870
+        {
+            LED_CFG_STRUC LedCfg;
+            RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
+            LedCfg.field.LedPolar = 0;
+            LedCfg.field.RLedMode = 0;
+            LedCfg.field.GLedMode = 0;
+            LedCfg.field.YLedMode = 0;
+            RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
+        }
+#endif // RT2870 //
+       }
+
+       RTMPusecDelay(5000);    //  5 msec to gurantee Ant Diversity timer canceled
+
+       MlmeQueueDestroy(&pAd->Mlme.Queue);
+       NdisFreeSpinLock(&pAd->Mlme.TaskLock);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
+}
+
+VOID MlmeResetRalinkCounters(
+       IN  PRTMP_ADAPTER   pAd)
+{
+       pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
+       // clear all OneSecxxx counters.
+       pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
+       pAd->RalinkCounters.OneSecFalseCCACnt = 0;
+       pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
+       pAd->RalinkCounters.OneSecRxOkCnt = 0;
+       pAd->RalinkCounters.OneSecTxFailCount = 0;
+       pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
+       pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
+       pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
+
+       // TODO: for debug only. to be removed
+       pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
+       pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
+       pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
+       pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
+       pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
+       pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
+       pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
+       pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
+       pAd->RalinkCounters.OneSecTxDoneCount = 0;
+       pAd->RalinkCounters.OneSecRxCount = 0;
+       pAd->RalinkCounters.OneSecTxAggregationCount = 0;
+       pAd->RalinkCounters.OneSecRxAggregationCount = 0;
+
+       return;
+}
+
+unsigned long rx_AMSDU;
+unsigned long rx_Total;
+
+/*
+       ==========================================================================
+       Description:
+               This routine is executed periodically to -
+               1. Decide if it's a right time to turn on PwrMgmt bit of all
+                  outgoiing frames
+               2. Calculate ChannelQuality based on statistics of the last
+                  period, so that TX rate won't toggling very frequently between a
+                  successful TX and a failed TX.
+               3. If the calculated ChannelQuality indicated current connection not
+                  healthy, then a ROAMing attempt is tried here.
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+#define ADHOC_BEACON_LOST_TIME         (8*OS_HZ)  // 8 sec
+VOID MlmePeriodicExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3)
+{
+       ULONG                   TxTotalCnt;
+       PRTMP_ADAPTER   pAd = (RTMP_ADAPTER *)FunctionContext;
+
+       // Do nothing if the driver is starting halt state.
+       // This might happen when timer already been fired before cancel timer with mlmehalt
+       if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_RADIO_OFF |
+                                                               fRTMP_ADAPTER_RADIO_MEASUREMENT |
+                                                               fRTMP_ADAPTER_RESET_IN_PROGRESS))))
+               return;
+
+       RT28XX_MLME_PRE_SANITY_CHECK(pAd);
+
+#ifdef RALINK_ATE
+       /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */
+       if (ATE_ON(pAd))
+       {
+               if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1))
+       {
+                       pAd->Mlme.PeriodicRound ++;
+                       return;
+               }
+       }
+#endif // RALINK_ATE //
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // Do nothing if monitor mode is on
+               if (MONITOR_ON(pAd))
+                       return;
+
+               if (pAd->Mlme.PeriodicRound & 0x1)
+               {
+                       // This is the fix for wifi 11n extension channel overlapping test case.  for 2860D
+                       if (((pAd->MACVersion & 0xffff) == 0x0101) &&
+                               (STA_TGN_WIFI_ON(pAd)) &&
+                               (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
+
+                               {
+                                       RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
+                                       pAd->CommonCfg.IOTestParm.bToggle = TRUE;
+                               }
+                               else if ((STA_TGN_WIFI_ON(pAd)) &&
+                                               ((pAd->MACVersion & 0xffff) == 0x0101))
+                               {
+                                       RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
+                                       pAd->CommonCfg.IOTestParm.bToggle = FALSE;
+                               }
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       pAd->bUpdateBcnCntDone = FALSE;
+
+//     RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
+       pAd->Mlme.PeriodicRound ++;
+
+       // execute every 500ms
+       if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
+       {
+#ifdef CONFIG_STA_SUPPORT
+               // perform dynamic tx rate switching based on past TX history
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
+                                       )
+                               && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
+                               MlmeDynamicTxRateSwitching(pAd);
+               }
+#endif // CONFIG_STA_SUPPORT //
+       }
+
+       // Normal 1 second Mlme PeriodicExec.
+       if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
+       {
+                pAd->Mlme.OneSecPeriodicRound ++;
+
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+       {
+                       /* request from Baron : move this routine from later to here */
+                       /* for showing Rx error count in ATE RXFRAME */
+            NICUpdateRawCounters(pAd);
+                       if (pAd->ate.bRxFer == 1)
+                       {
+                               pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec;
+                           ate_print(KERN_EMERG "MlmePeriodicExec: Rx packet cnt = %d/%d\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt);
+                               pAd->ate.RxCntPerSec = 0;
+
+                               if (pAd->ate.RxAntennaSel == 0)
+                                       ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n",
+                                               pAd->ate.AvgRssi0, pAd->ate.AvgRssi1, pAd->ate.AvgRssi2);
+                               else
+                                       ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0);
+                       }
+                       MlmeResetRalinkCounters(pAd);
+                       return;
+       }
+#endif // RALINK_ATE //
+
+
+               if (rx_Total)
+               {
+
+                       // reset counters
+                       rx_AMSDU = 0;
+                       rx_Total = 0;
+               }
+
+               //ORIBATimerTimeout(pAd);
+
+               // Media status changed, report to NDIS
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
+               {
+                       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
+                       if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+                       {
+                               pAd->IndicateMediaState = NdisMediaStateConnected;
+                               RTMP_IndicateMediaState(pAd);
+
+                       }
+                       else
+                       {
+                               pAd->IndicateMediaState = NdisMediaStateDisconnected;
+                               RTMP_IndicateMediaState(pAd);
+                       }
+               }
+
+               NdisGetSystemUpTime(&pAd->Mlme.Now32);
+
+               // add the most up-to-date h/w raw counters into software variable, so that
+               // the dynamic tuning mechanism below are based on most up-to-date information
+               NICUpdateRawCounters(pAd);
+
+#ifdef RT2870
+               RT2870_WatchDog(pAd);
+#endif // RT2870 //
+
+#ifdef DOT11_N_SUPPORT
+               // Need statistics after read counter. So put after NICUpdateRawCounters
+               ORIBATimerTimeout(pAd);
+#endif // DOT11_N_SUPPORT //
+
+               // if MGMT RING is full more than twice within 1 second, we consider there's
+               // a hardware problem stucking the TX path. In this case, try a hardware reset
+               // to recover the system
+       //      if (pAd->RalinkCounters.MgmtRingFullCount >= 2)
+       //              RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR);
+       //      else
+       //              pAd->RalinkCounters.MgmtRingFullCount = 0;
+
+               // The time period for checking antenna is according to traffic
+               if (pAd->Mlme.bEnableAutoAntennaCheck)
+               {
+                       TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
+                                                        pAd->RalinkCounters.OneSecTxRetryOkCount +
+                                                        pAd->RalinkCounters.OneSecTxFailCount;
+
+                       if (TxTotalCnt > 50)
+                       {
+                               if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
+                               {
+                                       AsicEvaluateRxAnt(pAd);
+                               }
+                       }
+                       else
+                       {
+                               if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
+                               {
+                                       AsicEvaluateRxAnt(pAd);
+                               }
+                       }
+               }
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       STAMlmePeriodicExec(pAd);
+#endif // CONFIG_STA_SUPPORT //
+
+               MlmeResetRalinkCounters(pAd);
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       {
+                               // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
+                               // and sending CTS-to-self over and over.
+                               // Software Patch Solution:
+                               // 1. Polling debug state register 0x10F4 every one second.
+                               // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
+                               // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
+
+                               UINT32  MacReg = 0;
+
+                               RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
+                               if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
+                               {
+                                       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
+                                       RTMPusecDelay(1);
+                                       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
+
+                                       DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
+                               }
+                       }
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+               RT28XX_MLME_HANDLER(pAd);
+       }
+
+
+       pAd->bUpdateBcnCntDone = FALSE;
+}
+
+#ifdef CONFIG_STA_SUPPORT
+VOID STAMlmePeriodicExec(
+       PRTMP_ADAPTER pAd)
+{
+       ULONG   TxTotalCnt;
+       int     i;
+
+//
+// We return here in ATE mode, because the statistics
+// that ATE needs are not collected via this routine.
+//
+#ifdef RALINK_ATE
+       // It is supposed that we will never reach here in ATE mode.
+       ASSERT(!(ATE_ON(pAd)));
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+    if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
+#endif // WPA_SUPPLICANT_SUPPORT //
+    {
+       // WPA MIC error should block association attempt for 60 seconds
+       if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
+               pAd->StaCfg.bBlockAssoc = FALSE;
+    }
+
+    if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
+       {
+               if (pAd->IndicateMediaState == NdisMediaStateConnected)
+               {
+                       RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+               }
+               pAd->PreMediaState = pAd->IndicateMediaState;
+       }
+
+
+
+
+       AsicStaBbpTuning(pAd);
+
+       TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
+                                        pAd->RalinkCounters.OneSecTxRetryOkCount +
+                                        pAd->RalinkCounters.OneSecTxFailCount;
+
+       if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+       {
+               // update channel quality for Roaming and UI LinkQuality display
+               MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
+       }
+
+       // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
+       // Radio is currently in noisy environment
+       if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+               AsicAdjustTxPower(pAd);
+
+       if (INFRA_ON(pAd))
+       {
+#ifdef QOS_DLS_SUPPORT
+               // Check DLS time out, then tear down those session
+               RTMPCheckDLSTimeOut(pAd);
+#endif // QOS_DLS_SUPPORT //
+
+               // Is PSM bit consistent with user power management policy?
+               // This is the only place that will set PSM bit ON.
+               if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+               MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
+
+               pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
+
+               if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
+                       ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
+               {
+                       RTMPSetAGCInitValue(pAd, BW_20);
+                       DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
+               }
+
+        //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
+        //    (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
+        {
+               if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
+               {
+                   // When APSD is enabled, the period changes as 20 sec
+                       if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
+                               RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
+               }
+               else
+               {
+                   // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
+                       if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
+                {
+                    if (pAd->CommonCfg.bWmmCapable)
+                                       RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
+                    else
+                                               RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
+                }
+               }
+        }
+
+               if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
+                       {
+                       DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
+                       pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
+                       pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
+
+                       // Lost AP, send disconnect & link down event
+                       LinkDown(pAd, FALSE);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+            if (pAd->StaCfg.WpaSupplicantUP)
+                       {
+                union iwreq_data    wrqu;
+                //send disassociate event to wpa_supplicant
+                memset(&wrqu, 0, sizeof(wrqu));
+                wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
+                wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+            }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+            {
+                union iwreq_data    wrqu;
+                memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+                wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+            }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+                       // RTMPPatchMacBbpBug(pAd);
+                       MlmeAutoReconnectLastSSID(pAd);
+               }
+               else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
+               {
+                       pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
+                       DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
+                       MlmeAutoReconnectLastSSID(pAd);
+               }
+
+               // Add auto seamless roaming
+               if (pAd->StaCfg.bFastRoaming)
+               {
+                       SHORT   dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam));
+
+                       if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
+                       {
+                               MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
+                       }
+               }
+       }
+       else if (ADHOC_ON(pAd))
+       {
+               //radar detect
+               if ((pAd->CommonCfg.Channel > 14)
+                       && (pAd->CommonCfg.bIEEE80211H == 1)
+                       && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
+               {
+                       RadarDetectPeriodic(pAd);
+               }
+
+               // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
+               // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
+               // join later.
+               if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
+                       OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+               {
+                       MLME_START_REQ_STRUCT     StartReq;
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
+                       LinkDown(pAd, FALSE);
+
+                       StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+                       MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
+               }
+
+               for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
+               {
+                       MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
+
+                       if (pEntry->ValidAsCLI == FALSE)
+                               continue;
+
+                       if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
+                               MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
+               }
+       }
+       else // no INFRA nor ADHOC connection
+       {
+
+               if (pAd->StaCfg.bScanReqIsFromWebUI &&
+            ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
+                       goto SKIP_AUTO_SCAN_CONN;
+        else
+            pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
+
+               if ((pAd->StaCfg.bAutoReconnect == TRUE)
+                       && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
+                       && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
+               {
+                       if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
+                       {
+                               MLME_SCAN_REQ_STRUCT       ScanReq;
+
+                               if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
+                                       ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
+                                       MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+                                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+                                       // Reset Missed scan number
+                                       pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
+                               }
+                               else if (pAd->StaCfg.BssType == BSS_ADHOC)      // Quit the forever scan when in a very clean room
+                                       MlmeAutoReconnectLastSSID(pAd);
+                       }
+                       else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
+                       {
+                               if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
+                               {
+                                       MlmeAutoScan(pAd);
+                                       pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
+                               }
+                               else
+                               {
+#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+                                       if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+                                       {
+                                               if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1)
+                                                       MlmeAutoReconnectLastSSID(pAd);
+                                       }
+                                       else
+#endif // CARRIER_DETECTION_SUPPORT //
+                                               MlmeAutoReconnectLastSSID(pAd);
+                               }
+                       }
+               }
+       }
+
+SKIP_AUTO_SCAN_CONN:
+
+#ifdef DOT11_N_SUPPORT
+    if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
+       {
+               pAd->MacTab.fAnyBASession = TRUE;
+               AsicUpdateProtect(pAd, HT_FORCERTSCTS,  ALLN_SETPROTECT, FALSE, FALSE);
+       }
+       else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
+       {
+               pAd->MacTab.fAnyBASession = FALSE;
+               AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode,  ALLN_SETPROTECT, FALSE, FALSE);
+       }
+#endif // DOT11_N_SUPPORT //
+
+
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+       if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
+               TriEventCounterMaintenance(pAd);
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+       return;
+}
+
+// Link down report
+VOID LinkDownExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3)
+{
+
+       RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+       pAd->IndicateMediaState = NdisMediaStateDisconnected;
+       RTMP_IndicateMediaState(pAd);
+    pAd->ExtraInfo = GENERAL_LINK_DOWN;
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID MlmeAutoScan(
+       IN PRTMP_ADAPTER pAd)
+{
+       // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
+       if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
+               MlmeEnqueue(pAd,
+                                       MLME_CNTL_STATE_MACHINE,
+                                       OID_802_11_BSSID_LIST_SCAN,
+                                       0,
+                                       NULL);
+               RT28XX_MLME_HANDLER(pAd);
+       }
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID MlmeAutoReconnectLastSSID(
+       IN PRTMP_ADAPTER pAd)
+{
+
+
+       // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
+       if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
+               (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
+       {
+               NDIS_802_11_SSID OidSsid;
+               OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
+               NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
+
+               DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
+               MlmeEnqueue(pAd,
+                                       MLME_CNTL_STATE_MACHINE,
+                                       OID_802_11_SSID,
+                                       sizeof(NDIS_802_11_SSID),
+                                       &OidSsid);
+               RT28XX_MLME_HANDLER(pAd);
+       }
+}
+#endif // CONFIG_STA_SUPPORT //
+
+/*
+       ==========================================================================
+       Validate SSID for connection try and rescan purpose
+       Valid SSID will have visible chars only.
+       The valid length is from 0 to 32.
+       IRQL = DISPATCH_LEVEL
+       ==========================================================================
+ */
+BOOLEAN MlmeValidateSSID(
+       IN PUCHAR       pSsid,
+       IN UCHAR        SsidLen)
+{
+       int     index;
+
+       if (SsidLen > MAX_LEN_OF_SSID)
+               return (FALSE);
+
+       // Check each character value
+       for (index = 0; index < SsidLen; index++)
+       {
+               if (pSsid[index] < 0x20)
+                       return (FALSE);
+       }
+
+       // All checked
+       return (TRUE);
+}
+
+VOID MlmeSelectTxRateTable(
+       IN PRTMP_ADAPTER                pAd,
+       IN PMAC_TABLE_ENTRY             pEntry,
+       IN PUCHAR                               *ppTable,
+       IN PUCHAR                               pTableSize,
+       IN PUCHAR                               pInitTxRateIdx)
+{
+       do
+       {
+               // decide the rate table for tuning
+               if (pAd->CommonCfg.TxRateTableSize > 0)
+               {
+                       *ppTable = RateSwitchTable;
+                       *pTableSize = RateSwitchTable[0];
+                       *pInitTxRateIdx = RateSwitchTable[1];
+
+                       break;
+               }
+
+#ifdef CONFIG_STA_SUPPORT
+               if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
+               {
+#ifdef DOT11_N_SUPPORT
+                       if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
+                               (pEntry->HTCapability.MCSSet[0] == 0xff) &&
+                               ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
+                       {// 11N 1S Adhoc
+                               *ppTable = RateSwitchTable11N1S;
+                               *pTableSize = RateSwitchTable11N1S[0];
+                               *pInitTxRateIdx = RateSwitchTable11N1S[1];
+
+                       }
+                       else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
+                                       (pEntry->HTCapability.MCSSet[0] == 0xff) &&
+                                       (pEntry->HTCapability.MCSSet[1] == 0xff) &&
+                                       (pAd->Antenna.field.TxPath == 2))
+                       {// 11N 2S Adhoc
+                               if (pAd->LatchRfRegs.Channel <= 14)
+                               {
+                                       *ppTable = RateSwitchTable11N2S;
+                                       *pTableSize = RateSwitchTable11N2S[0];
+                                       *pInitTxRateIdx = RateSwitchTable11N2S[1];
+                               }
+                               else
+                               {
+                                       *ppTable = RateSwitchTable11N2SForABand;
+                                       *pTableSize = RateSwitchTable11N2SForABand[0];
+                                       *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
+                               }
+
+                       }
+                       else
+#endif // DOT11_N_SUPPORT //
+                               if ((pEntry->RateLen == 4)
+#ifdef DOT11_N_SUPPORT
+                                       && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
+#endif // DOT11_N_SUPPORT //
+                                       )
+                       {
+                               *ppTable = RateSwitchTable11B;
+                               *pTableSize = RateSwitchTable11B[0];
+                               *pInitTxRateIdx = RateSwitchTable11B[1];
+
+                       }
+                       else if (pAd->LatchRfRegs.Channel <= 14)
+                       {
+                               *ppTable = RateSwitchTable11BG;
+                               *pTableSize = RateSwitchTable11BG[0];
+                               *pInitTxRateIdx = RateSwitchTable11BG[1];
+
+                       }
+                       else
+                       {
+                               *ppTable = RateSwitchTable11G;
+                               *pTableSize = RateSwitchTable11G[0];
+                               *pInitTxRateIdx = RateSwitchTable11G[1];
+
+                       }
+                       break;
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+               //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
+               //      ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
+               if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
+                       ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
+               {// 11BGN 1S AP
+                       *ppTable = RateSwitchTable11BGN1S;
+                       *pTableSize = RateSwitchTable11BGN1S[0];
+                       *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
+
+                       break;
+               }
+
+               //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
+               //      (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
+               if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
+                       (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
+               {// 11BGN 2S AP
+                       if (pAd->LatchRfRegs.Channel <= 14)
+                       {
+                               *ppTable = RateSwitchTable11BGN2S;
+                               *pTableSize = RateSwitchTable11BGN2S[0];
+                               *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
+
+                       }
+                       else
+                       {
+                               *ppTable = RateSwitchTable11BGN2SForABand;
+                               *pTableSize = RateSwitchTable11BGN2SForABand[0];
+                               *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
+
+                       }
+                       break;
+               }
+
+               //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
+               if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
+               {// 11N 1S AP
+                       *ppTable = RateSwitchTable11N1S;
+                       *pTableSize = RateSwitchTable11N1S[0];
+                       *pInitTxRateIdx = RateSwitchTable11N1S[1];
+
+                       break;
+               }
+
+               //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
+               if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
+               {// 11N 2S AP
+                       if (pAd->LatchRfRegs.Channel <= 14)
+                       {
+                       *ppTable = RateSwitchTable11N2S;
+                       *pTableSize = RateSwitchTable11N2S[0];
+                       *pInitTxRateIdx = RateSwitchTable11N2S[1];
+            }
+                       else
+                       {
+                               *ppTable = RateSwitchTable11N2SForABand;
+                               *pTableSize = RateSwitchTable11N2SForABand[0];
+                               *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
+                       }
+
+                       break;
+               }
+#endif // DOT11_N_SUPPORT //
+               //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
+               if ((pEntry->RateLen == 4)
+#ifdef DOT11_N_SUPPORT
+                       && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
+#endif // DOT11_N_SUPPORT //
+                       )
+               {// B only AP
+                       *ppTable = RateSwitchTable11B;
+                       *pTableSize = RateSwitchTable11B[0];
+                       *pInitTxRateIdx = RateSwitchTable11B[1];
+
+                       break;
+               }
+
+               //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
+               if ((pEntry->RateLen > 8)
+#ifdef DOT11_N_SUPPORT
+                       && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
+#endif // DOT11_N_SUPPORT //
+                       )
+               {// B/G  mixed AP
+                       *ppTable = RateSwitchTable11BG;
+                       *pTableSize = RateSwitchTable11BG[0];
+                       *pInitTxRateIdx = RateSwitchTable11BG[1];
+
+                       break;
+               }
+
+               //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
+               if ((pEntry->RateLen == 8)
+#ifdef DOT11_N_SUPPORT
+                       && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
+#endif // DOT11_N_SUPPORT //
+                       )
+               {// G only AP
+                       *ppTable = RateSwitchTable11G;
+                       *pTableSize = RateSwitchTable11G[0];
+                       *pInitTxRateIdx = RateSwitchTable11G[1];
+
+                       break;
+               }
+#ifdef DOT11_N_SUPPORT
+#endif // DOT11_N_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+#ifdef DOT11_N_SUPPORT
+                       //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
+                       if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
+#endif // DOT11_N_SUPPORT //
+                       {       // Legacy mode
+                               if (pAd->CommonCfg.MaxTxRate <= RATE_11)
+                               {
+                                       *ppTable = RateSwitchTable11B;
+                                       *pTableSize = RateSwitchTable11B[0];
+                                       *pInitTxRateIdx = RateSwitchTable11B[1];
+                               }
+                               else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
+                               {
+                                       *ppTable = RateSwitchTable11G;
+                                       *pTableSize = RateSwitchTable11G[0];
+                                       *pInitTxRateIdx = RateSwitchTable11G[1];
+
+                               }
+                               else
+                               {
+                                       *ppTable = RateSwitchTable11BG;
+                                       *pTableSize = RateSwitchTable11BG[0];
+                                       *pInitTxRateIdx = RateSwitchTable11BG[1];
+                               }
+                               break;
+                       }
+#ifdef DOT11_N_SUPPORT
+                       if (pAd->LatchRfRegs.Channel <= 14)
+                       {
+                               if (pAd->CommonCfg.TxStream == 1)
+                               {
+                                       *ppTable = RateSwitchTable11N1S;
+                                       *pTableSize = RateSwitchTable11N1S[0];
+                                       *pInitTxRateIdx = RateSwitchTable11N1S[1];
+                                       DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
+                               }
+                               else
+                               {
+                                       *ppTable = RateSwitchTable11N2S;
+                                       *pTableSize = RateSwitchTable11N2S[0];
+                                       *pInitTxRateIdx = RateSwitchTable11N2S[1];
+                                       DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
+                               }
+                       }
+                       else
+                       {
+                               if (pAd->CommonCfg.TxStream == 1)
+                               {
+                                       *ppTable = RateSwitchTable11N1S;
+                                       *pTableSize = RateSwitchTable11N1S[0];
+                                       *pInitTxRateIdx = RateSwitchTable11N1S[1];
+                                       DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
+                               }
+                               else
+                               {
+                                       *ppTable = RateSwitchTable11N2SForABand;
+                                       *pTableSize = RateSwitchTable11N2SForABand[0];
+                                       *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
+                                       DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
+                               }
+                       }
+#endif // DOT11_N_SUPPORT //
+                       DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
+                               pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
+               }
+#endif // CONFIG_STA_SUPPORT //
+       } while(FALSE);
+}
+
+#ifdef CONFIG_STA_SUPPORT
+/*
+       ==========================================================================
+       Description:
+               This routine checks if there're other APs out there capable for
+               roaming. Caller should call this routine only when Link up in INFRA mode
+               and channel quality is below CQI_GOOD_THRESHOLD.
+
+       IRQL = DISPATCH_LEVEL
+
+       Output:
+       ==========================================================================
+ */
+VOID MlmeCheckForRoaming(
+       IN PRTMP_ADAPTER pAd,
+       IN ULONG        Now32)
+{
+       USHORT     i;
+       BSS_TABLE  *pRoamTab = &pAd->MlmeAux.RoamTab;
+       BSS_ENTRY  *pBss;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
+       // put all roaming candidates into RoamTab, and sort in RSSI order
+       BssTableInit(pRoamTab);
+       for (i = 0; i < pAd->ScanTab.BssNr; i++)
+       {
+               pBss = &pAd->ScanTab.BssEntry[i];
+
+               if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
+                       continue;        // AP disappear
+               if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
+                       continue;        // RSSI too weak. forget it.
+               if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
+                       continue;        // skip current AP
+               if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
+                       continue;        // only AP with stronger RSSI is eligible for roaming
+
+               // AP passing all above rules is put into roaming candidate table
+               NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
+               pRoamTab->BssNr += 1;
+       }
+
+       if (pRoamTab->BssNr > 0)
+       {
+               // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
+               if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
+               {
+                       pAd->RalinkCounters.PoorCQIRoamingCount ++;
+                       DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
+                       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
+                       RT28XX_MLME_HANDLER(pAd);
+               }
+       }
+       DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
+}
+
+/*
+       ==========================================================================
+       Description:
+               This routine checks if there're other APs out there capable for
+               roaming. Caller should call this routine only when link up in INFRA mode
+               and channel quality is below CQI_GOOD_THRESHOLD.
+
+       IRQL = DISPATCH_LEVEL
+
+       Output:
+       ==========================================================================
+ */
+VOID MlmeCheckForFastRoaming(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      ULONG                   Now)
+{
+       USHORT          i;
+       BSS_TABLE       *pRoamTab = &pAd->MlmeAux.RoamTab;
+       BSS_ENTRY       *pBss;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
+       // put all roaming candidates into RoamTab, and sort in RSSI order
+       BssTableInit(pRoamTab);
+       for (i = 0; i < pAd->ScanTab.BssNr; i++)
+       {
+               pBss = &pAd->ScanTab.BssEntry[i];
+
+        if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
+                       continue;        // RSSI too weak. forget it.
+               if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
+                       continue;        // skip current AP
+               if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
+                       continue;        // skip different SSID
+        if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
+                       continue;        // skip AP without better RSSI
+
+        DBGPRINT(RT_DEBUG_TRACE, ("LastRssi0 = %d, pBss->Rssi = %d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), pBss->Rssi));
+               // AP passing all above rules is put into roaming candidate table
+               NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
+               pRoamTab->BssNr += 1;
+       }
+
+       if (pRoamTab->BssNr > 0)
+       {
+               // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
+               if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
+               {
+                       pAd->RalinkCounters.PoorCQIRoamingCount ++;
+                       DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
+                       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
+                       RT28XX_MLME_HANDLER(pAd);
+               }
+       }
+       // Maybe site survey required
+       else
+       {
+               if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
+               {
+                       // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
+                       DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
+                       pAd->StaCfg.ScanCnt = 2;
+                       pAd->StaCfg.LastScanTime = Now;
+                       MlmeAutoScan(pAd);
+               }
+       }
+
+    DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
+}
+
+/*
+       ==========================================================================
+       Description:
+               This routine calculates TxPER, RxPER of the past N-sec period. And
+               according to the calculation result, ChannelQuality is calculated here
+               to decide if current AP is still doing the job.
+
+               If ChannelQuality is not good, a ROAMing attempt may be tried later.
+       Output:
+               StaCfg.ChannelQuality - 0..100
+
+       IRQL = DISPATCH_LEVEL
+
+       NOTE: This routine decide channle quality based on RX CRC error ratio.
+               Caller should make sure a function call to NICUpdateRawCounters(pAd)
+               is performed right before this routine, so that this routine can decide
+               channel quality based on the most up-to-date information
+       ==========================================================================
+ */
+VOID MlmeCalculateChannelQuality(
+       IN PRTMP_ADAPTER pAd,
+       IN ULONG Now32)
+{
+       ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
+       ULONG RxCnt, RxPER;
+       UCHAR NorRssi;
+       CHAR  MaxRssi;
+       ULONG BeaconLostTime = BEACON_LOST_TIME;
+
+#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+       // longer beacon lost time when carrier detection enabled
+       if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+       {
+               BeaconLostTime = BEACON_LOST_TIME + BEACON_LOST_TIME/2;
+       }
+#endif // CARRIER_DETECTION_SUPPORT //
+
+       MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
+
+       //
+       // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
+       //
+       TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
+       TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
+       if (TxCnt < 5)
+       {
+               TxPER = 0;
+               TxPRR = 0;
+       }
+       else
+       {
+               TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
+               TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
+       }
+
+       //
+       // calculate RX PER - don't take RxPER into consideration if too few sample
+       //
+       RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
+       if (RxCnt < 5)
+               RxPER = 0;
+       else
+               RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
+
+       //
+       // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
+       //
+       if (INFRA_ON(pAd) &&
+               (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
+               (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
+               pAd->Mlme.ChannelQuality = 0;
+       }
+       else
+       {
+               // Normalize Rssi
+               if (MaxRssi > -40)
+                       NorRssi = 100;
+               else if (MaxRssi < -90)
+                       NorRssi = 0;
+               else
+                       NorRssi = (MaxRssi + 90) * 2;
+
+               // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER        (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
+               pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
+                                                                  TX_WEIGHTING * (100 - TxPRR) +
+                                                                  RX_WEIGHTING* (100 - RxPER)) / 100;
+               if (pAd->Mlme.ChannelQuality >= 100)
+                       pAd->Mlme.ChannelQuality = 100;
+       }
+
+}
+
+VOID MlmeSetTxRate(
+       IN PRTMP_ADAPTER                pAd,
+       IN PMAC_TABLE_ENTRY             pEntry,
+       IN PRTMP_TX_RATE_SWITCH pTxRate)
+{
+       UCHAR   MaxMode = MODE_OFDM;
+
+#ifdef DOT11_N_SUPPORT
+       MaxMode = MODE_HTGREENFIELD;
+
+       if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
+               pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
+       else
+#endif // DOT11_N_SUPPORT //
+               pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
+
+       if (pTxRate->CurrMCS < MCS_AUTO)
+               pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
+
+       if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
+               pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
+
+       if (ADHOC_ON(pAd))
+       {
+               // If peer adhoc is b-only mode, we can't send 11g rate.
+               pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
+               pEntry->HTPhyMode.field.STBC    = STBC_NONE;
+
+               //
+               // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
+               //
+               pEntry->HTPhyMode.field.MODE    = pTxRate->Mode;
+               pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
+               pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
+
+               // Patch speed error in status page
+               pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
+       }
+       else
+       {
+               if (pTxRate->Mode <= MaxMode)
+                       pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
+
+#ifdef DOT11_N_SUPPORT
+               if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
+                       pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
+               else
+#endif // DOT11_N_SUPPORT //
+                       pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
+
+#ifdef DOT11_N_SUPPORT
+               // Reexam each bandwidth's SGI support.
+               if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
+               {
+                       if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
+                               pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
+                       if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
+                               pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
+               }
+
+               // Turn RTS/CTS rate to 6Mbps.
+               if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
+               {
+                       pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
+                       if (pAd->MacTab.fAnyBASession)
+                       {
+                               AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+                       }
+                       else
+                       {
+                               AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+                       }
+               }
+               else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
+               {
+                       pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
+                       if (pAd->MacTab.fAnyBASession)
+                       {
+                               AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+                       }
+                       else
+                       {
+                               AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+                       }
+               }
+               else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
+               {
+                       AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+
+               }
+               else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
+               {
+                       AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+               }
+#endif // DOT11_N_SUPPORT //
+
+               pEntry->HTPhyMode.field.STBC    = pAd->StaCfg.HTPhyMode.field.STBC;
+               pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
+               pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
+               pEntry->HTPhyMode.field.MODE    = pAd->StaCfg.HTPhyMode.field.MODE;
+#ifdef DOT11_N_SUPPORT
+               if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
+                   pAd->WIFItestbed.bGreenField)
+                   pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
+#endif // DOT11_N_SUPPORT //
+       }
+
+       pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
+}
+
+/*
+       ==========================================================================
+       Description:
+               This routine calculates the acumulated TxPER of eaxh TxRate. And
+               according to the calculation result, change CommonCfg.TxRate which
+               is the stable TX Rate we expect the Radio situation could sustained.
+
+               CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
+       Output:
+               CommonCfg.TxRate -
+
+       IRQL = DISPATCH_LEVEL
+
+       NOTE:
+               call this routine every second
+       ==========================================================================
+ */
+VOID MlmeDynamicTxRateSwitching(
+       IN PRTMP_ADAPTER pAd)
+{
+       UCHAR                                   UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
+       ULONG                                   i, AccuTxTotalCnt = 0, TxTotalCnt;
+       ULONG                                   TxErrorRatio = 0;
+       BOOLEAN                                 bTxRateChanged, bUpgradeQuality = FALSE;
+       PRTMP_TX_RATE_SWITCH    pCurrTxRate, pNextTxRate = NULL;
+       PUCHAR                                  pTable;
+       UCHAR                                   TableSize = 0;
+       UCHAR                                   InitTxRateIdx = 0, TrainUp, TrainDown;
+       CHAR                                    Rssi, RssiOffset = 0;
+       TX_STA_CNT1_STRUC               StaTx1;
+       TX_STA_CNT0_STRUC               TxStaCnt0;
+       ULONG                                   TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
+       MAC_TABLE_ENTRY                 *pEntry;
+
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+       {
+               return;
+       }
+#endif // RALINK_ATE //
+
+       //
+       // walk through MAC table, see if need to change AP's TX rate toward each entry
+       //
+       for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               pEntry = &pAd->MacTab.Content[i];
+
+               // check if this entry need to switch rate automatically
+               if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
+                       continue;
+
+               if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
+               {
+                       Rssi = RTMPMaxRssi(pAd,
+                                                          pAd->StaCfg.RssiSample.AvgRssi0,
+                                                          pAd->StaCfg.RssiSample.AvgRssi1,
+                                                          pAd->StaCfg.RssiSample.AvgRssi2);
+
+                       // Update statistic counter
+                       RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
+                       RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
+                       pAd->bUpdateBcnCntDone = TRUE;
+                       TxRetransmit = StaTx1.field.TxRetransmit;
+                       TxSuccess = StaTx1.field.TxSuccess;
+                       TxFailCount = TxStaCnt0.field.TxFailCount;
+                       TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
+
+                       pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
+                       pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
+                       pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
+                       pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
+                       pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
+                       pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
+
+                       // if no traffic in the past 1-sec period, don't change TX rate,
+                       // but clear all bad history. because the bad history may affect the next
+                       // Chariot throughput test
+                       AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
+                                                pAd->RalinkCounters.OneSecTxRetryOkCount +
+                                                pAd->RalinkCounters.OneSecTxFailCount;
+
+                       if (TxTotalCnt)
+                               TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
+               }
+               else
+               {
+                       if (INFRA_ON(pAd) && (i == 1))
+                               Rssi = RTMPMaxRssi(pAd,
+                                                                  pAd->StaCfg.RssiSample.AvgRssi0,
+                                                                  pAd->StaCfg.RssiSample.AvgRssi1,
+                                                                  pAd->StaCfg.RssiSample.AvgRssi2);
+                       else
+                               Rssi = RTMPMaxRssi(pAd,
+                                                                  pEntry->RssiSample.AvgRssi0,
+                                                                  pEntry->RssiSample.AvgRssi1,
+                                                                  pEntry->RssiSample.AvgRssi2);
+
+                       TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
+                                pEntry->OneSecTxRetryOkCount +
+                                pEntry->OneSecTxFailCount;
+
+                       if (TxTotalCnt)
+                               TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
+               }
+
+               CurrRateIdx = pEntry->CurrTxRateIndex;
+
+               MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
+
+               if (CurrRateIdx >= TableSize)
+               {
+                       CurrRateIdx = TableSize - 1;
+               }
+
+               // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
+               // So need to sync here.
+               pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
+               if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
+                       //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
+                       )
+               {
+
+                       // Need to sync Real Tx rate and our record.
+                       // Then return for next DRS.
+                       pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
+                       pEntry->CurrTxRateIndex = InitTxRateIdx;
+                       MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
+
+                       // reset all OneSecTx counters
+                       RESET_ONE_SEC_TX_CNT(pEntry);
+                       continue;
+               }
+
+               // decide the next upgrade rate and downgrade rate, if any
+               if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
+               {
+                       UpRateIdx = CurrRateIdx + 1;
+                       DownRateIdx = CurrRateIdx -1;
+               }
+               else if (CurrRateIdx == 0)
+               {
+                       UpRateIdx = CurrRateIdx + 1;
+                       DownRateIdx = CurrRateIdx;
+               }
+               else if (CurrRateIdx == (TableSize - 1))
+               {
+                       UpRateIdx = CurrRateIdx;
+                       DownRateIdx = CurrRateIdx - 1;
+               }
+
+               pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
+
+#ifdef DOT11_N_SUPPORT
+               if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
+               {
+                       TrainUp         = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
+                       TrainDown       = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
+               }
+               else
+#endif // DOT11_N_SUPPORT //
+               {
+                       TrainUp         = pCurrTxRate->TrainUp;
+                       TrainDown       = pCurrTxRate->TrainDown;
+               }
+
+               //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
+
+               //
+               // Keep the last time TxRateChangeAction status.
+               //
+               pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
+
+
+
+               //
+               // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
+               //         (criteria copied from RT2500 for Netopia case)
+               //
+               if (TxTotalCnt <= 15)
+               {
+                       CHAR    idx = 0;
+                       UCHAR   TxRateIdx;
+                       //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
+                       UCHAR   MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0,  MCS5 =0, MCS6 = 0, MCS7 = 0;
+               UCHAR   MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
+                       UCHAR   MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
+
+                       // check the existence and index of each needed MCS
+                       while (idx < pTable[0])
+                       {
+                               pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
+
+                               if (pCurrTxRate->CurrMCS == MCS_0)
+                               {
+                                       MCS0 = idx;
+                               }
+                               else if (pCurrTxRate->CurrMCS == MCS_1)
+                               {
+                                       MCS1 = idx;
+                               }
+                               else if (pCurrTxRate->CurrMCS == MCS_2)
+                               {
+                                       MCS2 = idx;
+                               }
+                               else if (pCurrTxRate->CurrMCS == MCS_3)
+                               {
+                                       MCS3 = idx;
+                               }
+                               else if (pCurrTxRate->CurrMCS == MCS_4)
+                               {
+                                       MCS4 = idx;
+                               }
+                   else if (pCurrTxRate->CurrMCS == MCS_5)
+                   {
+                       MCS5 = idx;
+                   }
+                   else if (pCurrTxRate->CurrMCS == MCS_6)
+                   {
+                       MCS6 = idx;
+                   }
+                               //else if (pCurrTxRate->CurrMCS == MCS_7)
+                               else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800))   // prevent the highest MCS using short GI when 1T and low throughput
+                               {
+                                       MCS7 = idx;
+                               }
+                               else if (pCurrTxRate->CurrMCS == MCS_12)
+                               {
+                                       MCS12 = idx;
+                               }
+                               else if (pCurrTxRate->CurrMCS == MCS_13)
+                               {
+                                       MCS13 = idx;
+                               }
+                               else if (pCurrTxRate->CurrMCS == MCS_14)
+                               {
+                                       MCS14 = idx;
+                               }
+                               //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/)    //we hope to use ShortGI as initial rate
+                               else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800))  //we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI
+                               {
+                                       MCS15 = idx;
+                               }
+                               else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
+                               {
+                                       MCS20 = idx;
+                               }
+                               else if (pCurrTxRate->CurrMCS == MCS_21)
+                               {
+                                       MCS21 = idx;
+                               }
+                               else if (pCurrTxRate->CurrMCS == MCS_22)
+                               {
+                                       MCS22 = idx;
+                               }
+                               else if (pCurrTxRate->CurrMCS == MCS_23)
+                               {
+                                       MCS23 = idx;
+                               }
+                               idx ++;
+                       }
+
+                       if (pAd->LatchRfRegs.Channel <= 14)
+                       {
+                               if (pAd->NicConfig2.field.ExternalLNAForG)
+                               {
+                                       RssiOffset = 2;
+                               }
+                               else
+                               {
+                                       RssiOffset = 5;
+                               }
+                       }
+                       else
+                       {
+                               if (pAd->NicConfig2.field.ExternalLNAForA)
+                               {
+                                       RssiOffset = 5;
+                               }
+                               else
+                               {
+                                       RssiOffset = 8;
+                               }
+                       }
+#ifdef DOT11_N_SUPPORT
+                       /*if (MCS15)*/
+                       if ((pTable == RateSwitchTable11BGN3S) ||
+                               (pTable == RateSwitchTable11N3S) ||
+                               (pTable == RateSwitchTable))
+                       {// N mode with 3 stream // 3*3
+                               if (MCS23 && (Rssi >= -70))
+                                       TxRateIdx = MCS15;
+                               else if (MCS22 && (Rssi >= -72))
+                                       TxRateIdx = MCS14;
+                   else if (MCS21 && (Rssi >= -76))
+                                       TxRateIdx = MCS13;
+                               else if (MCS20 && (Rssi >= -78))
+                                       TxRateIdx = MCS12;
+                       else if (MCS4 && (Rssi >= -82))
+                               TxRateIdx = MCS4;
+                       else if (MCS3 && (Rssi >= -84))
+                               TxRateIdx = MCS3;
+                       else if (MCS2 && (Rssi >= -86))
+                               TxRateIdx = MCS2;
+                       else if (MCS1 && (Rssi >= -88))
+                               TxRateIdx = MCS1;
+                       else
+                               TxRateIdx = MCS0;
+               }
+//             else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
+               else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
+                       {// N mode with 2 stream
+                               if (MCS15 && (Rssi >= (-70+RssiOffset)))
+                                       TxRateIdx = MCS15;
+                               else if (MCS14 && (Rssi >= (-72+RssiOffset)))
+                                       TxRateIdx = MCS14;
+                               else if (MCS13 && (Rssi >= (-76+RssiOffset)))
+                                       TxRateIdx = MCS13;
+                               else if (MCS12 && (Rssi >= (-78+RssiOffset)))
+                                       TxRateIdx = MCS12;
+                               else if (MCS4 && (Rssi >= (-82+RssiOffset)))
+                                       TxRateIdx = MCS4;
+                               else if (MCS3 && (Rssi >= (-84+RssiOffset)))
+                                       TxRateIdx = MCS3;
+                               else if (MCS2 && (Rssi >= (-86+RssiOffset)))
+                                       TxRateIdx = MCS2;
+                               else if (MCS1 && (Rssi >= (-88+RssiOffset)))
+                                       TxRateIdx = MCS1;
+                               else
+                                       TxRateIdx = MCS0;
+                       }
+                       else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
+                       {// N mode with 1 stream
+                               if (MCS7 && (Rssi > (-72+RssiOffset)))
+                                       TxRateIdx = MCS7;
+                               else if (MCS6 && (Rssi > (-74+RssiOffset)))
+                                       TxRateIdx = MCS6;
+                               else if (MCS5 && (Rssi > (-77+RssiOffset)))
+                                       TxRateIdx = MCS5;
+                               else if (MCS4 && (Rssi > (-79+RssiOffset)))
+                                       TxRateIdx = MCS4;
+                               else if (MCS3 && (Rssi > (-81+RssiOffset)))
+                                       TxRateIdx = MCS3;
+                               else if (MCS2 && (Rssi > (-83+RssiOffset)))
+                                       TxRateIdx = MCS2;
+                               else if (MCS1 && (Rssi > (-86+RssiOffset)))
+                                       TxRateIdx = MCS1;
+                               else
+                                       TxRateIdx = MCS0;
+                       }
+                       else
+#endif // DOT11_N_SUPPORT //
+                       {// Legacy mode
+                               if (MCS7 && (Rssi > -70))
+                                       TxRateIdx = MCS7;
+                               else if (MCS6 && (Rssi > -74))
+                                       TxRateIdx = MCS6;
+                               else if (MCS5 && (Rssi > -78))
+                                       TxRateIdx = MCS5;
+                               else if (MCS4 && (Rssi > -82))
+                                       TxRateIdx = MCS4;
+                               else if (MCS4 == 0)     // for B-only mode
+                                       TxRateIdx = MCS3;
+                               else if (MCS3 && (Rssi > -85))
+                                       TxRateIdx = MCS3;
+                               else if (MCS2 && (Rssi > -87))
+                                       TxRateIdx = MCS2;
+                               else if (MCS1 && (Rssi > -90))
+                                       TxRateIdx = MCS1;
+                               else
+                                       TxRateIdx = MCS0;
+                       }
+
+       //              if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
+                       {
+                               pEntry->CurrTxRateIndex = TxRateIdx;
+                               pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
+                               MlmeSetTxRate(pAd, pEntry, pNextTxRate);
+                       }
+
+                       NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
+                       NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
+                       pEntry->fLastSecAccordingRSSI = TRUE;
+                       // reset all OneSecTx counters
+                       RESET_ONE_SEC_TX_CNT(pEntry);
+
+                       continue;
+               }
+
+               if (pEntry->fLastSecAccordingRSSI == TRUE)
+               {
+                       pEntry->fLastSecAccordingRSSI = FALSE;
+                       pEntry->LastSecTxRateChangeAction = 0;
+                       // reset all OneSecTx counters
+                       RESET_ONE_SEC_TX_CNT(pEntry);
+
+                       continue;
+               }
+
+               do
+               {
+                       BOOLEAN bTrainUpDown = FALSE;
+
+                       pEntry->CurrTxRateStableTime ++;
+
+                       // downgrade TX quality if PER >= Rate-Down threshold
+                       if (TxErrorRatio >= TrainDown)
+                       {
+                               bTrainUpDown = TRUE;
+                               pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
+                       }
+                       // upgrade TX quality if PER <= Rate-Up threshold
+                       else if (TxErrorRatio <= TrainUp)
+                       {
+                               bTrainUpDown = TRUE;
+                               bUpgradeQuality = TRUE;
+                               if (pEntry->TxQuality[CurrRateIdx])
+                                       pEntry->TxQuality[CurrRateIdx] --;  // quality very good in CurrRate
+
+                               if (pEntry->TxRateUpPenalty)
+                                       pEntry->TxRateUpPenalty --;
+                               else if (pEntry->TxQuality[UpRateIdx])
+                                       pEntry->TxQuality[UpRateIdx] --;    // may improve next UP rate's quality
+                       }
+
+                       pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
+
+                       if (bTrainUpDown)
+                       {
+                               // perform DRS - consider TxRate Down first, then rate up.
+                               if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
+                               {
+                                       pEntry->CurrTxRateIndex = DownRateIdx;
+                               }
+                               else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
+                               {
+                                       pEntry->CurrTxRateIndex = UpRateIdx;
+                               }
+                       }
+               } while (FALSE);
+
+               // if rate-up happen, clear all bad history of all TX rates
+               if (pEntry->CurrTxRateIndex > CurrRateIdx)
+               {
+                       pEntry->CurrTxRateStableTime = 0;
+                       pEntry->TxRateUpPenalty = 0;
+                       pEntry->LastSecTxRateChangeAction = 1; // rate UP
+                       NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
+                       NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
+
+                       //
+                       // For TxRate fast train up
+                       //
+                       if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
+                       {
+                               RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
+
+                               pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
+                       }
+                       bTxRateChanged = TRUE;
+               }
+               // if rate-down happen, only clear DownRate's bad history
+               else if (pEntry->CurrTxRateIndex < CurrRateIdx)
+               {
+                       pEntry->CurrTxRateStableTime = 0;
+                       pEntry->TxRateUpPenalty = 0;           // no penalty
+                       pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
+                       pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
+                       pEntry->PER[pEntry->CurrTxRateIndex] = 0;
+
+                       //
+                       // For TxRate fast train down
+                       //
+                       if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
+                       {
+                               RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
+
+                               pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
+                       }
+                       bTxRateChanged = TRUE;
+               }
+               else
+               {
+                       pEntry->LastSecTxRateChangeAction = 0; // rate no change
+                       bTxRateChanged = FALSE;
+               }
+
+               pEntry->LastTxOkCount = TxSuccess;
+
+               // reset all OneSecTx counters
+               RESET_ONE_SEC_TX_CNT(pEntry);
+
+               pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
+               if (bTxRateChanged && pNextTxRate)
+               {
+                       MlmeSetTxRate(pAd, pEntry, pNextTxRate);
+               }
+       }
+}
+
+/*
+       ========================================================================
+       Routine Description:
+               Station side, Auto TxRate faster train up timer call back function.
+
+       Arguments:
+               SystemSpecific1                 - Not used.
+               FunctionContext                 - Pointer to our Adapter context.
+               SystemSpecific2                 - Not used.
+               SystemSpecific3                 - Not used.
+
+       Return Value:
+               None
+
+       ========================================================================
+*/
+VOID StaQuickResponeForRateUpExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3)
+{
+       PRTMP_ADAPTER                   pAd = (PRTMP_ADAPTER)FunctionContext;
+       UCHAR                                   UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
+       ULONG                                   TxTotalCnt;
+       ULONG                                   TxErrorRatio = 0;
+       BOOLEAN                                 bTxRateChanged; //, bUpgradeQuality = FALSE;
+       PRTMP_TX_RATE_SWITCH    pCurrTxRate, pNextTxRate = NULL;
+       PUCHAR                                  pTable;
+       UCHAR                                   TableSize = 0;
+       UCHAR                                   InitTxRateIdx = 0, TrainUp, TrainDown;
+       TX_STA_CNT1_STRUC               StaTx1;
+       TX_STA_CNT0_STRUC               TxStaCnt0;
+       CHAR                                    Rssi, ratio;
+       ULONG                                   TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
+       MAC_TABLE_ENTRY                 *pEntry;
+       ULONG                                   i;
+
+       pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
+
+    //
+    // walk through MAC table, see if need to change AP's TX rate toward each entry
+    //
+       for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               pEntry = &pAd->MacTab.Content[i];
+
+               // check if this entry need to switch rate automatically
+               if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
+                       continue;
+
+               if (INFRA_ON(pAd) && (i == 1))
+                       Rssi = RTMPMaxRssi(pAd,
+                                                          pAd->StaCfg.RssiSample.AvgRssi0,
+                                                          pAd->StaCfg.RssiSample.AvgRssi1,
+                                                          pAd->StaCfg.RssiSample.AvgRssi2);
+               else
+                       Rssi = RTMPMaxRssi(pAd,
+                                                          pEntry->RssiSample.AvgRssi0,
+                                                          pEntry->RssiSample.AvgRssi1,
+                                                          pEntry->RssiSample.AvgRssi2);
+
+               CurrRateIdx = pAd->CommonCfg.TxRateIndex;
+
+                       MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
+
+               // decide the next upgrade rate and downgrade rate, if any
+               if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
+               {
+                       UpRateIdx = CurrRateIdx + 1;
+                       DownRateIdx = CurrRateIdx -1;
+               }
+               else if (CurrRateIdx == 0)
+               {
+                       UpRateIdx = CurrRateIdx + 1;
+                       DownRateIdx = CurrRateIdx;
+               }
+               else if (CurrRateIdx == (TableSize - 1))
+               {
+                       UpRateIdx = CurrRateIdx;
+                       DownRateIdx = CurrRateIdx - 1;
+               }
+
+               pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
+
+#ifdef DOT11_N_SUPPORT
+               if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
+               {
+                       TrainUp         = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
+                       TrainDown       = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
+               }
+               else
+#endif // DOT11_N_SUPPORT //
+               {
+                       TrainUp         = pCurrTxRate->TrainUp;
+                       TrainDown       = pCurrTxRate->TrainDown;
+               }
+
+               if (pAd->MacTab.Size == 1)
+               {
+                       // Update statistic counter
+                       RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
+                       RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
+
+                       TxRetransmit = StaTx1.field.TxRetransmit;
+                       TxSuccess = StaTx1.field.TxSuccess;
+                       TxFailCount = TxStaCnt0.field.TxFailCount;
+                       TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
+
+                       pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
+                       pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
+                       pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
+                       pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
+                       pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
+                       pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
+
+#if 0 // test by Gary.
+                       // if no traffic in the past 1-sec period, don't change TX rate,
+                       // but clear all bad history. because the bad history may affect the next
+                       // Chariot throughput test
+                       TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
+                                                pAd->RalinkCounters.OneSecTxRetryOkCount +
+                                                pAd->RalinkCounters.OneSecTxFailCount;
+#endif
+                       if (TxTotalCnt)
+                               TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
+               }
+               else
+               {
+                       TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
+                                pEntry->OneSecTxRetryOkCount +
+                                pEntry->OneSecTxFailCount;
+
+                       if (TxTotalCnt)
+                               TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
+               }
+
+
+               //
+               // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
+               //         (criteria copied from RT2500 for Netopia case)
+               //
+               if (TxTotalCnt <= 12)
+               {
+                       NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
+                       NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
+
+                       if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
+                       {
+                               pAd->CommonCfg.TxRateIndex = DownRateIdx;
+                               pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
+                       }
+                       else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
+                       {
+                               pAd->CommonCfg.TxRateIndex = UpRateIdx;
+                       }
+
+                       DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
+                       return;
+               }
+
+               do
+               {
+                       ULONG OneSecTxNoRetryOKRationCount;
+
+                       if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
+                               ratio = 5;
+                       else
+                               ratio = 4;
+
+                       // downgrade TX quality if PER >= Rate-Down threshold
+                       if (TxErrorRatio >= TrainDown)
+                       {
+                               pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
+                       }
+
+                       pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
+
+                       OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
+
+                       // perform DRS - consider TxRate Down first, then rate up.
+                       if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
+                       {
+                               if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
+                               {
+                                       pAd->CommonCfg.TxRateIndex = DownRateIdx;
+                                       pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
+
+                               }
+
+                       }
+                       else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
+                       {
+                               if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
+                               {
+
+                               }
+                               else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
+                               {
+                                       pAd->CommonCfg.TxRateIndex = UpRateIdx;
+                               }
+                       }
+               }while (FALSE);
+
+               // if rate-up happen, clear all bad history of all TX rates
+               if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
+               {
+                       pAd->DrsCounters.TxRateUpPenalty = 0;
+                       NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
+                       NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
+                       bTxRateChanged = TRUE;
+               }
+               // if rate-down happen, only clear DownRate's bad history
+               else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
+               {
+                       DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
+
+                       pAd->DrsCounters.TxRateUpPenalty = 0;           // no penalty
+                       pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
+                       pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
+                       bTxRateChanged = TRUE;
+               }
+               else
+               {
+                       bTxRateChanged = FALSE;
+               }
+
+               pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
+               if (bTxRateChanged && pNextTxRate)
+               {
+                       MlmeSetTxRate(pAd, pEntry, pNextTxRate);
+               }
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+               This routine is executed periodically inside MlmePeriodicExec() after
+               association with an AP.
+               It checks if StaCfg.Psm is consistent with user policy (recorded in
+               StaCfg.WindowsPowerMode). If not, enforce user policy. However,
+               there're some conditions to consider:
+               1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
+                  the time when Mibss==TRUE
+               2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
+                  if outgoing traffic available in TxRing or MgmtRing.
+       Output:
+               1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID MlmeCheckPsmChange(
+       IN PRTMP_ADAPTER pAd,
+       IN ULONG        Now32)
+{
+       ULONG   PowerMode;
+
+       // condition -
+       // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
+       // 2. user wants either MAX_PSP or FAST_PSP
+       // 3. but current psm is not in PWR_SAVE
+       // 4. CNTL state machine is not doing SCANning
+       // 5. no TX SUCCESS event for the past 1-sec period
+#ifdef NDIS51_MINIPORT
+       if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
+               PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
+       else
+#endif
+               PowerMode = pAd->StaCfg.WindowsPowerMode;
+
+       if (INFRA_ON(pAd) &&
+               (PowerMode != Ndis802_11PowerModeCAM) &&
+               (pAd->StaCfg.Psm == PWR_ACTIVE) &&
+//             (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+               (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
+               (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
+               (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
+       {
+               NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
+               pAd->RalinkCounters.RxCountSinceLastNULL = 0;
+               MlmeSetPsmBit(pAd, PWR_SAVE);
+               if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
+               {
+                       RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
+               }
+               else
+               {
+                       RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
+               }
+       }
+}
+
+// IRQL = PASSIVE_LEVEL
+// IRQL = DISPATCH_LEVEL
+VOID MlmeSetPsmBit(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT psm)
+{
+       AUTO_RSP_CFG_STRUC csr4;
+
+       pAd->StaCfg.Psm = psm;
+       RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
+       csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
+       RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
+       DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+// IRQL = DISPATCH_LEVEL
+VOID MlmeSetTxPreamble(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT TxPreamble)
+{
+       AUTO_RSP_CFG_STRUC csr4;
+
+       //
+       // Always use Long preamble before verifiation short preamble functionality works well.
+       // Todo: remove the following line if short preamble functionality works
+       //
+       //TxPreamble = Rt802_11PreambleLong;
+
+       RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
+       if (TxPreamble == Rt802_11PreambleLong)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+               csr4.field.AutoResponderPreamble = 0;
+       }
+       else
+       {
+               // NOTE: 1Mbps should always use long preamble
+               DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
+               OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+               csr4.field.AutoResponderPreamble = 1;
+       }
+
+       RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
+}
+
+/*
+    ==========================================================================
+    Description:
+        Update basic rate bitmap
+    ==========================================================================
+ */
+
+VOID UpdateBasicRateBitmap(
+    IN  PRTMP_ADAPTER   pAdapter)
+{
+    INT  i, j;
+                  /* 1  2  5.5, 11,  6,  9, 12, 18, 24, 36, 48,  54 */
+    UCHAR rate[] = { 2, 4,  11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
+    UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
+    UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
+    ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
+
+
+    /* if A mode, always use fix BasicRateBitMap */
+    //if (pAdapter->CommonCfg.Channel == PHY_11A)
+       if (pAdapter->CommonCfg.Channel > 14)
+        pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
+    /* End of if */
+
+    if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
+    {
+        /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
+        return;
+    } /* End of if */
+
+    for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+    {
+        sup_p[i] &= 0x7f;
+        ext_p[i] &= 0x7f;
+    } /* End of for */
+
+    for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+    {
+        if (bitmap & (1 << i))
+        {
+            for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
+            {
+                if (sup_p[j] == rate[i])
+                    sup_p[j] |= 0x80;
+                /* End of if */
+            } /* End of for */
+
+            for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
+            {
+                if (ext_p[j] == rate[i])
+                    ext_p[j] |= 0x80;
+                /* End of if */
+            } /* End of for */
+        } /* End of if */
+    } /* End of for */
+} /* End of UpdateBasicRateBitmap */
+
+// IRQL = PASSIVE_LEVEL
+// IRQL = DISPATCH_LEVEL
+// bLinkUp is to identify the inital link speed.
+// TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
+VOID MlmeUpdateTxRates(
+       IN PRTMP_ADAPTER                pAd,
+       IN      BOOLEAN                         bLinkUp,
+       IN      UCHAR                           apidx)
+{
+       int i, num;
+       UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
+       UCHAR MinSupport = RATE_54;
+       ULONG BasicRateBitmap = 0;
+       UCHAR CurrBasicRate = RATE_1;
+       UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
+       PHTTRANSMIT_SETTING             pHtPhy = NULL;
+       PHTTRANSMIT_SETTING             pMaxHtPhy = NULL;
+       PHTTRANSMIT_SETTING             pMinHtPhy = NULL;
+       BOOLEAN                                 *auto_rate_cur_p;
+       UCHAR                                   HtMcs = MCS_AUTO;
+
+       // find max desired rate
+       UpdateBasicRateBitmap(pAd);
+
+       num = 0;
+       auto_rate_cur_p = NULL;
+       for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+       {
+               switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
+               {
+                       case 2:  Rate = RATE_1;   num++;   break;
+                       case 4:  Rate = RATE_2;   num++;   break;
+                       case 11: Rate = RATE_5_5; num++;   break;
+                       case 22: Rate = RATE_11;  num++;   break;
+                       case 12: Rate = RATE_6;   num++;   break;
+                       case 18: Rate = RATE_9;   num++;   break;
+                       case 24: Rate = RATE_12;  num++;   break;
+                       case 36: Rate = RATE_18;  num++;   break;
+                       case 48: Rate = RATE_24;  num++;   break;
+                       case 72: Rate = RATE_36;  num++;   break;
+                       case 96: Rate = RATE_48;  num++;   break;
+                       case 108: Rate = RATE_54; num++;   break;
+                       //default: Rate = RATE_1;   break;
+               }
+               if (MaxDesire < Rate)  MaxDesire = Rate;
+       }
+
+//===========================================================================
+//===========================================================================
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               pHtPhy          = &pAd->StaCfg.HTPhyMode;
+               pMaxHtPhy       = &pAd->StaCfg.MaxHTPhyMode;
+               pMinHtPhy       = &pAd->StaCfg.MinHTPhyMode;
+
+               auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
+               HtMcs           = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
+
+               if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
+                       (pAd->CommonCfg.PhyMode == PHY_11B) &&
+                       (MaxDesire > RATE_11))
+               {
+                       MaxDesire = RATE_11;
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       pAd->CommonCfg.MaxDesiredRate = MaxDesire;
+       pMinHtPhy->word = 0;
+       pMaxHtPhy->word = 0;
+       pHtPhy->word = 0;
+
+       // Auto rate switching is enabled only if more than one DESIRED RATES are
+       // specified; otherwise disabled
+       if (num <= 1)
+       {
+               //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
+               //pAd->CommonCfg.bAutoTxRateSwitch      = FALSE;
+               *auto_rate_cur_p = FALSE;
+       }
+       else
+       {
+               //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
+               //pAd->CommonCfg.bAutoTxRateSwitch      = TRUE;
+               *auto_rate_cur_p = TRUE;
+       }
+
+#if 1
+       if (HtMcs != MCS_AUTO)
+       {
+               //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
+               //pAd->CommonCfg.bAutoTxRateSwitch      = FALSE;
+               *auto_rate_cur_p = FALSE;
+       }
+       else
+       {
+               //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
+               //pAd->CommonCfg.bAutoTxRateSwitch      = TRUE;
+               *auto_rate_cur_p = TRUE;
+       }
+#endif
+
+#ifdef CONFIG_STA_SUPPORT
+       if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
+       {
+               pSupRate = &pAd->StaActive.SupRate[0];
+               pExtRate = &pAd->StaActive.ExtRate[0];
+               SupRateLen = pAd->StaActive.SupRateLen;
+               ExtRateLen = pAd->StaActive.ExtRateLen;
+       }
+       else
+#endif // CONFIG_STA_SUPPORT //
+       {
+               pSupRate = &pAd->CommonCfg.SupRate[0];
+               pExtRate = &pAd->CommonCfg.ExtRate[0];
+               SupRateLen = pAd->CommonCfg.SupRateLen;
+               ExtRateLen = pAd->CommonCfg.ExtRateLen;
+       }
+
+       // find max supported rate
+       for (i=0; i<SupRateLen; i++)
+       {
+               switch (pSupRate[i] & 0x7f)
+               {
+                       case 2:   Rate = RATE_1;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001;       break;
+                       case 4:   Rate = RATE_2;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002;       break;
+                       case 11:  Rate = RATE_5_5;      if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004;       break;
+                       case 22:  Rate = RATE_11;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008;       break;
+                       case 12:  Rate = RATE_6;        /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0010;  break;
+                       case 18:  Rate = RATE_9;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020;       break;
+                       case 24:  Rate = RATE_12;       /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0040;  break;
+                       case 36:  Rate = RATE_18;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080;       break;
+                       case 48:  Rate = RATE_24;       /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0100;  break;
+                       case 72:  Rate = RATE_36;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200;       break;
+                       case 96:  Rate = RATE_48;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400;       break;
+                       case 108: Rate = RATE_54;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800;       break;
+                       default:  Rate = RATE_1;        break;
+               }
+               if (MaxSupport < Rate)  MaxSupport = Rate;
+
+               if (MinSupport > Rate) MinSupport = Rate;
+       }
+
+       for (i=0; i<ExtRateLen; i++)
+       {
+               switch (pExtRate[i] & 0x7f)
+               {
+                       case 2:   Rate = RATE_1;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001;       break;
+                       case 4:   Rate = RATE_2;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002;       break;
+                       case 11:  Rate = RATE_5_5;      if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004;       break;
+                       case 22:  Rate = RATE_11;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008;       break;
+                       case 12:  Rate = RATE_6;        /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0010;  break;
+                       case 18:  Rate = RATE_9;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020;       break;
+                       case 24:  Rate = RATE_12;       /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0040;  break;
+                       case 36:  Rate = RATE_18;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080;       break;
+                       case 48:  Rate = RATE_24;       /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0100;  break;
+                       case 72:  Rate = RATE_36;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200;       break;
+                       case 96:  Rate = RATE_48;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400;       break;
+                       case 108: Rate = RATE_54;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800;       break;
+                       default:  Rate = RATE_1;        break;
+               }
+               if (MaxSupport < Rate)  MaxSupport = Rate;
+
+               if (MinSupport > Rate) MinSupport = Rate;
+       }
+
+       RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
+
+       // bug fix
+       // pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap;
+
+       // calculate the exptected ACK rate for each TX rate. This info is used to caculate
+       // the DURATION field of outgoing uniicast DATA/MGMT frame
+       for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+       {
+               if (BasicRateBitmap & (0x01 << i))
+                       CurrBasicRate = (UCHAR)i;
+               pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
+       // max tx rate = min {max desire rate, max supported rate}
+       if (MaxSupport < MaxDesire)
+               pAd->CommonCfg.MaxTxRate = MaxSupport;
+       else
+               pAd->CommonCfg.MaxTxRate = MaxDesire;
+
+       pAd->CommonCfg.MinTxRate = MinSupport;
+       // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
+       // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
+       // on average RSSI
+       //       1. RSSI >= -70db, start at 54 Mbps (short distance)
+       //       2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
+       //       3. -75 > RSSI, start at 11 Mbps (long distance)
+       //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
+       //      OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
+       if (*auto_rate_cur_p)
+       {
+               short dbm = 0;
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
+#endif // CONFIG_STA_SUPPORT //
+               if (bLinkUp == TRUE)
+                       pAd->CommonCfg.TxRate = RATE_24;
+               else
+                       pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
+
+               if (dbm < -75)
+                       pAd->CommonCfg.TxRate = RATE_11;
+               else if (dbm < -70)
+                       pAd->CommonCfg.TxRate = RATE_24;
+
+               // should never exceed MaxTxRate (consider 11B-only mode)
+               if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
+                       pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
+
+               pAd->CommonCfg.TxRateIndex = 0;
+       }
+       else
+       {
+               pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
+               pHtPhy->field.MCS       = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
+               pHtPhy->field.MODE      = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
+
+               pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC    = pHtPhy->field.STBC;
+               pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
+               pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS             = pHtPhy->field.MCS;
+               pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE    = pHtPhy->field.MODE;
+       }
+
+       if (pAd->CommonCfg.TxRate <= RATE_11)
+       {
+               pMaxHtPhy->field.MODE = MODE_CCK;
+               pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
+               pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
+       }
+       else
+       {
+               pMaxHtPhy->field.MODE = MODE_OFDM;
+               pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
+               if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
+                       {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
+               else
+                       {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
+       }
+
+       pHtPhy->word = (pMaxHtPhy->word);
+       if (bLinkUp && (pAd->OpMode == OPMODE_STA))
+       {
+                       pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
+                       pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
+                       pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
+       }
+       else
+       {
+               switch (pAd->CommonCfg.PhyMode)
+               {
+                       case PHY_11BG_MIXED:
+                       case PHY_11B:
+#ifdef DOT11_N_SUPPORT
+                       case PHY_11BGN_MIXED:
+#endif // DOT11_N_SUPPORT //
+                               pAd->CommonCfg.MlmeRate = RATE_1;
+                               pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
+                               pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
+
+//#ifdef       WIFI_TEST
+                               pAd->CommonCfg.RtsRate = RATE_11;
+//#else
+//                             pAd->CommonCfg.RtsRate = RATE_1;
+//#endif
+                               break;
+                       case PHY_11G:
+                       case PHY_11A:
+#ifdef DOT11_N_SUPPORT
+                       case PHY_11AGN_MIXED:
+                       case PHY_11GN_MIXED:
+                       case PHY_11N_2_4G:
+                       case PHY_11AN_MIXED:
+                       case PHY_11N_5G:
+#endif // DOT11_N_SUPPORT //
+                               pAd->CommonCfg.MlmeRate = RATE_6;
+                               pAd->CommonCfg.RtsRate = RATE_6;
+                               pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+                               pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+                               break;
+                       case PHY_11ABG_MIXED:
+#ifdef DOT11_N_SUPPORT
+                       case PHY_11ABGN_MIXED:
+#endif // DOT11_N_SUPPORT //
+                               if (pAd->CommonCfg.Channel <= 14)
+                               {
+                                       pAd->CommonCfg.MlmeRate = RATE_1;
+                                       pAd->CommonCfg.RtsRate = RATE_1;
+                                       pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
+                                       pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
+                               }
+                               else
+                               {
+                                       pAd->CommonCfg.MlmeRate = RATE_6;
+                                       pAd->CommonCfg.RtsRate = RATE_6;
+                                       pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+                                       pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+                               }
+                               break;
+                       default: // error
+                               pAd->CommonCfg.MlmeRate = RATE_6;
+                               pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+                               pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+                               pAd->CommonCfg.RtsRate = RATE_1;
+                               break;
+               }
+               //
+               // Keep Basic Mlme Rate.
+               //
+               pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
+               if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
+                       pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
+               else
+                       pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
+               pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
+                        RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
+                        /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
+       DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
+                        RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
+       DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
+                        pAd->CommonCfg.MlmeTransmit.word, pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word ));
+}
+
+#ifdef DOT11_N_SUPPORT
+/*
+       ==========================================================================
+       Description:
+               This function update HT Rate setting.
+               Input Wcid value is valid for 2 case :
+               1. it's used for Station in infra mode that copy AP rate to Mactable.
+               2. OR Station   in adhoc mode to copy peer's HT rate to Mactable.
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID MlmeUpdateHtTxRates(
+       IN PRTMP_ADAPTER                pAd,
+       IN      UCHAR                           apidx)
+{
+       UCHAR   StbcMcs; //j, StbcMcs, bitmask;
+       CHAR    i; // 3*3
+       RT_HT_CAPABILITY        *pRtHtCap = NULL;
+       RT_HT_PHY_INFO          *pActiveHtPhy = NULL;
+       ULONG           BasicMCS;
+       UCHAR j, bitmask;
+       PRT_HT_PHY_INFO                 pDesireHtPhy = NULL;
+       PHTTRANSMIT_SETTING             pHtPhy = NULL;
+       PHTTRANSMIT_SETTING             pMaxHtPhy = NULL;
+       PHTTRANSMIT_SETTING             pMinHtPhy = NULL;
+       BOOLEAN                                 *auto_rate_cur_p;
+
+       DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
+
+       auto_rate_cur_p = NULL;
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               pDesireHtPhy    = &pAd->StaCfg.DesiredHtPhyInfo;
+               pActiveHtPhy    = &pAd->StaCfg.DesiredHtPhyInfo;
+               pHtPhy          = &pAd->StaCfg.HTPhyMode;
+               pMaxHtPhy       = &pAd->StaCfg.MaxHTPhyMode;
+               pMinHtPhy       = &pAd->StaCfg.MinHTPhyMode;
+
+               auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+       if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
+       {
+               if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
+                       return;
+
+               pRtHtCap = &pAd->StaActive.SupportedHtPhy;
+               pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
+               StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
+               BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
+               if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
+                       pMaxHtPhy->field.STBC = STBC_USE;
+               else
+                       pMaxHtPhy->field.STBC = STBC_NONE;
+       }
+       else
+#endif // CONFIG_STA_SUPPORT //
+       {
+               if (pDesireHtPhy->bHtEnable == FALSE)
+                       return;
+
+               pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
+               StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
+               BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
+               if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
+                       pMaxHtPhy->field.STBC = STBC_USE;
+               else
+                       pMaxHtPhy->field.STBC = STBC_NONE;
+       }
+
+       // Decide MAX ht rate.
+       if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
+               pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
+       else
+               pMaxHtPhy->field.MODE = MODE_HTMIX;
+
+    if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
+               pMaxHtPhy->field.BW = BW_40;
+       else
+               pMaxHtPhy->field.BW = BW_20;
+
+    if (pMaxHtPhy->field.BW == BW_20)
+               pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
+       else
+               pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
+
+       for (i=23; i>=0; i--) // 3*3
+       {
+               j = i/8;
+               bitmask = (1<<(i-(j*8)));
+
+               if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
+               {
+                       pMaxHtPhy->field.MCS = i;
+                       break;
+               }
+
+               if (i==0)
+                       break;
+       }
+
+       // Copy MIN ht rate.  rt2860???
+       pMinHtPhy->field.BW = BW_20;
+       pMinHtPhy->field.MCS = 0;
+       pMinHtPhy->field.STBC = 0;
+       pMinHtPhy->field.ShortGI = 0;
+       //If STA assigns fixed rate. update to fixed here.
+#ifdef CONFIG_STA_SUPPORT
+       if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
+       {
+               if (pDesireHtPhy->MCSSet[4] != 0)
+               {
+                       pMaxHtPhy->field.MCS = 32;
+                       pMinHtPhy->field.MCS = 32;
+                       DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
+               }
+
+               for (i=23; (CHAR)i >= 0; i--) // 3*3
+               {
+                       j = i/8;
+                       bitmask = (1<<(i-(j*8)));
+                       if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
+                       {
+                               pMaxHtPhy->field.MCS = i;
+                               pMinHtPhy->field.MCS = i;
+                               break;
+                       }
+                       if (i==0)
+                               break;
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+
+       // Decide ht rate
+       pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
+       pHtPhy->field.BW = pMaxHtPhy->field.BW;
+       pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
+       pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
+       pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
+
+       // use default now. rt2860
+       if (pDesireHtPhy->MCSSet[0] != 0xff)
+               *auto_rate_cur_p = FALSE;
+       else
+               *auto_rate_cur_p = TRUE;
+
+       DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d  \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
+       DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d,  \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
+               pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
+       DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
+}
+#endif // DOT11_N_SUPPORT //
+
+// IRQL = DISPATCH_LEVEL
+VOID MlmeRadioOff(
+       IN PRTMP_ADAPTER pAd)
+{
+       RT28XX_MLME_RADIO_OFF(pAd);
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID MlmeRadioOn(
+       IN PRTMP_ADAPTER pAd)
+{
+       RT28XX_MLME_RADIO_ON(pAd);
+}
+
+// ===========================================================================================
+// bss_table.c
+// ===========================================================================================
+
+
+/*! \brief initialize BSS table
+ *     \param p_tab pointer to the table
+ *     \return none
+ *     \pre
+ *     \post
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID BssTableInit(
+       IN BSS_TABLE *Tab)
+{
+       int i;
+
+       Tab->BssNr = 0;
+    Tab->BssOverlapNr = 0;
+       for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
+       {
+               NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
+               Tab->BssEntry[i].Rssi = -127;   // initial the rssi as a minimum value
+       }
+}
+
+#ifdef DOT11_N_SUPPORT
+VOID BATableInit(
+       IN PRTMP_ADAPTER pAd,
+    IN BA_TABLE *Tab)
+{
+       int i;
+
+       Tab->numAsOriginator = 0;
+       Tab->numAsRecipient = 0;
+       NdisAllocateSpinLock(&pAd->BATabLock);
+       for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
+       {
+               Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
+               NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
+       }
+       for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
+       {
+               Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
+       }
+}
+#endif // DOT11_N_SUPPORT //
+
+/*! \brief search the BSS table by SSID
+ *     \param p_tab pointer to the bss table
+ *     \param ssid SSID string
+ *     \return index of the table, BSS_NOT_FOUND if not in the table
+ *     \pre
+ *     \post
+ *     \note search by sequential search
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+ULONG BssTableSearch(
+       IN BSS_TABLE *Tab,
+       IN PUCHAR        pBssid,
+       IN UCHAR         Channel)
+{
+       UCHAR i;
+
+       for (i = 0; i < Tab->BssNr; i++)
+       {
+               //
+               // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
+               // We should distinguish this case.
+               //
+               if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
+                        ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
+                       MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
+               {
+                       return i;
+               }
+       }
+       return (ULONG)BSS_NOT_FOUND;
+}
+
+ULONG BssSsidTableSearch(
+       IN BSS_TABLE *Tab,
+       IN PUCHAR        pBssid,
+       IN PUCHAR        pSsid,
+       IN UCHAR         SsidLen,
+       IN UCHAR         Channel)
+{
+       UCHAR i;
+
+       for (i = 0; i < Tab->BssNr; i++)
+       {
+               //
+               // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
+               // We should distinguish this case.
+               //
+               if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
+                        ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
+                       MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
+                       SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
+               {
+                       return i;
+               }
+       }
+       return (ULONG)BSS_NOT_FOUND;
+}
+
+ULONG BssTableSearchWithSSID(
+       IN BSS_TABLE *Tab,
+       IN PUCHAR        Bssid,
+       IN PUCHAR        pSsid,
+       IN UCHAR         SsidLen,
+       IN UCHAR         Channel)
+{
+       UCHAR i;
+
+       for (i = 0; i < Tab->BssNr; i++)
+       {
+               if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
+                       ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
+                       MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
+                       (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
+                       (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
+                       (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
+               {
+                       return i;
+               }
+       }
+       return (ULONG)BSS_NOT_FOUND;
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID BssTableDeleteEntry(
+       IN OUT  BSS_TABLE *Tab,
+       IN              PUCHAR    pBssid,
+       IN              UCHAR     Channel)
+{
+       UCHAR i, j;
+
+       for (i = 0; i < Tab->BssNr; i++)
+       {
+               if ((Tab->BssEntry[i].Channel == Channel) &&
+                       (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
+               {
+                       for (j = i; j < Tab->BssNr - 1; j++)
+                       {
+                               NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
+                       }
+                       NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
+                       Tab->BssNr -= 1;
+                       return;
+               }
+       }
+}
+
+#ifdef DOT11_N_SUPPORT
+/*
+       ========================================================================
+       Routine Description:
+               Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
+
+       Arguments:
+       // IRQL = DISPATCH_LEVEL
+       ========================================================================
+*/
+VOID BATableDeleteORIEntry(
+       IN OUT  PRTMP_ADAPTER pAd,
+       IN              BA_ORI_ENTRY    *pBAORIEntry)
+{
+
+       if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
+       {
+               NdisAcquireSpinLock(&pAd->BATabLock);
+               if (pBAORIEntry->ORI_BA_Status == Originator_Done)
+               {
+                       pAd->BATable.numAsOriginator -= 1;
+                       DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
+                       // Erase Bitmap flag.
+               }
+               pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) ));       // If STA mode,  erase flag here
+               pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0;    // If STA mode,  erase flag here
+               pBAORIEntry->ORI_BA_Status = Originator_NONE;
+               pBAORIEntry->Token = 1;
+               // Not clear Sequence here.
+               NdisReleaseSpinLock(&pAd->BATabLock);
+       }
+}
+#endif // DOT11_N_SUPPORT //
+
+/*! \brief
+ *     \param
+ *     \return
+ *     \pre
+ *     \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID BssEntrySet(
+       IN PRTMP_ADAPTER        pAd,
+       OUT BSS_ENTRY *pBss,
+       IN PUCHAR pBssid,
+       IN CHAR Ssid[],
+       IN UCHAR SsidLen,
+       IN UCHAR BssType,
+       IN USHORT BeaconPeriod,
+       IN PCF_PARM pCfParm,
+       IN USHORT AtimWin,
+       IN USHORT CapabilityInfo,
+       IN UCHAR SupRate[],
+       IN UCHAR SupRateLen,
+       IN UCHAR ExtRate[],
+       IN UCHAR ExtRateLen,
+       IN HT_CAPABILITY_IE *pHtCapability,
+       IN ADD_HT_INFO_IE *pAddHtInfo,  // AP might use this additional ht info IE
+       IN UCHAR                        HtCapabilityLen,
+       IN UCHAR                        AddHtInfoLen,
+       IN UCHAR                        NewExtChanOffset,
+       IN UCHAR Channel,
+       IN CHAR Rssi,
+       IN LARGE_INTEGER TimeStamp,
+       IN UCHAR CkipFlag,
+       IN PEDCA_PARM pEdcaParm,
+       IN PQOS_CAPABILITY_PARM pQosCapability,
+       IN PQBSS_LOAD_PARM pQbssLoad,
+       IN USHORT LengthVIE,
+       IN PNDIS_802_11_VARIABLE_IEs pVIE)
+{
+       COPY_MAC_ADDR(pBss->Bssid, pBssid);
+       // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
+       pBss->Hidden = 1;
+       if (SsidLen > 0)
+       {
+               // For hidden SSID AP, it might send beacon with SSID len equal to 0
+               // Or send beacon /probe response with SSID len matching real SSID length,
+               // but SSID is all zero. such as "00-00-00-00" with length 4.
+               // We have to prevent this case overwrite correct table
+               if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
+               {
+                   NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
+                       NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
+                       pBss->SsidLen = SsidLen;
+                       pBss->Hidden = 0;
+               }
+       }
+       else
+               pBss->SsidLen = 0;
+       pBss->BssType = BssType;
+       pBss->BeaconPeriod = BeaconPeriod;
+       if (BssType == BSS_INFRA)
+       {
+               if (pCfParm->bValid)
+               {
+                       pBss->CfpCount = pCfParm->CfpCount;
+                       pBss->CfpPeriod = pCfParm->CfpPeriod;
+                       pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
+                       pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
+               }
+       }
+       else
+       {
+               pBss->AtimWin = AtimWin;
+       }
+
+       pBss->CapabilityInfo = CapabilityInfo;
+       // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
+       // Combine with AuthMode, they will decide the connection methods.
+       pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
+       ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
+       if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
+               NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
+       else
+               NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
+       pBss->SupRateLen = SupRateLen;
+       ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
+       NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
+       NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
+       NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
+       pBss->NewExtChanOffset = NewExtChanOffset;
+       pBss->ExtRateLen = ExtRateLen;
+       pBss->Channel = Channel;
+       pBss->CentralChannel = Channel;
+       pBss->Rssi = Rssi;
+       // Update CkipFlag. if not exists, the value is 0x0
+       pBss->CkipFlag = CkipFlag;
+
+       // New for microsoft Fixed IEs
+       NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
+       pBss->FixIEs.BeaconInterval = BeaconPeriod;
+       pBss->FixIEs.Capabilities = CapabilityInfo;
+
+       // New for microsoft Variable IEs
+       if (LengthVIE != 0)
+       {
+               pBss->VarIELen = LengthVIE;
+               NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
+       }
+       else
+       {
+               pBss->VarIELen = 0;
+       }
+
+       pBss->AddHtInfoLen = 0;
+       pBss->HtCapabilityLen = 0;
+#ifdef DOT11_N_SUPPORT
+       if (HtCapabilityLen> 0)
+       {
+               pBss->HtCapabilityLen = HtCapabilityLen;
+               NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
+               if (AddHtInfoLen > 0)
+               {
+                       pBss->AddHtInfoLen = AddHtInfoLen;
+                       NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
+
+                               if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
+                               {
+                                       pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
+                               }
+                               else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
+                               {
+                                               pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
+                               }
+               }
+       }
+#endif // DOT11_N_SUPPORT //
+
+       BssCipherParse(pBss);
+
+       // new for QOS
+       if (pEdcaParm)
+               NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
+       else
+               pBss->EdcaParm.bValid = FALSE;
+       if (pQosCapability)
+               NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
+       else
+               pBss->QosCapability.bValid = FALSE;
+       if (pQbssLoad)
+               NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
+       else
+               pBss->QbssLoad.bValid = FALSE;
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               PEID_STRUCT     pEid;
+               USHORT          Length = 0;
+
+
+               NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
+               NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
+#ifdef EXT_BUILD_CHANNEL_LIST
+               NdisZeroMemory(&pBss->CountryString[0], 3);
+               pBss->bHasCountryIE = FALSE;
+#endif // EXT_BUILD_CHANNEL_LIST //
+               pEid = (PEID_STRUCT) pVIE;
+               while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
+               {
+                       switch(pEid->Eid)
+                       {
+                               case IE_WPA:
+                                       if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
+                                       {
+                                               if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
+                                               {
+                                                       pBss->WpaIE.IELen = 0;
+                                                       break;
+                                               }
+                                               pBss->WpaIE.IELen = pEid->Len + 2;
+                                               NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
+                                       }
+                                       break;
+                case IE_RSN:
+                    if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
+                                       {
+                                               if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
+                                               {
+                                                       pBss->RsnIE.IELen = 0;
+                                                       break;
+                                               }
+                                               pBss->RsnIE.IELen = pEid->Len + 2;
+                                               NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
+                       }
+                               break;
+#ifdef EXT_BUILD_CHANNEL_LIST
+                               case IE_COUNTRY:
+                                       NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
+                                       pBss->bHasCountryIE = TRUE;
+                                       break;
+#endif // EXT_BUILD_CHANNEL_LIST //
+            }
+                       Length = Length + 2 + (USHORT)pEid->Len;  // Eid[1] + Len[1]+ content[Len]
+                       pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+}
+
+/*!
+ *     \brief insert an entry into the bss table
+ *     \param p_tab The BSS table
+ *     \param Bssid BSSID
+ *     \param ssid SSID
+ *     \param ssid_len Length of SSID
+ *     \param bss_type
+ *     \param beacon_period
+ *     \param timestamp
+ *     \param p_cf
+ *     \param atim_win
+ *     \param cap
+ *     \param rates
+ *     \param rates_len
+ *     \param channel_idx
+ *     \return none
+ *     \pre
+ *     \post
+ *     \note If SSID is identical, the old entry will be replaced by the new one
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+ULONG BssTableSetEntry(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT BSS_TABLE *Tab,
+       IN PUCHAR pBssid,
+       IN CHAR Ssid[],
+       IN UCHAR SsidLen,
+       IN UCHAR BssType,
+       IN USHORT BeaconPeriod,
+       IN CF_PARM *CfParm,
+       IN USHORT AtimWin,
+       IN USHORT CapabilityInfo,
+       IN UCHAR SupRate[],
+       IN UCHAR SupRateLen,
+       IN UCHAR ExtRate[],
+       IN UCHAR ExtRateLen,
+       IN HT_CAPABILITY_IE *pHtCapability,
+       IN ADD_HT_INFO_IE *pAddHtInfo,  // AP might use this additional ht info IE
+       IN UCHAR                        HtCapabilityLen,
+       IN UCHAR                        AddHtInfoLen,
+       IN UCHAR                        NewExtChanOffset,
+       IN UCHAR ChannelNo,
+       IN CHAR Rssi,
+       IN LARGE_INTEGER TimeStamp,
+       IN UCHAR CkipFlag,
+       IN PEDCA_PARM pEdcaParm,
+       IN PQOS_CAPABILITY_PARM pQosCapability,
+       IN PQBSS_LOAD_PARM pQbssLoad,
+       IN USHORT LengthVIE,
+       IN PNDIS_802_11_VARIABLE_IEs pVIE)
+{
+       ULONG   Idx;
+
+       Idx = BssTableSearchWithSSID(Tab, pBssid,  Ssid, SsidLen, ChannelNo);
+       if (Idx == BSS_NOT_FOUND)
+       {
+               if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
+           {
+                       //
+                       // It may happen when BSS Table was full.
+                       // The desired AP will not be added into BSS Table
+                       // In this case, if we found the desired AP then overwrite BSS Table.
+                       //
+                       if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+                       {
+                               if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
+                                       SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
+                               {
+                                       Idx = Tab->BssOverlapNr;
+                                       BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
+                                               CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
+                                               NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
+                    Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
+                               }
+                               return Idx;
+                       }
+                       else
+                       {
+                       return BSS_NOT_FOUND;
+                       }
+               }
+               Idx = Tab->BssNr;
+               BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
+                                       CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
+                                       NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
+               Tab->BssNr++;
+       }
+       else
+       {
+               BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
+                                       CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
+                                       NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
+       }
+
+       return Idx;
+}
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+VOID  TriEventInit(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       UCHAR           i;
+
+       for (i = 0;i < MAX_TRIGGER_EVENT;i++)
+               pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
+
+       pAd->CommonCfg.TriggerEventTab.EventANo = 0;
+       pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
+}
+
+ULONG TriEventTableSetEntry(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT TRIGGER_EVENT_TAB *Tab,
+       IN PUCHAR pBssid,
+       IN HT_CAPABILITY_IE *pHtCapability,
+       IN UCHAR                        HtCapabilityLen,
+       IN UCHAR                        RegClass,
+       IN UCHAR ChannelNo)
+{
+       // Event A
+       if (HtCapabilityLen == 0)
+       {
+               if (Tab->EventANo < MAX_TRIGGER_EVENT)
+               {
+                       RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
+                       Tab->EventA[Tab->EventANo].bValid = TRUE;
+                       Tab->EventA[Tab->EventANo].Channel = ChannelNo;
+                       Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
+                       if (RegClass != 0)
+                       {
+                               // Beacon has Regulatory class IE. So use beacon's
+                               Tab->EventA[Tab->EventANo].RegClass = RegClass;
+                       }
+                       else
+                       {
+                               // Use Station's Regulatory class instead.
+                               if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
+                               {
+                                       if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
+                                       {
+                                               Tab->EventA[Tab->EventANo].RegClass = 32;
+                                       }
+                                       else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
+                                               Tab->EventA[Tab->EventANo].RegClass = 33;
+                               }
+                               else
+                                       Tab->EventA[Tab->EventANo].RegClass = ??;
+
+                       }
+
+                       Tab->EventANo ++;
+               }
+       }
+       else if (pHtCapability->HtCapInfo.Intolerant40)
+       {
+               Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
+       }
+
+}
+
+/*
+       ========================================================================
+       Routine Description:
+               Trigger Event table Maintainence called once every second.
+
+       Arguments:
+       // IRQL = DISPATCH_LEVEL
+       ========================================================================
+*/
+VOID TriEventCounterMaintenance(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       UCHAR           i;
+       BOOLEAN                 bNotify = FALSE;
+       for (i = 0;i < MAX_TRIGGER_EVENT;i++)
+       {
+               if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
+               {
+                       pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
+                       if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
+                       {
+                               pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
+                               pAd->CommonCfg.TriggerEventTab.EventANo --;
+                               // Need to send 20/40 Coexistence Notify frame if has status change.
+                               bNotify = TRUE;
+                       }
+               }
+       }
+       if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
+       {
+               pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
+               if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
+                       bNotify = TRUE;
+       }
+
+       if (bNotify == TRUE)
+               Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
+}
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+// IRQL = DISPATCH_LEVEL
+VOID BssTableSsidSort(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT BSS_TABLE *OutTab,
+       IN      CHAR Ssid[],
+       IN      UCHAR SsidLen)
+{
+       INT i;
+       BssTableInit(OutTab);
+
+       for (i = 0; i < pAd->ScanTab.BssNr; i++)
+       {
+               BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
+               BOOLEAN bIsHiddenApIncluded = FALSE;
+
+               if (((pAd->CommonCfg.bIEEE80211H == 1) &&
+            (pAd->MlmeAux.Channel > 14) &&
+             RadarChannelCheck(pAd, pInBss->Channel))
+#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+             || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+#endif // CARRIER_DETECTION_SUPPORT //
+            )
+               {
+                       if (pInBss->Hidden)
+                               bIsHiddenApIncluded = TRUE;
+               }
+
+               if ((pInBss->BssType == pAd->StaCfg.BssType) &&
+                       (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
+               {
+                       BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
+
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+                       // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
+                       if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
+                               (pInBss->bHasCountryIE == FALSE))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
+                               continue;
+                       }
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+#ifdef DOT11_N_SUPPORT
+                       // 2.4G/5G N only mode
+                       if ((pInBss->HtCapabilityLen == 0) &&
+                               ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
+                               continue;
+                       }
+#endif // DOT11_N_SUPPORT //
+
+                       // New for WPA2
+                       // Check the Authmode first
+                       if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+                       {
+                               // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
+                               if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
+                                       // None matched
+                                       continue;
+
+                               // Check cipher suite, AP must have more secured cipher than station setting
+                               if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+                               {
+                                       // If it's not mixed mode, we should only let BSS pass with the same encryption
+                                       if (pInBss->WPA.bMixMode == FALSE)
+                                               if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
+                                                       continue;
+
+                                       // check group cipher
+                                       if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
+                                               (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
+                                               (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
+                                               continue;
+
+                                       // check pairwise cipher, skip if none matched
+                                       // If profile set to AES, let it pass without question.
+                                       // If profile set to TKIP, we must find one mateched
+                                       if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
+                                               (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
+                                               (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
+                                               continue;
+                               }
+                               else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+                               {
+                                       // If it's not mixed mode, we should only let BSS pass with the same encryption
+                                       if (pInBss->WPA2.bMixMode == FALSE)
+                                               if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
+                                                       continue;
+
+                                       // check group cipher
+                                       if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
+                                               (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
+                                               (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
+                                               continue;
+
+                                       // check pairwise cipher, skip if none matched
+                                       // If profile set to AES, let it pass without question.
+                                       // If profile set to TKIP, we must find one mateched
+                                       if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
+                                               (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
+                                               (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
+                                               continue;
+                               }
+                       }
+                       // Bss Type matched, SSID matched.
+                       // We will check wepstatus for qualification Bss
+                       else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
+                               //
+                               // For the SESv2 case, we will not qualify WepStatus.
+                               //
+                               if (!pInBss->bSES)
+                                       continue;
+                       }
+
+                       // Since the AP is using hidden SSID, and we are trying to connect to ANY
+                       // It definitely will fail. So, skip it.
+                       // CCX also require not even try to connect it!!
+                       if (SsidLen == 0)
+                               continue;
+
+#ifdef DOT11_N_SUPPORT
+                       // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
+                       // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
+                       if ((pInBss->CentralChannel != pInBss->Channel) &&
+                               (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
+                       {
+                               if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
+                               {
+                                       pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+                                       SetCommonHT(pAd);
+                                       pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
+                               }
+                               else
+                               {
+                                       if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
+                                       {
+                                               SetCommonHT(pAd);
+                                       }
+                               }
+                       }
+#endif // DOT11_N_SUPPORT //
+
+                       // copy matching BSS from InTab to OutTab
+                       NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
+
+                       OutTab->BssNr++;
+               }
+               else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
+               {
+                       BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
+
+
+#ifdef DOT11_N_SUPPORT
+                       // 2.4G/5G N only mode
+                       if ((pInBss->HtCapabilityLen == 0) &&
+                               ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
+                               continue;
+                       }
+#endif // DOT11_N_SUPPORT //
+
+                       // New for WPA2
+                       // Check the Authmode first
+                       if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+                       {
+                               // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
+                               if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
+                                       // None matched
+                                       continue;
+
+                               // Check cipher suite, AP must have more secured cipher than station setting
+                               if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+                               {
+                                       // If it's not mixed mode, we should only let BSS pass with the same encryption
+                                       if (pInBss->WPA.bMixMode == FALSE)
+                                               if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
+                                                       continue;
+
+                                       // check group cipher
+                                       if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
+                                               continue;
+
+                                       // check pairwise cipher, skip if none matched
+                                       // If profile set to AES, let it pass without question.
+                                       // If profile set to TKIP, we must find one mateched
+                                       if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
+                                               (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
+                                               (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
+                                               continue;
+                               }
+                               else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+                               {
+                                       // If it's not mixed mode, we should only let BSS pass with the same encryption
+                                       if (pInBss->WPA2.bMixMode == FALSE)
+                                               if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
+                                                       continue;
+
+                                       // check group cipher
+                                       if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
+                                               continue;
+
+                                       // check pairwise cipher, skip if none matched
+                                       // If profile set to AES, let it pass without question.
+                                       // If profile set to TKIP, we must find one mateched
+                                       if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
+                                               (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
+                                               (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
+                                               continue;
+                               }
+                       }
+                       // Bss Type matched, SSID matched.
+                       // We will check wepstatus for qualification Bss
+                       else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
+                                       continue;
+
+#ifdef DOT11_N_SUPPORT
+                       // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
+                       // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
+                       if ((pInBss->CentralChannel != pInBss->Channel) &&
+                               (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
+                       {
+                               if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
+                               {
+                                       pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+                                       SetCommonHT(pAd);
+                                       pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
+                               }
+                       }
+#endif // DOT11_N_SUPPORT //
+
+                       // copy matching BSS from InTab to OutTab
+                       NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
+
+                       OutTab->BssNr++;
+               }
+
+               if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
+                       break;
+       }
+
+       BssTableSortByRssi(OutTab);
+}
+
+
+// IRQL = DISPATCH_LEVEL
+VOID BssTableSortByRssi(
+       IN OUT BSS_TABLE *OutTab)
+{
+       INT       i, j;
+       BSS_ENTRY TmpBss;
+
+       for (i = 0; i < OutTab->BssNr - 1; i++)
+       {
+               for (j = i+1; j < OutTab->BssNr; j++)
+               {
+                       if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
+                       {
+                               NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
+                               NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
+                               NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
+                       }
+               }
+       }
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+VOID BssCipherParse(
+       IN OUT  PBSS_ENTRY      pBss)
+{
+       PEID_STRUCT              pEid;
+       PUCHAR                          pTmp;
+       PRSN_IE_HEADER_STRUCT                   pRsnHeader;
+       PCIPHER_SUITE_STRUCT                    pCipher;
+       PAKM_SUITE_STRUCT                               pAKM;
+       USHORT                                                  Count;
+       INT                                                             Length;
+       NDIS_802_11_ENCRYPTION_STATUS   TmpCipher;
+
+       //
+       // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
+       //
+       if (pBss->Privacy)
+       {
+               pBss->WepStatus         = Ndis802_11WEPEnabled;
+       }
+       else
+       {
+               pBss->WepStatus         = Ndis802_11WEPDisabled;
+       }
+       // Set default to disable & open authentication before parsing variable IE
+       pBss->AuthMode          = Ndis802_11AuthModeOpen;
+       pBss->AuthModeAux       = Ndis802_11AuthModeOpen;
+
+       // Init WPA setting
+       pBss->WPA.PairCipher    = Ndis802_11WEPDisabled;
+       pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
+       pBss->WPA.GroupCipher   = Ndis802_11WEPDisabled;
+       pBss->WPA.RsnCapability = 0;
+       pBss->WPA.bMixMode              = FALSE;
+
+       // Init WPA2 setting
+       pBss->WPA2.PairCipher    = Ndis802_11WEPDisabled;
+       pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
+       pBss->WPA2.GroupCipher   = Ndis802_11WEPDisabled;
+       pBss->WPA2.RsnCapability = 0;
+       pBss->WPA2.bMixMode      = FALSE;
+
+
+       Length = (INT) pBss->VarIELen;
+
+       while (Length > 0)
+       {
+               // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
+               pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
+               pEid = (PEID_STRUCT) pTmp;
+               switch (pEid->Eid)
+               {
+                       case IE_WPA:
+                               //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
+                               if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
+                               {
+                                       pTmp   += 11;
+                                       switch (*pTmp)
+                                       {
+                                               case 1:
+                                               case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
+                                                       pBss->WepStatus = Ndis802_11Encryption1Enabled;
+                                                       pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
+                                                       pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
+                                                       break;
+                                               case 2:
+                                                       pBss->WepStatus = Ndis802_11Encryption2Enabled;
+                                                       pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
+                                                       pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
+                                                       break;
+                                               case 4:
+                                                       pBss->WepStatus = Ndis802_11Encryption3Enabled;
+                                                       pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
+                                                       pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
+                                                       break;
+                                               default:
+                                                       break;
+                                       }
+
+                                       // if Cisco IE_WPA, break
+                                       break;
+                               }
+                               else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
+                               {
+                                       pBss->bSES = TRUE;
+                                       break;
+                               }
+                               else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
+                               {
+                                       // if unsupported vendor specific IE
+                                       break;
+                               }
+                               // Skip OUI, version, and multicast suite
+                               // This part should be improved in the future when AP supported multiple cipher suite.
+                               // For now, it's OK since almost all APs have fixed cipher suite supported.
+                               // pTmp = (PUCHAR) pEid->Octet;
+                               pTmp   += 11;
+
+                               // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
+                               //      Value      Meaning
+                               //      0                       None
+                               //      1                       WEP-40
+                               //      2                       Tkip
+                               //      3                       WRAP
+                               //      4                       AES
+                               //      5                       WEP-104
+                               // Parse group cipher
+                               switch (*pTmp)
+                               {
+                                       case 1:
+                                               pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
+                                               break;
+                                       case 5:
+                                               pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
+                                               break;
+                                       case 2:
+                                               pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
+                                               break;
+                                       case 4:
+                                               pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
+                                               break;
+                                       default:
+                                               break;
+                               }
+                               // number of unicast suite
+                               pTmp   += 1;
+
+                               // skip all unicast cipher suites
+                               //Count = *(PUSHORT) pTmp;
+                               Count = (pTmp[1]<<8) + pTmp[0];
+                               pTmp   += sizeof(USHORT);
+
+                               // Parsing all unicast cipher suite
+                               while (Count > 0)
+                               {
+                                       // Skip OUI
+                                       pTmp += 3;
+                                       TmpCipher = Ndis802_11WEPDisabled;
+                                       switch (*pTmp)
+                                       {
+                                               case 1:
+                                               case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
+                                                       TmpCipher = Ndis802_11Encryption1Enabled;
+                                                       break;
+                                               case 2:
+                                                       TmpCipher = Ndis802_11Encryption2Enabled;
+                                                       break;
+                                               case 4:
+                                                       TmpCipher = Ndis802_11Encryption3Enabled;
+                                                       break;
+                                               default:
+                                                       break;
+                                       }
+                                       if (TmpCipher > pBss->WPA.PairCipher)
+                                       {
+                                               // Move the lower cipher suite to PairCipherAux
+                                               pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
+                                               pBss->WPA.PairCipher    = TmpCipher;
+                                       }
+                                       else
+                                       {
+                                               pBss->WPA.PairCipherAux = TmpCipher;
+                                       }
+                                       pTmp++;
+                                       Count--;
+                               }
+
+                               // 4. get AKM suite counts
+                               //Count = *(PUSHORT) pTmp;
+                               Count = (pTmp[1]<<8) + pTmp[0];
+                               pTmp   += sizeof(USHORT);
+                               pTmp   += 3;
+
+                               switch (*pTmp)
+                               {
+                                       case 1:
+                                               // Set AP support WPA mode
+                                               if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+                                                       pBss->AuthMode = Ndis802_11AuthModeWPA;
+                                               else
+                                                       pBss->AuthModeAux = Ndis802_11AuthModeWPA;
+                                               break;
+                                       case 2:
+                                               // Set AP support WPA mode
+                                               if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+                                                       pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
+                                               else
+                                                       pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
+                                               break;
+                                       default:
+                                               break;
+                               }
+                               pTmp   += 1;
+
+                               // Fixed for WPA-None
+                               if (pBss->BssType == BSS_ADHOC)
+                               {
+                                       pBss->AuthMode    = Ndis802_11AuthModeWPANone;
+                                       pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
+                                       pBss->WepStatus   = pBss->WPA.GroupCipher;
+                                       // Patched bugs for old driver
+                                       if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
+                                               pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
+                               }
+                               else
+                                       pBss->WepStatus   = pBss->WPA.PairCipher;
+
+                               // Check the Pair & Group, if different, turn on mixed mode flag
+                               if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
+                                       pBss->WPA.bMixMode = TRUE;
+
+                               break;
+
+                       case IE_RSN:
+                               pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
+
+                               // 0. Version must be 1
+                               if (le2cpu16(pRsnHeader->Version) != 1)
+                                       break;
+                               pTmp   += sizeof(RSN_IE_HEADER_STRUCT);
+
+                               // 1. Check group cipher
+                               pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
+                               if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
+                                       break;
+
+                               // Parse group cipher
+                               switch (pCipher->Type)
+                               {
+                                       case 1:
+                                               pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
+                                               break;
+                                       case 5:
+                                               pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
+                                               break;
+                                       case 2:
+                                               pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
+                                               break;
+                                       case 4:
+                                               pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
+                                               break;
+                                       default:
+                                               break;
+                               }
+                               // set to correct offset for next parsing
+                               pTmp   += sizeof(CIPHER_SUITE_STRUCT);
+
+                               // 2. Get pairwise cipher counts
+                               //Count = *(PUSHORT) pTmp;
+                               Count = (pTmp[1]<<8) + pTmp[0];
+                               pTmp   += sizeof(USHORT);
+
+                               // 3. Get pairwise cipher
+                               // Parsing all unicast cipher suite
+                               while (Count > 0)
+                               {
+                                       // Skip OUI
+                                       pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
+                                       TmpCipher = Ndis802_11WEPDisabled;
+                                       switch (pCipher->Type)
+                                       {
+                                               case 1:
+                                               case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
+                                                       TmpCipher = Ndis802_11Encryption1Enabled;
+                                                       break;
+                                               case 2:
+                                                       TmpCipher = Ndis802_11Encryption2Enabled;
+                                                       break;
+                                               case 4:
+                                                       TmpCipher = Ndis802_11Encryption3Enabled;
+                                                       break;
+                                               default:
+                                                       break;
+                                       }
+                                       if (TmpCipher > pBss->WPA2.PairCipher)
+                                       {
+                                               // Move the lower cipher suite to PairCipherAux
+                                               pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
+                                               pBss->WPA2.PairCipher    = TmpCipher;
+                                       }
+                                       else
+                                       {
+                                               pBss->WPA2.PairCipherAux = TmpCipher;
+                                       }
+                                       pTmp += sizeof(CIPHER_SUITE_STRUCT);
+                                       Count--;
+                               }
+
+                               // 4. get AKM suite counts
+                               //Count = *(PUSHORT) pTmp;
+                               Count = (pTmp[1]<<8) + pTmp[0];
+                               pTmp   += sizeof(USHORT);
+
+                               // 5. Get AKM ciphers
+                               pAKM = (PAKM_SUITE_STRUCT) pTmp;
+                               if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
+                                       break;
+
+                               switch (pAKM->Type)
+                               {
+                                       case 1:
+                                               // Set AP support WPA mode
+                                               if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+                                                       pBss->AuthMode = Ndis802_11AuthModeWPA2;
+                                               else
+                                                       pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
+                                               break;
+                                       case 2:
+                                               // Set AP support WPA mode
+                                               if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+                                                       pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
+                                               else
+                                                       pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
+                                               break;
+                                       default:
+                                               break;
+                               }
+                               pTmp   += (Count * sizeof(AKM_SUITE_STRUCT));
+
+                               // Fixed for WPA-None
+                               if (pBss->BssType == BSS_ADHOC)
+                               {
+                                       pBss->AuthMode = Ndis802_11AuthModeWPANone;
+                                       pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
+                                       pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
+                                       pBss->WPA.GroupCipher   = pBss->WPA2.GroupCipher;
+                                       pBss->WepStatus                 = pBss->WPA.GroupCipher;
+                                       // Patched bugs for old driver
+                                       if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
+                                               pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
+                               }
+                               pBss->WepStatus   = pBss->WPA2.PairCipher;
+
+                               // 6. Get RSN capability
+                               //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
+                               pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
+                               pTmp += sizeof(USHORT);
+
+                               // Check the Pair & Group, if different, turn on mixed mode flag
+                               if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
+                                       pBss->WPA2.bMixMode = TRUE;
+
+                               break;
+                       default:
+                               break;
+               }
+               Length -= (pEid->Len + 2);
+       }
+}
+
+// ===========================================================================================
+// mac_table.c
+// ===========================================================================================
+
+/*! \brief generates a random mac address value for IBSS BSSID
+ *     \param Addr the bssid location
+ *     \return none
+ *     \pre
+ *     \post
+ */
+VOID MacAddrRandomBssid(
+       IN PRTMP_ADAPTER pAd,
+       OUT PUCHAR pAddr)
+{
+       INT i;
+
+       for (i = 0; i < MAC_ADDR_LEN; i++)
+       {
+               pAddr[i] = RandomByte(pAd);
+       }
+
+       pAddr[0] = (pAddr[0] & 0xfe) | 0x02;  // the first 2 bits must be 01xxxxxxxx
+}
+
+/*! \brief init the management mac frame header
+ *     \param p_hdr mac header
+ *     \param subtype subtype of the frame
+ *     \param p_ds destination address, don't care if it is a broadcast address
+ *     \return none
+ *     \pre the station has the following information in the pAd->StaCfg
+ *      - bssid
+ *      - station address
+ *     \post
+ *     \note this function initializes the following field
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID MgtMacHeaderInit(
+       IN      PRTMP_ADAPTER   pAd,
+       IN OUT PHEADER_802_11 pHdr80211,
+       IN UCHAR SubType,
+       IN UCHAR ToDs,
+       IN PUCHAR pDA,
+       IN PUCHAR pBssid)
+{
+       NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
+
+       pHdr80211->FC.Type = BTYPE_MGMT;
+       pHdr80211->FC.SubType = SubType;
+//     if (SubType == SUBTYPE_ACK)     // sample, no use, it will conflict with ACTION frame sub type
+//             pHdr80211->FC.Type = BTYPE_CNTL;
+       pHdr80211->FC.ToDs = ToDs;
+       COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
+#endif // CONFIG_STA_SUPPORT //
+       COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
+}
+
+// ===========================================================================================
+// mem_mgmt.c
+// ===========================================================================================
+
+/*!***************************************************************************
+ * This routine build an outgoing frame, and fill all information specified
+ * in argument list to the frame body. The actual frame size is the summation
+ * of all arguments.
+ * input params:
+ *             Buffer - pointer to a pre-allocated memory segment
+ *             args - a list of <int arg_size, arg> pairs.
+ *             NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
+ *                                                function will FAIL!!!
+ * return:
+ *             Size of the buffer
+ * usage:
+ *             MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ****************************************************************************/
+ULONG MakeOutgoingFrame(
+       OUT CHAR *Buffer,
+       OUT ULONG *FrameLen, ...)
+{
+       CHAR   *p;
+       int     leng;
+       ULONG   TotLeng;
+       va_list Args;
+
+       // calculates the total length
+       TotLeng = 0;
+       va_start(Args, FrameLen);
+       do
+       {
+               leng = va_arg(Args, int);
+               if (leng == END_OF_ARGS)
+               {
+                       break;
+               }
+               p = va_arg(Args, PVOID);
+               NdisMoveMemory(&Buffer[TotLeng], p, leng);
+               TotLeng = TotLeng + leng;
+       } while(TRUE);
+
+       va_end(Args); /* clean up */
+       *FrameLen = TotLeng;
+       return TotLeng;
+}
+
+// ===========================================================================================
+// mlme_queue.c
+// ===========================================================================================
+
+/*! \brief     Initialize The MLME Queue, used by MLME Functions
+ *     \param  *Queue     The MLME Queue
+ *     \return Always     Return NDIS_STATE_SUCCESS in this implementation
+ *     \pre
+ *     \post
+ *     \note   Because this is done only once (at the init stage), no need to be locked
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+NDIS_STATUS MlmeQueueInit(
+       IN MLME_QUEUE *Queue)
+{
+       INT i;
+
+       NdisAllocateSpinLock(&Queue->Lock);
+
+       Queue->Num      = 0;
+       Queue->Head = 0;
+       Queue->Tail = 0;
+
+       for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
+       {
+               Queue->Entry[i].Occupied = FALSE;
+               Queue->Entry[i].MsgLen = 0;
+               NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
+       }
+
+       return NDIS_STATUS_SUCCESS;
+}
+
+/*! \brief      Enqueue a message for other threads, if they want to send messages to MLME thread
+ *     \param  *Queue    The MLME Queue
+ *     \param   Machine  The State Machine Id
+ *     \param   MsgType  The Message Type
+ *     \param   MsgLen   The Message length
+ *     \param  *Msg      The message pointer
+ *     \return  TRUE if enqueue is successful, FALSE if the queue is full
+ *     \pre
+ *     \post
+ *     \note    The message has to be initialized
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeEnqueue(
+       IN      PRTMP_ADAPTER   pAd,
+       IN ULONG Machine,
+       IN ULONG MsgType,
+       IN ULONG MsgLen,
+       IN VOID *Msg)
+{
+       INT Tail;
+       MLME_QUEUE      *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
+
+       // Do nothing if the driver is starting halt state.
+       // This might happen when timer already been fired before cancel timer with mlmehalt
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+               return FALSE;
+
+       // First check the size, it MUST not exceed the mlme queue size
+       if (MsgLen > MGMT_DMA_BUFFER_SIZE)
+       {
+               DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
+               return FALSE;
+       }
+
+       if (MlmeQueueFull(Queue))
+       {
+               return FALSE;
+       }
+
+       NdisAcquireSpinLock(&(Queue->Lock));
+       Tail = Queue->Tail;
+       Queue->Tail++;
+       Queue->Num++;
+       if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
+       {
+               Queue->Tail = 0;
+       }
+
+       Queue->Entry[Tail].Wcid = RESERVED_WCID;
+       Queue->Entry[Tail].Occupied = TRUE;
+       Queue->Entry[Tail].Machine = Machine;
+       Queue->Entry[Tail].MsgType = MsgType;
+       Queue->Entry[Tail].MsgLen  = MsgLen;
+
+       if (Msg != NULL)
+       {
+               NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
+       }
+
+       NdisReleaseSpinLock(&(Queue->Lock));
+       return TRUE;
+}
+
+/*! \brief      This function is used when Recv gets a MLME message
+ *     \param  *Queue                   The MLME Queue
+ *     \param   TimeStampHigh   The upper 32 bit of timestamp
+ *     \param   TimeStampLow    The lower 32 bit of timestamp
+ *     \param   Rssi                    The receiving RSSI strength
+ *     \param   MsgLen                  The length of the message
+ *     \param  *Msg                     The message pointer
+ *     \return  TRUE if everything ok, FALSE otherwise (like Queue Full)
+ *     \pre
+ *     \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeEnqueueForRecv(
+       IN      PRTMP_ADAPTER   pAd,
+       IN ULONG Wcid,
+       IN ULONG TimeStampHigh,
+       IN ULONG TimeStampLow,
+       IN UCHAR Rssi0,
+       IN UCHAR Rssi1,
+       IN UCHAR Rssi2,
+       IN ULONG MsgLen,
+       IN VOID *Msg,
+       IN UCHAR Signal)
+{
+       INT              Tail, Machine;
+       PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+       INT              MsgType;
+       MLME_QUEUE      *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
+
+#ifdef RALINK_ATE
+       /* Nothing to do in ATE mode */
+       if(ATE_ON(pAd))
+               return FALSE;
+#endif // RALINK_ATE //
+
+       // Do nothing if the driver is starting halt state.
+       // This might happen when timer already been fired before cancel timer with mlmehalt
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+       {
+               DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
+               return FALSE;
+       }
+
+       // First check the size, it MUST not exceed the mlme queue size
+       if (MsgLen > MGMT_DMA_BUFFER_SIZE)
+       {
+               DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
+               return FALSE;
+       }
+
+       if (MlmeQueueFull(Queue))
+       {
+               return FALSE;
+       }
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
+               {
+                       DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
+                       return FALSE;
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       // OK, we got all the informations, it is time to put things into queue
+       NdisAcquireSpinLock(&(Queue->Lock));
+       Tail = Queue->Tail;
+       Queue->Tail++;
+       Queue->Num++;
+       if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
+       {
+               Queue->Tail = 0;
+       }
+       Queue->Entry[Tail].Occupied = TRUE;
+       Queue->Entry[Tail].Machine = Machine;
+       Queue->Entry[Tail].MsgType = MsgType;
+       Queue->Entry[Tail].MsgLen  = MsgLen;
+       Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
+       Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
+       Queue->Entry[Tail].Rssi0 = Rssi0;
+       Queue->Entry[Tail].Rssi1 = Rssi1;
+       Queue->Entry[Tail].Rssi2 = Rssi2;
+       Queue->Entry[Tail].Signal = Signal;
+       Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
+
+       Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
+
+       if (Msg != NULL)
+       {
+               NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
+       }
+
+       NdisReleaseSpinLock(&(Queue->Lock));
+
+       RT28XX_MLME_HANDLER(pAd);
+
+       return TRUE;
+}
+
+
+/*! \brief      Dequeue a message from the MLME Queue
+ *     \param  *Queue    The MLME Queue
+ *     \param  *Elem     The message dequeued from MLME Queue
+ *     \return  TRUE if the Elem contains something, FALSE otherwise
+ *     \pre
+ *     \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeDequeue(
+       IN MLME_QUEUE *Queue,
+       OUT MLME_QUEUE_ELEM **Elem)
+{
+       NdisAcquireSpinLock(&(Queue->Lock));
+       *Elem = &(Queue->Entry[Queue->Head]);
+       Queue->Num--;
+       Queue->Head++;
+       if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
+       {
+               Queue->Head = 0;
+       }
+       NdisReleaseSpinLock(&(Queue->Lock));
+       return TRUE;
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID   MlmeRestartStateMachine(
+       IN      PRTMP_ADAPTER   pAd)
+{
+#ifdef CONFIG_STA_SUPPORT
+       BOOLEAN                         Cancelled;
+#endif // CONFIG_STA_SUPPORT //
+
+       DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+#ifdef QOS_DLS_SUPPORT
+               UCHAR i;
+#endif // QOS_DLS_SUPPORT //
+               // Cancel all timer events
+               // Be careful to cancel new added timer
+               RTMPCancelTimer(&pAd->MlmeAux.AssocTimer,         &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer,   &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer,  &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.AuthTimer,           &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer,         &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.ScanTimer,           &Cancelled);
+
+#ifdef QOS_DLS_SUPPORT
+               for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
+               {
+                       RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
+               }
+#endif // QOS_DLS_SUPPORT //
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       // Change back to original channel in case of doing scan
+       AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+       AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+
+       // Resume MSDU which is turned off durning scan
+       RTMPResumeMsduTransmission(pAd);
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // Set all state machines back IDLE
+               pAd->Mlme.CntlMachine.CurrState    = CNTL_IDLE;
+               pAd->Mlme.AssocMachine.CurrState   = ASSOC_IDLE;
+               pAd->Mlme.AuthMachine.CurrState    = AUTH_REQ_IDLE;
+               pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
+               pAd->Mlme.SyncMachine.CurrState    = SYNC_IDLE;
+               pAd->Mlme.ActMachine.CurrState    = ACT_IDLE;
+#ifdef QOS_DLS_SUPPORT
+               pAd->Mlme.DlsMachine.CurrState    = DLS_IDLE;
+#endif // QOS_DLS_SUPPORT //
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+}
+
+/*! \brief     test if the MLME Queue is empty
+ *     \param  *Queue    The MLME Queue
+ *     \return TRUE if the Queue is empty, FALSE otherwise
+ *     \pre
+ *     \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeQueueEmpty(
+       IN MLME_QUEUE *Queue)
+{
+       BOOLEAN Ans;
+
+       NdisAcquireSpinLock(&(Queue->Lock));
+       Ans = (Queue->Num == 0);
+       NdisReleaseSpinLock(&(Queue->Lock));
+
+       return Ans;
+}
+
+/*! \brief      test if the MLME Queue is full
+ *     \param   *Queue          The MLME Queue
+ *     \return  TRUE if the Queue is empty, FALSE otherwise
+ *     \pre
+ *     \post
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeQueueFull(
+       IN MLME_QUEUE *Queue)
+{
+       BOOLEAN Ans;
+
+       NdisAcquireSpinLock(&(Queue->Lock));
+       Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
+       NdisReleaseSpinLock(&(Queue->Lock));
+
+       return Ans;
+}
+
+/*! \brief      The destructor of MLME Queue
+ *     \param
+ *     \return
+ *     \pre
+ *     \post
+ *     \note   Clear Mlme Queue, Set Queue->Num to Zero.
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+VOID MlmeQueueDestroy(
+       IN MLME_QUEUE *pQueue)
+{
+       NdisAcquireSpinLock(&(pQueue->Lock));
+       pQueue->Num  = 0;
+       pQueue->Head = 0;
+       pQueue->Tail = 0;
+       NdisReleaseSpinLock(&(pQueue->Lock));
+       NdisFreeSpinLock(&(pQueue->Lock));
+}
+
+/*! \brief      To substitute the message type if the message is coming from external
+ *     \param  pFrame             The frame received
+ *     \param  *Machine           The state machine
+ *     \param  *MsgType           the message type for the state machine
+ *     \return TRUE if the substitution is successful, FALSE otherwise
+ *     \pre
+ *     \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+#ifdef CONFIG_STA_SUPPORT
+BOOLEAN MsgTypeSubst(
+       IN PRTMP_ADAPTER  pAd,
+       IN PFRAME_802_11 pFrame,
+       OUT INT *Machine,
+       OUT INT *MsgType)
+{
+       USHORT  Seq;
+       UCHAR   EAPType;
+       PUCHAR  pData;
+
+       // Pointer to start of data frames including SNAP header
+       pData = (PUCHAR) pFrame + LENGTH_802_11;
+
+       // The only data type will pass to this function is EAPOL frame
+       if (pFrame->Hdr.FC.Type == BTYPE_DATA)
+       {
+               if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
+               {
+                       // Cisco Aironet SNAP header
+                       *Machine = AIRONET_STATE_MACHINE;
+                       *MsgType = MT2_AIRONET_MSG;
+                       return (TRUE);
+               }
+#ifdef LEAP_SUPPORT
+               if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
+               {
+                       // LEAP frames
+                       *Machine = LEAP_STATE_MACHINE;
+                       EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
+                       return (LeapMsgTypeSubst(EAPType, MsgType));
+               }
+               else
+#endif // LEAP_SUPPORT //
+               {
+                       *Machine = WPA_PSK_STATE_MACHINE;
+                       EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
+                       return(WpaMsgTypeSubst(EAPType, MsgType));
+               }
+       }
+
+       switch (pFrame->Hdr.FC.SubType)
+       {
+               case SUBTYPE_ASSOC_REQ:
+                       *Machine = ASSOC_STATE_MACHINE;
+                       *MsgType = MT2_PEER_ASSOC_REQ;
+                       break;
+               case SUBTYPE_ASSOC_RSP:
+                       *Machine = ASSOC_STATE_MACHINE;
+                       *MsgType = MT2_PEER_ASSOC_RSP;
+                       break;
+               case SUBTYPE_REASSOC_REQ:
+                       *Machine = ASSOC_STATE_MACHINE;
+                       *MsgType = MT2_PEER_REASSOC_REQ;
+                       break;
+               case SUBTYPE_REASSOC_RSP:
+                       *Machine = ASSOC_STATE_MACHINE;
+                       *MsgType = MT2_PEER_REASSOC_RSP;
+                       break;
+               case SUBTYPE_PROBE_REQ:
+                       *Machine = SYNC_STATE_MACHINE;
+                       *MsgType = MT2_PEER_PROBE_REQ;
+                       break;
+               case SUBTYPE_PROBE_RSP:
+                       *Machine = SYNC_STATE_MACHINE;
+                       *MsgType = MT2_PEER_PROBE_RSP;
+                       break;
+               case SUBTYPE_BEACON:
+                       *Machine = SYNC_STATE_MACHINE;
+                       *MsgType = MT2_PEER_BEACON;
+                       break;
+               case SUBTYPE_ATIM:
+                       *Machine = SYNC_STATE_MACHINE;
+                       *MsgType = MT2_PEER_ATIM;
+                       break;
+               case SUBTYPE_DISASSOC:
+                       *Machine = ASSOC_STATE_MACHINE;
+                       *MsgType = MT2_PEER_DISASSOC_REQ;
+                       break;
+               case SUBTYPE_AUTH:
+                       // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
+                       NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
+                       if (Seq == 1 || Seq == 3)
+                       {
+                               *Machine = AUTH_RSP_STATE_MACHINE;
+                               *MsgType = MT2_PEER_AUTH_ODD;
+                       }
+                       else if (Seq == 2 || Seq == 4)
+                       {
+                               *Machine = AUTH_STATE_MACHINE;
+                               *MsgType = MT2_PEER_AUTH_EVEN;
+                       }
+                       else
+                       {
+                               return FALSE;
+                       }
+                       break;
+               case SUBTYPE_DEAUTH:
+                       *Machine = AUTH_RSP_STATE_MACHINE;
+                       *MsgType = MT2_PEER_DEAUTH;
+                       break;
+               case SUBTYPE_ACTION:
+                       *Machine = ACTION_STATE_MACHINE;
+                       //  Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
+                       if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
+                       {
+                               *MsgType = MT2_ACT_INVALID;
+                       }
+                       else
+                       {
+                               *MsgType = (pFrame->Octet[0]&0x7F);
+                       }
+                       break;
+               default:
+                       return FALSE;
+                       break;
+       }
+
+       return TRUE;
+}
+#endif // CONFIG_STA_SUPPORT //
+
+// ===========================================================================================
+// state_machine.c
+// ===========================================================================================
+
+/*! \brief Initialize the state machine.
+ *     \param *S                       pointer to the state machine
+ *     \param  Trans           State machine transition function
+ *     \param  StNr            number of states
+ *     \param  MsgNr           number of messages
+ *     \param  DefFunc         default function, when there is invalid state/message combination
+ *     \param  InitState       initial state of the state machine
+ *     \param  Base            StateMachine base, internal use only
+ *     \pre p_sm should be a legal pointer
+ *     \post
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+VOID StateMachineInit(
+       IN STATE_MACHINE *S,
+       IN STATE_MACHINE_FUNC Trans[],
+       IN ULONG StNr,
+       IN ULONG MsgNr,
+       IN STATE_MACHINE_FUNC DefFunc,
+       IN ULONG InitState,
+       IN ULONG Base)
+{
+       ULONG i, j;
+
+       // set number of states and messages
+       S->NrState = StNr;
+       S->NrMsg   = MsgNr;
+       S->Base    = Base;
+
+       S->TransFunc  = Trans;
+
+       // init all state transition to default function
+       for (i = 0; i < StNr; i++)
+       {
+               for (j = 0; j < MsgNr; j++)
+               {
+                       S->TransFunc[i * MsgNr + j] = DefFunc;
+               }
+       }
+
+       // set the starting state
+       S->CurrState = InitState;
+}
+
+/*! \brief This function fills in the function pointer into the cell in the state machine
+ *     \param *S       pointer to the state machine
+ *     \param St       state
+ *     \param Msg      incoming message
+ *     \param f        the function to be executed when (state, message) combination occurs at the state machine
+ *     \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state
+ *     \post
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+VOID StateMachineSetAction(
+       IN STATE_MACHINE *S,
+       IN ULONG St,
+       IN ULONG Msg,
+       IN STATE_MACHINE_FUNC Func)
+{
+       ULONG MsgIdx;
+
+       MsgIdx = Msg - S->Base;
+
+       if (St < S->NrState && MsgIdx < S->NrMsg)
+       {
+               // boundary checking before setting the action
+               S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
+       }
+}
+
+/*! \brief      This function does the state transition
+ *     \param   *Adapter the NIC adapter pointer
+ *     \param   *S       the state machine
+ *     \param   *Elem    the message to be executed
+ *     \return   None
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID StateMachinePerformAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN STATE_MACHINE *S,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
+}
+
+/*
+       ==========================================================================
+       Description:
+               The drop function, when machine executes this, the message is simply
+               ignored. This function does nothing, the message is freed in
+               StateMachinePerformAction()
+       ==========================================================================
+ */
+VOID Drop(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+// ===========================================================================================
+// lfsr.c
+// ===========================================================================================
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = PASSIVE_LEVEL
+
+       ==========================================================================
+ */
+VOID LfsrInit(
+       IN PRTMP_ADAPTER pAd,
+       IN ULONG Seed)
+{
+       if (Seed == 0)
+               pAd->Mlme.ShiftReg = 1;
+       else
+               pAd->Mlme.ShiftReg = Seed;
+}
+
+/*
+       ==========================================================================
+       Description:
+       ==========================================================================
+ */
+UCHAR RandomByte(
+       IN PRTMP_ADAPTER pAd)
+{
+       ULONG i;
+       UCHAR R, Result;
+
+       R = 0;
+
+       if (pAd->Mlme.ShiftReg == 0)
+       NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
+
+       for (i = 0; i < 8; i++)
+       {
+               if (pAd->Mlme.ShiftReg & 0x00000001)
+               {
+                       pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
+                       Result = 1;
+               }
+               else
+               {
+                       pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
+                       Result = 0;
+               }
+               R = (R << 1) | Result;
+       }
+
+       return R;
+}
+
+VOID AsicUpdateAutoFallBackTable(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pRateTable)
+{
+       UCHAR                                   i;
+       HT_FBK_CFG0_STRUC               HtCfg0;
+       HT_FBK_CFG1_STRUC               HtCfg1;
+       LG_FBK_CFG0_STRUC               LgCfg0;
+       LG_FBK_CFG1_STRUC               LgCfg1;
+       PRTMP_TX_RATE_SWITCH    pCurrTxRate, pNextTxRate;
+
+       // set to initial value
+       HtCfg0.word = 0x65432100;
+       HtCfg1.word = 0xedcba988;
+       LgCfg0.word = 0xedcba988;
+       LgCfg1.word = 0x00002100;
+
+       pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
+       for (i = 1; i < *((PUCHAR) pRateTable); i++)
+       {
+               pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
+               switch (pCurrTxRate->Mode)
+               {
+                       case 0:         //CCK
+                               break;
+                       case 1:         //OFDM
+                               {
+                                       switch(pCurrTxRate->CurrMCS)
+                                       {
+                                               case 0:
+                                                       LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+                                                       break;
+                                               case 1:
+                                                       LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+                                                       break;
+                                               case 2:
+                                                       LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+                                                       break;
+                                               case 3:
+                                                       LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+                                                       break;
+                                               case 4:
+                                                       LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+                                                       break;
+                                               case 5:
+                                                       LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+                                                       break;
+                                               case 6:
+                                                       LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+                                                       break;
+                                               case 7:
+                                                       LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+                                                       break;
+                                       }
+                               }
+                               break;
+#ifdef DOT11_N_SUPPORT
+                       case 2:         //HT-MIX
+                       case 3:         //HT-GF
+                               {
+                                       if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
+                                       {
+                                               switch(pCurrTxRate->CurrMCS)
+                                               {
+                                                       case 0:
+                                                               HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 1:
+                                                               HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 2:
+                                                               HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 3:
+                                                               HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 4:
+                                                               HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 5:
+                                                               HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 6:
+                                                               HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 7:
+                                                               HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 8:
+                                                               HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 9:
+                                                               HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 10:
+                                                               HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 11:
+                                                               HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 12:
+                                                               HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 13:
+                                                               HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 14:
+                                                               HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       case 15:
+                                                               HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
+                                                               break;
+                                                       default:
+                                                               DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
+                                               }
+                                       }
+                               }
+                               break;
+#endif // DOT11_N_SUPPORT //
+               }
+
+               pNextTxRate = pCurrTxRate;
+       }
+
+       RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
+       RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
+       RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
+       RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Set MAC register value according operation mode.
+               OperationMode AND bNonGFExist are for MM and GF Proteciton.
+               If MM or GF mask is not set, those passing argument doesn't not take effect.
+
+               Operation mode meaning:
+               = 0 : Pure HT, no preotection.
+               = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
+               = 0x10: No Transmission in 40M is protected.
+               = 0x11: Transmission in both 40M and 20M shall be protected
+               if (bNonGFExist)
+                       we should choose not to use GF. But still set correct ASIC registers.
+       ========================================================================
+*/
+VOID   AsicUpdateProtect(
+       IN              PRTMP_ADAPTER   pAd,
+       IN              USHORT                  OperationMode,
+       IN              UCHAR                   SetMask,
+       IN              BOOLEAN                 bDisableBGProtect,
+       IN              BOOLEAN                 bNonGFExist)
+{
+       PROT_CFG_STRUC  ProtCfg, ProtCfg4;
+       UINT32 Protect[6];
+       USHORT                  offset;
+       UCHAR                   i;
+       UINT32 MacReg = 0;
+
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+#ifdef DOT11_N_SUPPORT
+       if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
+       {
+               return;
+       }
+
+       if (pAd->BATable.numAsOriginator)
+       {
+               //
+               // enable the RTS/CTS to avoid channel collision
+               //
+               SetMask = ALLN_SETPROTECT;
+               OperationMode = 8;
+       }
+#endif // DOT11_N_SUPPORT //
+
+       // Config ASIC RTS threshold register
+       RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
+       MacReg &= 0xFF0000FF;
+#if 0
+       MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
+#else
+       // If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
+        if ((
+#ifdef DOT11_N_SUPPORT
+                       (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
+#endif // DOT11_N_SUPPORT //
+                       (pAd->CommonCfg.bAggregationCapable == TRUE))
+            && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
+        {
+                       MacReg |= (0x1000 << 8);
+        }
+        else
+        {
+                       MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
+        }
+#endif
+
+       RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
+
+       // Initial common protection settings
+       RTMPZeroMemory(Protect, sizeof(Protect));
+       ProtCfg4.word = 0;
+       ProtCfg.word = 0;
+       ProtCfg.field.TxopAllowGF40 = 1;
+       ProtCfg.field.TxopAllowGF20 = 1;
+       ProtCfg.field.TxopAllowMM40 = 1;
+       ProtCfg.field.TxopAllowMM20 = 1;
+       ProtCfg.field.TxopAllowOfdm = 1;
+       ProtCfg.field.TxopAllowCck = 1;
+       ProtCfg.field.RTSThEn = 1;
+       ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+
+       // update PHY mode and rate
+       if (pAd->CommonCfg.Channel > 14)
+               ProtCfg.field.ProtectRate = 0x4000;
+       ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
+
+       // Handle legacy(B/G) protection
+       if (bDisableBGProtect)
+       {
+               //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
+               ProtCfg.field.ProtectCtrl = 0;
+               Protect[0] = ProtCfg.word;
+               Protect[1] = ProtCfg.word;
+       }
+       else
+       {
+               //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
+               ProtCfg.field.ProtectCtrl = 0;                  // CCK do not need to be protected
+               Protect[0] = ProtCfg.word;
+               ProtCfg.field.ProtectCtrl = ASIC_CTS;   // OFDM needs using CCK to protect
+               Protect[1] = ProtCfg.word;
+       }
+
+#ifdef DOT11_N_SUPPORT
+       // Decide HT frame protection.
+       if ((SetMask & ALLN_SETPROTECT) != 0)
+       {
+               switch(OperationMode)
+               {
+                       case 0x0:
+                               // NO PROTECT
+                               // 1.All STAs in the BSS are 20/40 MHz HT
+                               // 2. in ai 20/40MHz BSS
+                               // 3. all STAs are 20MHz in a 20MHz BSS
+                               // Pure HT. no protection.
+
+                               // MM20_PROT_CFG
+                               //      Reserved (31:27)
+                               //      PROT_TXOP(25:20) -- 010111
+                               //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
+                               //  PROT_CTRL(17:16) -- 00 (None)
+                               //      PROT_RATE(15:0)  -- 0x4004 (OFDM 24M)
+                               Protect[2] = 0x01744004;
+
+                               // MM40_PROT_CFG
+                               //      Reserved (31:27)
+                               //      PROT_TXOP(25:20) -- 111111
+                               //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
+                               //  PROT_CTRL(17:16) -- 00 (None)
+                               //      PROT_RATE(15:0)  -- 0x4084 (duplicate OFDM 24M)
+                               Protect[3] = 0x03f44084;
+
+                               // CF20_PROT_CFG
+                               //      Reserved (31:27)
+                               //      PROT_TXOP(25:20) -- 010111
+                               //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
+                               //  PROT_CTRL(17:16) -- 00 (None)
+                               //      PROT_RATE(15:0)  -- 0x4004 (OFDM 24M)
+                               Protect[4] = 0x01744004;
+
+                               // CF40_PROT_CFG
+                               //      Reserved (31:27)
+                               //      PROT_TXOP(25:20) -- 111111
+                               //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
+                               //  PROT_CTRL(17:16) -- 00 (None)
+                               //      PROT_RATE(15:0)  -- 0x4084 (duplicate OFDM 24M)
+                               Protect[5] = 0x03f44084;
+
+                               if (bNonGFExist)
+                               {
+                                       // PROT_NAV(19:18)  -- 01 (Short NAV protectiion)
+                                       // PROT_CTRL(17:16) -- 01 (RTS/CTS)
+                                       Protect[4] = 0x01754004;
+                                       Protect[5] = 0x03f54084;
+                               }
+                               pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
+                               break;
+
+                       case 1:
+                               // This is "HT non-member protection mode."
+                               // If there may be non-HT STAs my BSS
+                               ProtCfg.word = 0x01744004;      // PROT_CTRL(17:16) : 0 (None)
+                               ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
+                               if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
+                               {
+                                       ProtCfg.word = 0x01740003;      //ERP use Protection bit is set, use protection rate at Clause 18..
+                                       ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
+                               }
+                               //Assign Protection method for 20&40 MHz packets
+                               ProtCfg.field.ProtectCtrl = ASIC_RTS;
+                               ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+                               ProtCfg4.field.ProtectCtrl = ASIC_RTS;
+                               ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
+                               Protect[2] = ProtCfg.word;
+                               Protect[3] = ProtCfg4.word;
+                               Protect[4] = ProtCfg.word;
+                               Protect[5] = ProtCfg4.word;
+                               pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
+                               break;
+
+                       case 2:
+                               // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
+                               ProtCfg.word = 0x01744004;  // PROT_CTRL(17:16) : 0 (None)
+                               ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
+
+                               //Assign Protection method for 40MHz packets
+                               ProtCfg4.field.ProtectCtrl = ASIC_RTS;
+                               ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
+                               Protect[2] = ProtCfg.word;
+                               Protect[3] = ProtCfg4.word;
+                               if (bNonGFExist)
+                               {
+                                       ProtCfg.field.ProtectCtrl = ASIC_RTS;
+                                       ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+                               }
+                               Protect[4] = ProtCfg.word;
+                               Protect[5] = ProtCfg4.word;
+
+                               pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
+                               break;
+
+                       case 3:
+                               // HT mixed mode.        PROTECT ALL!
+                               // Assign Rate
+                               ProtCfg.word = 0x01744004;      //duplicaet legacy 24M. BW set 1.
+                               ProtCfg4.word = 0x03f44084;
+                               // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
+                               if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
+                               {
+                                       ProtCfg.word = 0x01740003;      //ERP use Protection bit is set, use protection rate at Clause 18..
+                                       ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
+                               }
+                               //Assign Protection method for 20&40 MHz packets
+                               ProtCfg.field.ProtectCtrl = ASIC_RTS;
+                               ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+                               ProtCfg4.field.ProtectCtrl = ASIC_RTS;
+                               ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
+                               Protect[2] = ProtCfg.word;
+                               Protect[3] = ProtCfg4.word;
+                               Protect[4] = ProtCfg.word;
+                               Protect[5] = ProtCfg4.word;
+                               pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
+                               break;
+
+                       case 8:
+                               // Special on for Atheros problem n chip.
+                               Protect[2] = 0x01754004;
+                               Protect[3] = 0x03f54084;
+                               Protect[4] = 0x01754004;
+                               Protect[5] = 0x03f54084;
+                               pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
+                               break;
+               }
+       }
+#endif // DOT11_N_SUPPORT //
+
+       offset = CCK_PROT_CFG;
+       for (i = 0;i < 6;i++)
+       {
+               if ((SetMask & (1<< i)))
+               {
+                       RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
+               }
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicSwitchChannel(
+                                         IN PRTMP_ADAPTER pAd,
+       IN      UCHAR                   Channel,
+       IN      BOOLEAN                 bScan)
+{
+       ULONG                   R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
+       CHAR    TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
+       UCHAR   index;
+       UINT32  Value = 0; //BbpReg, Value;
+       RTMP_RF_REGS *RFRegTable;
+
+       // Search Tx power value
+       for (index = 0; index < pAd->ChannelListNum; index++)
+       {
+               if (Channel == pAd->ChannelList[index].Channel)
+               {
+                       TxPwer = pAd->ChannelList[index].Power;
+                       TxPwer2 = pAd->ChannelList[index].Power2;
+                       break;
+               }
+       }
+
+       if (index == MAX_NUM_OF_CHANNELS)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
+       }
+
+#ifdef RT2870
+       // The RF programming sequence is difference between 3xxx and 2xxx
+       if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
+       {
+               /* modify by WY for Read RF Reg. error */
+               UCHAR RFValue;
+
+               for (index = 0; index < NUM_OF_3020_CHNL; index++)
+               {
+                       if (Channel == FreqItems3020[index].Channel)
+                       {
+                               // Programming channel parameters
+                               RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
+                               RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
+
+                               RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
+                               RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
+                               RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
+
+                               // Set Tx Power
+                               RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
+                               RFValue = (RFValue & 0xE0) | TxPwer;
+                               RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
+
+                               // Set RF offset
+                               RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
+                               RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
+                               RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
+
+                               // Set BW
+                               if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
+                               {
+                                       RFValue = pAd->Mlme.CaliBW40RfR24;
+                                       //DISABLE_11N_CHECK(pAd);
+                               }
+                               else
+                               {
+                                       RFValue = pAd->Mlme.CaliBW20RfR24;
+                               }
+                               RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
+
+                               // Enable RF tuning
+                               RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
+                               RFValue = RFValue | 0x1;
+                               RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
+
+                               // latch channel for future usage.
+                               pAd->LatchRfRegs.Channel = Channel;
+
+                               break;
+                       }
+               }
+
+               DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
+                       Channel,
+                       pAd->RfIcType,
+                       TxPwer,
+                       TxPwer2,
+                       pAd->Antenna.field.TxPath,
+                       FreqItems3020[index].N,
+                       FreqItems3020[index].K,
+                       FreqItems3020[index].R));
+       }
+       else
+#endif // RT2870 //
+       {
+               RFRegTable = RF2850RegTable;
+
+               switch (pAd->RfIcType)
+               {
+                       case RFIC_2820:
+                       case RFIC_2850:
+                       case RFIC_2720:
+                       case RFIC_2750:
+
+                       for (index = 0; index < NUM_OF_2850_CHNL; index++)
+                       {
+                               if (Channel == RFRegTable[index].Channel)
+                               {
+                                       R2 = RFRegTable[index].R2;
+                                       if (pAd->Antenna.field.TxPath == 1)
+                                       {
+                                               R2 |= 0x4000;   // If TXpath is 1, bit 14 = 1;
+                                       }
+
+                                       if (pAd->Antenna.field.RxPath == 2)
+                                       {
+                                               R2 |= 0x40;     // write 1 to off Rxpath.
+                                       }
+                                       else if (pAd->Antenna.field.RxPath == 1)
+                                       {
+                                               R2 |= 0x20040;  // write 1 to off RxPath
+                                       }
+
+                                       if (Channel > 14)
+                                       {
+                                               // initialize R3, R4
+                                               R3 = (RFRegTable[index].R3 & 0xffffc1ff);
+                                               R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
+
+                                               // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
+                                               // R3
+                                               if ((TxPwer >= -7) && (TxPwer < 0))
+                                               {
+                                                       TxPwer = (7+TxPwer);
+                                                       TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
+                                                       R3 |= (TxPwer << 10);
+                                                       DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
+                                               }
+                                               else
+                                               {
+                                                       TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
+                                                       R3 |= (TxPwer << 10) | (1 << 9);
+                                               }
+
+                                               // R4
+                                               if ((TxPwer2 >= -7) && (TxPwer2 < 0))
+                                               {
+                                                       TxPwer2 = (7+TxPwer2);
+                                                       TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
+                                                       R4 |= (TxPwer2 << 7);
+                                                       DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
+                                               }
+                                               else
+                                               {
+                                                       TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
+                                                       R4 |= (TxPwer2 << 7) | (1 << 6);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
+                                       R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
+                                       }
+
+                                       // Based on BBP current mode before changing RF channel.
+                                       if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
+                                       {
+                                               R4 |=0x200000;
+                                       }
+
+                                       // Update variables
+                                       pAd->LatchRfRegs.Channel = Channel;
+                                       pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
+                                       pAd->LatchRfRegs.R2 = R2;
+                                       pAd->LatchRfRegs.R3 = R3;
+                                       pAd->LatchRfRegs.R4 = R4;
+
+                                       // Set RF value 1's set R3[bit2] = [0]
+                                       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+                                       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+                                       RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
+                                       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+                                       RTMPusecDelay(200);
+
+                                       // Set RF value 2's set R3[bit2] = [1]
+                                       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+                                       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+                                       RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
+                                       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+                                       RTMPusecDelay(200);
+
+                                       // Set RF value 3's set R3[bit2] = [0]
+                                       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+                                       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+                                       RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
+                                       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+                                       break;
+                               }
+                       }
+                       break;
+
+                       default:
+                       break;
+               }
+       }
+
+       // Change BBP setting during siwtch from a->g, g->a
+       if (Channel <= 14)
+       {
+           ULONG       TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
+
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd)));    // According the Rory's suggestion to solve the middle range issue.
+               //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
+
+               // Rx High power VGA offset for LNA select
+           if (pAd->NicConfig2.field.ExternalLNAForG)
+           {
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
+           }
+           else
+           {
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
+           }
+
+               // 5G band selection PIN, bit1 and bit2 are complement
+               RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
+               Value &= (~0x6);
+               Value |= (0x04);
+               RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+
+        // Turn off unused PA or LNA when only 1T or 1R
+               if (pAd->Antenna.field.TxPath == 1)
+               {
+                       TxPinCfg &= 0xFFFFFFF3;
+               }
+               if (pAd->Antenna.field.RxPath == 1)
+               {
+                       TxPinCfg &= 0xFFFFF3FF;
+               }
+
+               RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
+       }
+       else
+       {
+           ULONG       TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
+
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd)));   // According the Rory's suggestion to solve the middle range issue.
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
+
+               // Rx High power VGA offset for LNA select
+               if (pAd->NicConfig2.field.ExternalLNAForA)
+               {
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
+               }
+               else
+               {
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
+               }
+
+               // 5G band selection PIN, bit1 and bit2 are complement
+               RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
+               Value &= (~0x6);
+               Value |= (0x02);
+               RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+
+        // Turn off unused PA or LNA when only 1T or 1R
+               if (pAd->Antenna.field.TxPath == 1)
+               {
+                       TxPinCfg &= 0xFFFFFFF3;
+       }
+               if (pAd->Antenna.field.RxPath == 1)
+               {
+                       TxPinCfg &= 0xFFFFF3FF;
+       }
+
+               RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
+       }
+
+    // R66 should be set according to Channel and use 20MHz when scanning
+       //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
+       if (bScan)
+               RTMPSetAGCInitValue(pAd, BW_20);
+       else
+               RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
+
+       //
+       // On 11A, We should delay and wait RF/BBP to be stable
+       // and the appropriate time should be 1000 micro seconds
+       // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
+       //
+       RTMPusecDelay(1000);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n",
+                                                         Channel,
+                                                         pAd->RfIcType,
+                                                         (R3 & 0x00003e00) >> 9,
+                                                         (R4 & 0x000007c0) >> 6,
+                                                         pAd->Antenna.field.TxPath,
+                                                         pAd->LatchRfRegs.R1,
+                                                         pAd->LatchRfRegs.R2,
+                                                         pAd->LatchRfRegs.R3,
+                                                         pAd->LatchRfRegs.R4));
+}
+
+/*
+       ==========================================================================
+       Description:
+               This function is required for 2421 only, and should not be used during
+               site survey. It's only required after NIC decided to stay at a channel
+               for a longer period.
+               When this function is called, it's always after AsicSwitchChannel().
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicLockChannel(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR Channel)
+{
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID   AsicAntennaSelect(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Channel)
+{
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Antenna miscellaneous setting.
+
+       Arguments:
+               pAd                                             Pointer to our adapter
+               BandState                               Indicate current Band State.
+
+       Return Value:
+               None
+
+       IRQL <= DISPATCH_LEVEL
+
+       Note:
+               1.) Frame End type control
+                       only valid for G only (RF_2527 & RF_2529)
+                       0: means DPDT, set BBP R4 bit 5 to 1
+                       1: means SPDT, set BBP R4 bit 5 to 0
+
+
+       ========================================================================
+*/
+VOID   AsicAntennaSetting(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      ABGBAND_STATE   BandState)
+{
+}
+
+VOID AsicRfTuningExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3)
+{
+}
+
+/*
+       ==========================================================================
+       Description:
+               Gives CCK TX rate 2 more dB TX power.
+               This routine works only in LINK UP in INFRASTRUCTURE mode.
+
+               calculate desired Tx power in RF R3.Tx0~5,      should consider -
+               0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
+               1. TxPowerPercentage
+               2. auto calibration based on TSSI feedback
+               3. extra 2 db for CCK
+               4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
+
+       NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
+               it should be called AFTER MlmeDynamicTxRatSwitching()
+       ==========================================================================
+ */
+VOID AsicAdjustTxPower(
+       IN PRTMP_ADAPTER pAd)
+{
+       INT                     i, j;
+       CHAR            DeltaPwr = 0;
+       BOOLEAN         bAutoTxAgc = FALSE;
+       UCHAR           TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
+       UCHAR           BbpR1 = 0, BbpR49 = 0, idx;
+       PCHAR           pTxAgcCompensate;
+       ULONG           TxPwr[5];
+       CHAR            Value;
+
+       if (pAd->CommonCfg.BBPCurrentBW == BW_40)
+       {
+               if (pAd->CommonCfg.CentralChannel > 14)
+               {
+                       TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
+                       TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
+                       TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
+                       TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
+                       TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
+               }
+               else
+               {
+                       TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
+                       TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
+                       TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
+                       TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
+                       TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
+               }
+       }
+       else
+       {
+               if (pAd->CommonCfg.Channel > 14)
+               {
+                       TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
+                       TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
+                       TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
+                       TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
+                       TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
+               }
+               else
+               {
+                       TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
+                       TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
+                       TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
+                       TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
+                       TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
+               }
+       }
+
+       // TX power compensation for temperature variation based on TSSI. try every 4 second
+       if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
+       {
+               if (pAd->CommonCfg.Channel <= 14)
+               {
+                       /* bg channel */
+                       bAutoTxAgc         = pAd->bAutoTxAgcG;
+                       TssiRef            = pAd->TssiRefG;
+                       pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
+                       pTssiPlusBoundary  = &pAd->TssiPlusBoundaryG[0];
+                       TxAgcStep          = pAd->TxAgcStepG;
+                       pTxAgcCompensate   = &pAd->TxAgcCompensateG;
+               }
+               else
+               {
+                       /* a channel */
+                       bAutoTxAgc         = pAd->bAutoTxAgcA;
+                       TssiRef            = pAd->TssiRefA;
+                       pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
+                       pTssiPlusBoundary  = &pAd->TssiPlusBoundaryA[0];
+                       TxAgcStep          = pAd->TxAgcStepA;
+                       pTxAgcCompensate   = &pAd->TxAgcCompensateA;
+               }
+
+               if (bAutoTxAgc)
+               {
+                       /* BbpR1 is unsigned char */
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
+
+                       /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
+                       /* compensate: +4     +3   +2   +1    0   -1   -2   -3   -4 * steps */
+                       /* step value is defined in pAd->TxAgcStepG for tx power value */
+
+                       /* [4]+1+[4]   p4     p3   p2   p1   o1   m1   m2   m3   m4 */
+                       /* ex:         0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
+                          above value are examined in mass factory production */
+                       /*             [4]    [3]  [2]  [1]  [0]  [1]  [2]  [3]  [4] */
+
+                       /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
+                       /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
+                       /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
+
+                       if (BbpR49 > pTssiMinusBoundary[1])
+                       {
+                               // Reading is larger than the reference value
+                               // check for how large we need to decrease the Tx power
+                               for (idx = 1; idx < 5; idx++)
+                               {
+                                       if (BbpR49 <= pTssiMinusBoundary[idx])  // Found the range
+                                               break;
+                               }
+                               // The index is the step we should decrease, idx = 0 means there is nothing to compensate
+//                             if (R3 > (ULONG) (TxAgcStep * (idx-1)))
+                                       *pTxAgcCompensate = -(TxAgcStep * (idx-1));
+//                             else
+//                                     *pTxAgcCompensate = -((UCHAR)R3);
+
+                               DeltaPwr += (*pTxAgcCompensate);
+                               DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
+                                       BbpR49, TssiRef, TxAgcStep, idx-1));
+                       }
+                       else if (BbpR49 < pTssiPlusBoundary[1])
+                       {
+                               // Reading is smaller than the reference value
+                               // check for how large we need to increase the Tx power
+                               for (idx = 1; idx < 5; idx++)
+                               {
+                                       if (BbpR49 >= pTssiPlusBoundary[idx])   // Found the range
+                                               break;
+                               }
+                               // The index is the step we should increase, idx = 0 means there is nothing to compensate
+                               *pTxAgcCompensate = TxAgcStep * (idx-1);
+                               DeltaPwr += (*pTxAgcCompensate);
+                               DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
+                                       BbpR49, TssiRef, TxAgcStep, idx-1));
+                       }
+                       else
+                       {
+                               *pTxAgcCompensate = 0;
+                               DBGPRINT(RT_DEBUG_TRACE, ("   Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
+                                       BbpR49, TssiRef, TxAgcStep, 0));
+                       }
+               }
+       }
+       else
+       {
+               if (pAd->CommonCfg.Channel <= 14)
+               {
+                       bAutoTxAgc         = pAd->bAutoTxAgcG;
+                       pTxAgcCompensate   = &pAd->TxAgcCompensateG;
+               }
+               else
+               {
+                       bAutoTxAgc         = pAd->bAutoTxAgcA;
+                       pTxAgcCompensate   = &pAd->TxAgcCompensateA;
+               }
+
+               if (bAutoTxAgc)
+                       DeltaPwr += (*pTxAgcCompensate);
+       }
+
+       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
+       BbpR1 &= 0xFC;
+
+#ifdef SINGLE_SKU
+       // Handle regulatory max tx power constrain
+       do
+       {
+               UCHAR    TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
+               UCHAR    AdjustMaxTxPwr[40];
+
+               if (pAd->CommonCfg.Channel > 14) // 5G band
+                       TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
+               else // 2.4G band
+                       TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
+               CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
+
+               // error handling, range check
+               if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
+               {
+                       DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
+                       break;
+               }
+
+               criterion = *((PUCHAR)TxPwr + 2) & 0xF;        // FAE use OFDM 6M as criterion
+
+               DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
+
+               // Adjust max tx power according to the relationship of tx power in E2PROM
+               for (i=0; i<5; i++)
+               {
+                       // CCK will have 4dBm larger than OFDM
+                       // Therefore, we should separate to parse the tx power field
+                       if (i == 0)
+                       {
+                               for (j=0; j<8; j++)
+                               {
+                                       Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
+
+                                       if (j < 4)
+                                       {
+                                               // CCK will have 4dBm larger than OFDM
+                                               AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
+                                       }
+                                       else
+                                       {
+                                               AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
+                                       }
+                                       DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
+                               }
+                       }
+                       else
+                       {
+                               for (j=0; j<8; j++)
+                               {
+                                       Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
+
+                                       AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
+                                       DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
+                               }
+                       }
+               }
+
+               // Adjust tx power according to the relationship
+               for (i=0; i<5; i++)
+               {
+                       if (TxPwr[i] != 0xffffffff)
+                       {
+                               for (j=0; j<8; j++)
+                               {
+                                       Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
+
+                                       // The system tx power is larger than the regulatory, the power should be restrain
+                                       if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
+                                       {
+                                               // decrease to zero and don't need to take care BBPR1
+                                               if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
+                                                       Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
+                                               else
+                                                       Value = 0;
+
+                                               DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
+                                       }
+                                       else
+                                               DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
+
+                                               TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
+                               }
+                       }
+               }
+       } while (FALSE);
+#endif // SINGLE_SKU //
+
+       /* calculate delta power based on the percentage specified from UI */
+       // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
+       // We lower TX power here according to the percentage specified from UI
+       if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff)       // AUTO TX POWER control
+               ;
+       else if (pAd->CommonCfg.TxPowerPercentage > 90)  // 91 ~ 100% & AUTO, treat as 100% in terms of mW
+               ;
+       else if (pAd->CommonCfg.TxPowerPercentage > 60)  // 61 ~ 90%, treat as 75% in terms of mW               // DeltaPwr -= 1;
+       {
+               DeltaPwr -= 1;
+       }
+       else if (pAd->CommonCfg.TxPowerPercentage > 30)  // 31 ~ 60%, treat as 50% in terms of mW               // DeltaPwr -= 3;
+       {
+               DeltaPwr -= 3;
+       }
+       else if (pAd->CommonCfg.TxPowerPercentage > 15)  // 16 ~ 30%, treat as 25% in terms of mW               // DeltaPwr -= 6;
+       {
+               BbpR1 |= 0x01;
+       }
+       else if (pAd->CommonCfg.TxPowerPercentage > 9)   // 10 ~ 15%, treat as 12.5% in terms of mW             // DeltaPwr -= 9;
+       {
+               BbpR1 |= 0x01;
+               DeltaPwr -= 3;
+       }
+       else                                           // 0 ~ 9 %, treat as MIN(~3%) in terms of mW             // DeltaPwr -= 12;
+       {
+               BbpR1 |= 0x02;
+       }
+
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
+
+       /* reset different new tx power for different TX rate */
+       for(i=0; i<5; i++)
+       {
+               if (TxPwr[i] != 0xffffffff)
+               {
+                       for (j=0; j<8; j++)
+                       {
+                               Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
+
+                               if ((Value + DeltaPwr) < 0)
+                               {
+                                       Value = 0; /* min */
+                               }
+                               else if ((Value + DeltaPwr) > 0xF)
+                               {
+                                       Value = 0xF; /* max */
+                               }
+                               else
+                               {
+                                       Value += DeltaPwr; /* temperature compensation */
+                               }
+
+                               /* fill new value to CSR offset */
+                               TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
+                       }
+
+                       /* write tx power value to CSR */
+                       /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
+                                                                                       TX power for OFDM 6M/9M
+                                                                                       TX power for CCK5.5M/11M
+                                                                                       TX power for CCK1M/2M */
+                       /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
+                       RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
+               }
+       }
+
+}
+
+#ifdef CONFIG_STA_SUPPORT
+/*
+       ==========================================================================
+       Description:
+               put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
+               automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
+               the wakeup timer timeout. Driver has to issue a separate command to wake
+               PHY up.
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicSleepThenAutoWakeup(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT TbttNumToNextWakeUp)
+{
+    RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
+}
+
+/*
+       ==========================================================================
+       Description:
+               AsicForceWakeup() is used whenever manual wakeup is required
+               AsicForceSleep() should only be used when not in INFRA BSS. When
+               in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
+       ==========================================================================
+ */
+VOID AsicForceSleep(
+       IN PRTMP_ADAPTER pAd)
+{
+
+}
+
+/*
+       ==========================================================================
+       Description:
+               AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
+               expired.
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+       ==========================================================================
+ */
+VOID AsicForceWakeup(
+       IN PRTMP_ADAPTER pAd,
+       IN BOOLEAN    bFromTx)
+{
+    DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
+    RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
+}
+#endif // CONFIG_STA_SUPPORT //
+/*
+       ==========================================================================
+       Description:
+               Set My BSSID
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicSetBssid(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pBssid)
+{
+       ULONG             Addr4;
+       DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
+               pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
+
+       Addr4 = (ULONG)(pBssid[0])               |
+                       (ULONG)(pBssid[1] << 8)  |
+                       (ULONG)(pBssid[2] << 16) |
+                       (ULONG)(pBssid[3] << 24);
+       RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
+
+       Addr4 = 0;
+       // always one BSSID in STA mode
+       Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
+
+       RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
+}
+
+VOID AsicSetMcastWC(
+       IN PRTMP_ADAPTER pAd)
+{
+       MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
+       USHORT          offset;
+
+       pEntry->Sst        = SST_ASSOC;
+       pEntry->Aid        = MCAST_WCID;        // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
+       pEntry->PsMode     = PWR_ACTIVE;
+       pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
+       offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicDelWcidTab(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR        Wcid)
+{
+       ULONG             Addr0 = 0x0, Addr1 = 0x0;
+       ULONG           offset;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
+       offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
+       RTMP_IO_WRITE32(pAd, offset, Addr0);
+       offset += 4;
+       RTMP_IO_WRITE32(pAd, offset, Addr1);
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicEnableRDG(
+       IN PRTMP_ADAPTER pAd)
+{
+       TX_LINK_CFG_STRUC       TxLinkCfg;
+       UINT32                          Data = 0;
+
+       RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
+       TxLinkCfg.field.TxRDGEn = 1;
+       RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
+
+       RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+       Data  &= 0xFFFFFF00;
+       Data  |= 0x80;
+       RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+
+       //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicDisableRDG(
+       IN PRTMP_ADAPTER pAd)
+{
+       TX_LINK_CFG_STRUC       TxLinkCfg;
+       UINT32                          Data = 0;
+
+
+       RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
+       TxLinkCfg.field.TxRDGEn = 0;
+       RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
+
+       RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+
+       Data  &= 0xFFFFFF00;
+       //Data  |= 0x20;
+#ifndef WIFI_TEST
+       //if ( pAd->CommonCfg.bEnableTxBurst )
+       //      Data |= 0x60; // for performance issue not set the TXOP to 0
+#endif
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
+#ifdef DOT11_N_SUPPORT
+               && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
+#endif // DOT11_N_SUPPORT //
+       )
+       {
+               // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
+               if (pAd->CommonCfg.bEnableTxBurst)
+                       Data |= 0x20;
+       }
+       RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicDisableSync(
+       IN PRTMP_ADAPTER pAd)
+{
+       BCN_TIME_CFG_STRUC csr;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
+
+       // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
+       //                        that NIC will never wakes up because TSF stops and no more
+       //                        TBTT interrupts
+       pAd->TbttTickCount = 0;
+       RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+       csr.field.bBeaconGen = 0;
+       csr.field.bTBTTEnable = 0;
+       csr.field.TsfSyncMode = 0;
+       csr.field.bTsfTicking = 0;
+       RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicEnableBssSync(
+       IN PRTMP_ADAPTER pAd)
+{
+       BCN_TIME_CFG_STRUC csr;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
+
+       RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+//     RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
+               csr.field.bTsfTicking = 1;
+               csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
+               csr.field.bBeaconGen  = 0; // do NOT generate BEACON
+               csr.field.bTBTTEnable = 1;
+       }
+#endif // CONFIG_STA_SUPPORT //
+       RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+}
+
+/*
+       ==========================================================================
+       Description:
+       Note:
+               BEACON frame in shared memory should be built ok before this routine
+               can be called. Otherwise, a garbage frame maybe transmitted out every
+               Beacon period.
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicEnableIbssSync(
+       IN PRTMP_ADAPTER pAd)
+{
+       BCN_TIME_CFG_STRUC csr9;
+       PUCHAR                  ptr;
+       UINT i;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
+
+       RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
+       csr9.field.bBeaconGen = 0;
+       csr9.field.bTBTTEnable = 0;
+       csr9.field.bTsfTicking = 0;
+       RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
+
+
+#ifdef RT2870
+       // move BEACON TXD and frame content to on-chip memory
+       ptr = (PUCHAR)&pAd->BeaconTxWI;
+       for (i=0; i<TXWI_SIZE; i+=2)  // 16-byte TXWI field
+       {
+               //UINT32 longptr =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
+               //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
+               RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
+               ptr += 2;
+       }
+
+       // start right after the 16-byte TXWI field
+       ptr = pAd->BeaconBuf;
+       for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
+       {
+               //UINT32 longptr =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
+               //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
+               RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
+               ptr +=2;
+       }
+#endif // RT2870 //
+
+       //
+       // For Wi-Fi faily generated beacons between participating stations.
+       // Set TBTT phase adaptive adjustment step to 8us (default 16us)
+       // don't change settings 2006-5- by Jerry
+       //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);
+
+       // start sending BEACON
+       csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
+       csr9.field.bTsfTicking = 1;
+       csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
+       csr9.field.bTBTTEnable = 1;
+       csr9.field.bBeaconGen = 1;
+       RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicSetEdcaParm(
+       IN PRTMP_ADAPTER pAd,
+       IN PEDCA_PARM    pEdcaParm)
+{
+       EDCA_AC_CFG_STRUC   Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
+       AC_TXOP_CSR0_STRUC csr0;
+       AC_TXOP_CSR1_STRUC csr1;
+       AIFSN_CSR_STRUC    AifsnCsr;
+       CWMIN_CSR_STRUC    CwminCsr;
+       CWMAX_CSR_STRUC    CwmaxCsr;
+       int i;
+
+       Ac0Cfg.word = 0;
+       Ac1Cfg.word = 0;
+       Ac2Cfg.word = 0;
+       Ac3Cfg.word = 0;
+       if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
+               for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+               {
+                       if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
+                               CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
+               }
+
+               //========================================================
+               //      MAC Register has a copy .
+               //========================================================
+//#ifndef WIFI_TEST
+               if( pAd->CommonCfg.bEnableTxBurst )
+               {
+                       // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
+                       Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
+               }
+               else
+                       Ac0Cfg.field.AcTxop = 0;        // QID_AC_BE
+//#else
+//             Ac0Cfg.field.AcTxop = 0;        // QID_AC_BE
+//#endif
+               Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
+               Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
+               Ac0Cfg.field.Aifsn = 2;
+               RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
+
+               Ac1Cfg.field.AcTxop = 0;        // QID_AC_BK
+               Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
+               Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
+               Ac1Cfg.field.Aifsn = 2;
+               RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
+
+               if (pAd->CommonCfg.PhyMode == PHY_11B)
+               {
+                       Ac2Cfg.field.AcTxop = 192;      // AC_VI: 192*32us ~= 6ms
+                       Ac3Cfg.field.AcTxop = 96;       // AC_VO: 96*32us  ~= 3ms
+               }
+               else
+               {
+                       Ac2Cfg.field.AcTxop = 96;       // AC_VI: 96*32us ~= 3ms
+                       Ac3Cfg.field.AcTxop = 48;       // AC_VO: 48*32us ~= 1.5ms
+               }
+               Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
+               Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
+               Ac2Cfg.field.Aifsn = 2;
+               RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
+               Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
+               Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
+               Ac3Cfg.field.Aifsn = 2;
+               RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
+
+               //========================================================
+               //      DMA Register has a copy too.
+               //========================================================
+               csr0.field.Ac0Txop = 0;         // QID_AC_BE
+               csr0.field.Ac1Txop = 0;         // QID_AC_BK
+               RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
+               if (pAd->CommonCfg.PhyMode == PHY_11B)
+               {
+                       csr1.field.Ac2Txop = 192;               // AC_VI: 192*32us ~= 6ms
+                       csr1.field.Ac3Txop = 96;                // AC_VO: 96*32us  ~= 3ms
+               }
+               else
+               {
+                       csr1.field.Ac2Txop = 96;                // AC_VI: 96*32us ~= 3ms
+                       csr1.field.Ac3Txop = 48;                // AC_VO: 48*32us ~= 1.5ms
+               }
+               RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
+
+               CwminCsr.word = 0;
+               CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
+               CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
+               CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
+               CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
+               RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
+
+               CwmaxCsr.word = 0;
+               CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
+               CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
+               CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
+               CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
+               RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
+
+               RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
+
+               NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
+       }
+       else
+       {
+               OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
+               //========================================================
+               //      MAC Register has a copy.
+               //========================================================
+               //
+               // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
+               // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
+               //
+               //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
+
+               Ac0Cfg.field.AcTxop =  pEdcaParm->Txop[QID_AC_BE];
+               Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
+               Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
+               Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
+
+               Ac1Cfg.field.AcTxop =  pEdcaParm->Txop[QID_AC_BK];
+               Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
+               Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
+               Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
+
+               Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
+               Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
+               Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
+               Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       // Tuning for Wi-Fi WMM S06
+                       if (pAd->CommonCfg.bWiFiTest &&
+                               pEdcaParm->Aifsn[QID_AC_VI] == 10)
+                               Ac2Cfg.field.Aifsn -= 1;
+
+                       // Tuning for TGn Wi-Fi 5.2.32
+                       // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
+                       if (STA_TGN_WIFI_ON(pAd) &&
+                               pEdcaParm->Aifsn[QID_AC_VI] == 10)
+                       {
+                               Ac0Cfg.field.Aifsn = 3;
+                               Ac2Cfg.field.AcTxop = 5;
+                       }
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+               Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
+               Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
+               Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
+               Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
+
+//#ifdef WIFI_TEST
+               if (pAd->CommonCfg.bWiFiTest)
+               {
+                       if (Ac3Cfg.field.AcTxop == 102)
+                       {
+                       Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
+                               Ac0Cfg.field.Aifsn  = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
+                       Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
+                               Ac1Cfg.field.Aifsn  = pEdcaParm->Aifsn[QID_AC_BK];
+                       Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
+                       } /* End of if */
+               }
+//#endif // WIFI_TEST //
+
+               RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
+               RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
+               RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
+               RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
+
+
+               //========================================================
+               //      DMA Register has a copy too.
+               //========================================================
+               csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
+               csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
+               RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
+
+               csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
+               csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
+               RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
+
+               CwminCsr.word = 0;
+               CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
+               CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
+               CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
+#endif // CONFIG_STA_SUPPORT //
+               RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
+
+               CwmaxCsr.word = 0;
+               CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
+               CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
+               CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
+               CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
+               RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
+
+               AifsnCsr.word = 0;
+               AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
+               AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
+               AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       // Tuning for Wi-Fi WMM S06
+                       if (pAd->CommonCfg.bWiFiTest &&
+                               pEdcaParm->Aifsn[QID_AC_VI] == 10)
+                               AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
+
+                       // Tuning for TGn Wi-Fi 5.2.32
+                       // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
+                       if (STA_TGN_WIFI_ON(pAd) &&
+                               pEdcaParm->Aifsn[QID_AC_VI] == 10)
+                       {
+                               AifsnCsr.field.Aifsn0 = 3;
+                               AifsnCsr.field.Aifsn2 = 7;
+                       }
+
+                       if (INFRA_ON(pAd))
+                               CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
+               }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
+#endif // CONFIG_STA_SUPPORT //
+               RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
+
+               NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
+               if (!ADHOC_ON(pAd))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax  TXOP(us)  ACM\n", pEdcaParm->EdcaUpdateCount));
+                       DBGPRINT(RT_DEBUG_TRACE,("     AC_BE      %2d     %2d     %2d      %4d     %d\n",
+                                                                        pEdcaParm->Aifsn[0],
+                                                                        pEdcaParm->Cwmin[0],
+                                                                        pEdcaParm->Cwmax[0],
+                                                                        pEdcaParm->Txop[0]<<5,
+                                                                        pEdcaParm->bACM[0]));
+                       DBGPRINT(RT_DEBUG_TRACE,("     AC_BK      %2d     %2d     %2d      %4d     %d\n",
+                                                                        pEdcaParm->Aifsn[1],
+                                                                        pEdcaParm->Cwmin[1],
+                                                                        pEdcaParm->Cwmax[1],
+                                                                        pEdcaParm->Txop[1]<<5,
+                                                                        pEdcaParm->bACM[1]));
+                       DBGPRINT(RT_DEBUG_TRACE,("     AC_VI      %2d     %2d     %2d      %4d     %d\n",
+                                                                        pEdcaParm->Aifsn[2],
+                                                                        pEdcaParm->Cwmin[2],
+                                                                        pEdcaParm->Cwmax[2],
+                                                                        pEdcaParm->Txop[2]<<5,
+                                                                        pEdcaParm->bACM[2]));
+                       DBGPRINT(RT_DEBUG_TRACE,("     AC_VO      %2d     %2d     %2d      %4d     %d\n",
+                                                                        pEdcaParm->Aifsn[3],
+                                                                        pEdcaParm->Cwmin[3],
+                                                                        pEdcaParm->Cwmax[3],
+                                                                        pEdcaParm->Txop[3]<<5,
+                                                                        pEdcaParm->bACM[3]));
+               }
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID   AsicSetSlotTime(
+       IN PRTMP_ADAPTER pAd,
+       IN BOOLEAN bUseShortSlotTime)
+{
+       ULONG   SlotTime;
+       UINT32  RegValue = 0;
+
+#ifdef CONFIG_STA_SUPPORT
+       if (pAd->CommonCfg.Channel > 14)
+               bUseShortSlotTime = TRUE;
+#endif // CONFIG_STA_SUPPORT //
+
+       if (bUseShortSlotTime)
+               OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
+       else
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
+
+       SlotTime = (bUseShortSlotTime)? 9 : 20;
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // force using short SLOT time for FAE to demo performance when TxBurst is ON
+               if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
+#ifdef DOT11_N_SUPPORT
+                       || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
+#endif // DOT11_N_SUPPORT //
+                       )
+               {
+                       // In this case, we will think it is doing Wi-Fi test
+                       // And we will not set to short slot when bEnableTxBurst is TRUE.
+               }
+               else if (pAd->CommonCfg.bEnableTxBurst)
+                       SlotTime = 9;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       //
+       // For some reasons, always set it to short slot time.
+       //
+       // ToDo: Should consider capability with 11B
+       //
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               if (pAd->StaCfg.BssType == BSS_ADHOC)
+                       SlotTime = 20;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
+       RegValue = RegValue & 0xFFFFFF00;
+
+       RegValue |= SlotTime;
+
+       RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
+}
+
+/*
+       ========================================================================
+       Description:
+               Add Shared key information into ASIC.
+               Update shared key, TxMic and RxMic to Asic Shared key table
+               Update its cipherAlg to Asic Shared key Mode.
+
+    Return:
+       ========================================================================
+*/
+VOID AsicAddSharedKeyEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR                 BssIndex,
+       IN UCHAR                 KeyIdx,
+       IN UCHAR                 CipherAlg,
+       IN PUCHAR                pKey,
+       IN PUCHAR                pTxMic,
+       IN PUCHAR                pRxMic)
+{
+       ULONG offset; //, csr0;
+       SHAREDKEY_MODE_STRUC csr1;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
+//============================================================================================
+
+       DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
+       DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+               pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
+       if (pRxMic)
+       {
+               DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                       pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
+       }
+       if (pTxMic)
+       {
+               DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                       pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
+       }
+//============================================================================================
+       //
+       // fill key material - key + TX MIC + RX MIC
+       //
+
+#ifdef RT2870
+{
+       offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
+       RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
+
+       offset += MAX_LEN_OF_SHARE_KEY;
+       if (pTxMic)
+       {
+               RTUSBMultiWrite(pAd, offset, pTxMic, 8);
+       }
+
+       offset += 8;
+       if (pRxMic)
+       {
+               RTUSBMultiWrite(pAd, offset, pRxMic, 8);
+       }
+}
+#endif // RT2870 //
+
+       //
+       // Update cipher algorithm. WSTA always use BSS0
+       //
+       RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
+       DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
+       if ((BssIndex%2) == 0)
+       {
+               if (KeyIdx == 0)
+                       csr1.field.Bss0Key0CipherAlg = CipherAlg;
+               else if (KeyIdx == 1)
+                       csr1.field.Bss0Key1CipherAlg = CipherAlg;
+               else if (KeyIdx == 2)
+                       csr1.field.Bss0Key2CipherAlg = CipherAlg;
+               else
+                       csr1.field.Bss0Key3CipherAlg = CipherAlg;
+       }
+       else
+       {
+               if (KeyIdx == 0)
+                       csr1.field.Bss1Key0CipherAlg = CipherAlg;
+               else if (KeyIdx == 1)
+                       csr1.field.Bss1Key1CipherAlg = CipherAlg;
+               else if (KeyIdx == 2)
+                       csr1.field.Bss1Key2CipherAlg = CipherAlg;
+               else
+                       csr1.field.Bss1Key3CipherAlg = CipherAlg;
+       }
+       DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
+       RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
+
+}
+
+//     IRQL = DISPATCH_LEVEL
+VOID AsicRemoveSharedKeyEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR                 BssIndex,
+       IN UCHAR                 KeyIdx)
+{
+       //ULONG SecCsr0;
+       SHAREDKEY_MODE_STRUC csr1;
+
+       DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
+
+       RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
+       if ((BssIndex%2) == 0)
+       {
+               if (KeyIdx == 0)
+                       csr1.field.Bss0Key0CipherAlg = 0;
+               else if (KeyIdx == 1)
+                       csr1.field.Bss0Key1CipherAlg = 0;
+               else if (KeyIdx == 2)
+                       csr1.field.Bss0Key2CipherAlg = 0;
+               else
+                       csr1.field.Bss0Key3CipherAlg = 0;
+       }
+       else
+       {
+               if (KeyIdx == 0)
+                       csr1.field.Bss1Key0CipherAlg = 0;
+               else if (KeyIdx == 1)
+                       csr1.field.Bss1Key1CipherAlg = 0;
+               else if (KeyIdx == 2)
+                       csr1.field.Bss1Key2CipherAlg = 0;
+               else
+                       csr1.field.Bss1Key3CipherAlg = 0;
+       }
+       DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
+       RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
+       ASSERT(BssIndex < 4);
+       ASSERT(KeyIdx < 4);
+
+}
+
+
+VOID AsicUpdateWCIDAttribute(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT               WCID,
+       IN UCHAR                BssIndex,
+       IN UCHAR        CipherAlg,
+       IN BOOLEAN              bUsePairewiseKeyTable)
+{
+       ULONG   WCIDAttri = 0, offset;
+
+       //
+       // Update WCID attribute.
+       // Only TxKey could update WCID attribute.
+       //
+       offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
+       WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
+       RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
+}
+
+VOID AsicUpdateWCIDIVEIV(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT               WCID,
+       IN ULONG        uIV,
+       IN ULONG        uEIV)
+{
+       ULONG   offset;
+
+       offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
+
+       RTMP_IO_WRITE32(pAd, offset, uIV);
+       RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
+}
+
+VOID AsicUpdateRxWCIDTable(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT               WCID,
+       IN PUCHAR        pAddr)
+{
+       ULONG offset;
+       ULONG Addr;
+
+       offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
+       Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
+       RTMP_IO_WRITE32(pAd, offset, Addr);
+       Addr = pAddr[4] + (pAddr[5] << 8);
+       RTMP_IO_WRITE32(pAd, offset + 4, Addr);
+}
+
+
+/*
+    ========================================================================
+
+    Routine Description:
+        Set Cipher Key, Cipher algorithm, IV/EIV to Asic
+
+    Arguments:
+        pAd                     Pointer to our adapter
+        WCID                    WCID Entry number.
+        BssIndex                BSSID index, station or none multiple BSSID support
+                                this value should be 0.
+        KeyIdx                  This KeyIdx will set to IV's KeyID if bTxKey enabled
+        pCipherKey              Pointer to Cipher Key.
+        bUsePairewiseKeyTable   TRUE means saved the key in SharedKey table,
+                                otherwise PairewiseKey table
+        bTxKey                  This is the transmit key if enabled.
+
+    Return Value:
+        None
+
+    Note:
+        This routine will set the relative key stuff to Asic including WCID attribute,
+        Cipher Key, Cipher algorithm and IV/EIV.
+
+        IV/EIV will be update if this CipherKey is the transmission key because
+        ASIC will base on IV's KeyID value to select Cipher Key.
+
+        If bTxKey sets to FALSE, this is not the TX key, but it could be
+        RX key
+
+       For AP mode bTxKey must be always set to TRUE.
+    ========================================================================
+*/
+VOID AsicAddKeyEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT               WCID,
+       IN UCHAR                BssIndex,
+       IN UCHAR                KeyIdx,
+       IN PCIPHER_KEY  pCipherKey,
+       IN BOOLEAN              bUsePairewiseKeyTable,
+       IN BOOLEAN              bTxKey)
+{
+       ULONG   offset;
+//     ULONG   WCIDAttri = 0;
+       UCHAR   IV4 = 0;
+       PUCHAR          pKey = pCipherKey->Key;
+//     ULONG           KeyLen = pCipherKey->KeyLen;
+       PUCHAR          pTxMic = pCipherKey->TxMic;
+       PUCHAR          pRxMic = pCipherKey->RxMic;
+       PUCHAR          pTxtsc = pCipherKey->TxTsc;
+       UCHAR           CipherAlg = pCipherKey->CipherAlg;
+       SHAREDKEY_MODE_STRUC csr1;
+
+//     ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
+       //
+       // 1.) decide key table offset
+       //
+       if (bUsePairewiseKeyTable)
+               offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
+       else
+               offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
+
+       //
+       // 2.) Set Key to Asic
+       //
+       //for (i = 0; i < KeyLen; i++)
+
+#ifdef RT2870
+       RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
+       offset += MAX_LEN_OF_PEER_KEY;
+
+       //
+       // 3.) Set MIC key if available
+       //
+       if (pTxMic)
+       {
+               RTUSBMultiWrite(pAd, offset, pTxMic, 8);
+       }
+       offset += LEN_TKIP_TXMICK;
+
+       if (pRxMic)
+       {
+               RTUSBMultiWrite(pAd, offset, pRxMic, 8);
+       }
+#endif // RT2870 //
+
+       //
+       // 4.) Modify IV/EIV if needs
+       //     This will force Asic to use this key ID by setting IV.
+       //
+       if (bTxKey)
+       {
+
+#ifdef RT2870
+               UINT32 tmpVal;
+
+               //
+               // Write IV
+               //
+               IV4 = (KeyIdx << 6);
+               if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
+                       IV4 |= 0x20;  // turn on extension bit means EIV existence
+
+               tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
+               RTMP_IO_WRITE32(pAd, offset, tmpVal);
+
+               //
+               // Write EIV
+               //
+               offset += 4;
+               RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
+#endif // RT2870 //
+               AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
+       }
+
+       if (!bUsePairewiseKeyTable)
+       {
+               //
+               // Only update the shared key security mode
+               //
+               RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
+               if ((BssIndex % 2) == 0)
+               {
+                       if (KeyIdx == 0)
+                               csr1.field.Bss0Key0CipherAlg = CipherAlg;
+                       else if (KeyIdx == 1)
+                               csr1.field.Bss0Key1CipherAlg = CipherAlg;
+                       else if (KeyIdx == 2)
+                               csr1.field.Bss0Key2CipherAlg = CipherAlg;
+                       else
+                               csr1.field.Bss0Key3CipherAlg = CipherAlg;
+               }
+               else
+               {
+                       if (KeyIdx == 0)
+                               csr1.field.Bss1Key0CipherAlg = CipherAlg;
+                       else if (KeyIdx == 1)
+                               csr1.field.Bss1Key1CipherAlg = CipherAlg;
+                       else if (KeyIdx == 2)
+                               csr1.field.Bss1Key2CipherAlg = CipherAlg;
+                       else
+                               csr1.field.Bss1Key3CipherAlg = CipherAlg;
+               }
+               RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
+}
+
+
+/*
+       ========================================================================
+       Description:
+               Add Pair-wise key material into ASIC.
+               Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
+
+    Return:
+       ========================================================================
+*/
+VOID AsicAddPairwiseKeyEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR        pAddr,
+       IN UCHAR                WCID,
+       IN CIPHER_KEY            *pCipherKey)
+{
+       INT i;
+       ULONG           offset;
+       PUCHAR           pKey = pCipherKey->Key;
+       PUCHAR           pTxMic = pCipherKey->TxMic;
+       PUCHAR           pRxMic = pCipherKey->RxMic;
+#ifdef DBG
+       UCHAR           CipherAlg = pCipherKey->CipherAlg;
+#endif // DBG //
+
+       // EKEY
+       offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
+#ifdef RT2870
+       RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
+#endif // RT2870 //
+       for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
+       {
+               UINT32 Value;
+               RTMP_IO_READ32(pAd, offset + i, &Value);
+       }
+
+       offset += MAX_LEN_OF_PEER_KEY;
+
+       //  MIC KEY
+       if (pTxMic)
+       {
+#ifdef RT2870
+               RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
+#endif // RT2870 //
+       }
+       offset += 8;
+       if (pRxMic)
+       {
+#ifdef RT2870
+               RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
+#endif // RT2870 //
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
+       DBGPRINT(RT_DEBUG_TRACE,("      Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+               pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
+       if (pRxMic)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("     Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                       pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
+       }
+       if (pTxMic)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("     Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                       pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
+       }
+}
+/*
+       ========================================================================
+       Description:
+               Remove Pair-wise key material from ASIC.
+
+    Return:
+       ========================================================================
+*/
+VOID AsicRemovePairwiseKeyEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR                 BssIdx,
+       IN UCHAR                 Wcid)
+{
+       ULONG           WCIDAttri;
+       USHORT          offset;
+
+       // re-set the entry's WCID attribute as OPEN-NONE.
+       offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
+       WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
+       RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
+}
+
+BOOLEAN AsicSendCommandToMcu(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR                 Command,
+       IN UCHAR                 Token,
+       IN UCHAR                 Arg0,
+       IN UCHAR                 Arg1)
+{
+       HOST_CMD_CSR_STRUC      H2MCmd;
+       H2M_MAILBOX_STRUC       H2MMailbox;
+       ULONG                           i = 0;
+       do
+       {
+               RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
+               if (H2MMailbox.field.Owner == 0)
+                       break;
+
+               RTMPusecDelay(2);
+       } while(i++ < 100);
+
+       if (i >= 100)
+       {
+               {
+               DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
+               }
+               return FALSE;
+       }
+
+
+       H2MMailbox.field.Owner    = 1;     // pass ownership to MCU
+       H2MMailbox.field.CmdToken = Token;
+       H2MMailbox.field.HighByte = Arg1;
+       H2MMailbox.field.LowByte  = Arg0;
+       RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
+
+       H2MCmd.word                       = 0;
+       H2MCmd.field.HostCommand  = Command;
+       RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
+
+       if (Command != 0x80)
+       {
+       }
+
+       return TRUE;
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Verify the support rate for different PHY type
+
+       Arguments:
+               pAd                             Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       ========================================================================
+*/
+VOID   RTMPCheckRates(
+       IN              PRTMP_ADAPTER   pAd,
+       IN OUT  UCHAR                   SupRate[],
+       IN OUT  UCHAR                   *SupRateLen)
+{
+       UCHAR   RateIdx, i, j;
+       UCHAR   NewRate[12], NewRateLen;
+
+       NewRateLen = 0;
+
+       if (pAd->CommonCfg.PhyMode == PHY_11B)
+               RateIdx = 4;
+       else
+               RateIdx = 12;
+
+       // Check for support rates exclude basic rate bit
+       for (i = 0; i < *SupRateLen; i++)
+               for (j = 0; j < RateIdx; j++)
+                       if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
+                               NewRate[NewRateLen++] = SupRate[i];
+
+       *SupRateLen = NewRateLen;
+       NdisMoveMemory(SupRate, NewRate, NewRateLen);
+}
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef DOT11_N_SUPPORT
+BOOLEAN RTMPCheckChannel(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR                CentralChannel,
+       IN UCHAR                Channel)
+{
+       UCHAR           k;
+       UCHAR           UpperChannel = 0, LowerChannel = 0;
+       UCHAR           NoEffectChannelinList = 0;
+
+       // Find upper and lower channel according to 40MHz current operation.
+       if (CentralChannel < Channel)
+       {
+               UpperChannel = Channel;
+               if (CentralChannel > 2)
+                       LowerChannel = CentralChannel - 2;
+               else
+                       return FALSE;
+       }
+       else if (CentralChannel > Channel)
+       {
+               UpperChannel = CentralChannel + 2;
+               LowerChannel = Channel;
+       }
+
+       for (k = 0;k < pAd->ChannelListNum;k++)
+       {
+               if (pAd->ChannelList[k].Channel == UpperChannel)
+               {
+                       NoEffectChannelinList ++;
+               }
+               if (pAd->ChannelList[k].Channel == LowerChannel)
+               {
+                       NoEffectChannelinList ++;
+               }
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
+       if (NoEffectChannelinList == 2)
+               return TRUE;
+       else
+               return FALSE;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Verify the support rate for HT phy type
+
+       Arguments:
+               pAd                             Pointer to our adapter
+
+       Return Value:
+               FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability.  (AP Mode)
+
+       IRQL = PASSIVE_LEVEL
+
+       ========================================================================
+*/
+BOOLEAN        RTMPCheckHt(
+       IN      PRTMP_ADAPTER                   pAd,
+       IN      UCHAR                                   Wcid,
+       IN      HT_CAPABILITY_IE                *pHtCapability,
+       IN      ADD_HT_INFO_IE                  *pAddHtInfo)
+{
+       if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+               return FALSE;
+
+       // If use AMSDU, set flag.
+       if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
+               CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
+       // Save Peer Capability
+       if (pHtCapability->HtCapInfo.ShortGIfor20)
+               CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
+       if (pHtCapability->HtCapInfo.ShortGIfor40)
+               CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
+       if (pHtCapability->HtCapInfo.TxSTBC)
+               CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
+       if (pHtCapability->HtCapInfo.RxSTBC)
+               CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
+       if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
+       {
+               CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
+       }
+
+       if (Wcid < MAX_LEN_OF_MAC_TABLE)
+       {
+               pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
+       }
+
+       // Will check ChannelWidth for MCSSet[4] below
+       pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
+    switch (pAd->CommonCfg.RxStream)
+       {
+               case 1:
+                       pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
+                       pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
+            pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
+            pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
+                       break;
+               case 2:
+                       pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
+                       pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
+            pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
+            pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
+                       break;
+               case 3:
+                       pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
+                       pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
+            pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
+            pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
+                       break;
+       }
+
+       pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
+               pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
+               pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
+
+       pAd->MlmeAux.HtCapability.HtCapInfo.GF =  pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
+
+       // Send Assoc Req with my HT capability.
+       pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize =  pAd->CommonCfg.DesiredHtPhy.AmsduSize;
+       pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs =  pAd->CommonCfg.DesiredHtPhy.MimoPs;
+       pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 =  (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
+       pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 =  (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
+       pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC =  (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
+       pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC =  (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
+       pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
+    pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
+       pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
+       pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
+       if (pAd->CommonCfg.bRdg)
+       {
+               pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
+        pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
+       }
+
+    if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
+        pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0;  // BW20 can't transmit MCS32
+
+       COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
+       return TRUE;
+}
+#endif // DOT11_N_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Verify the support rate for different PHY type
+
+       Arguments:
+               pAd                             Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       ========================================================================
+*/
+VOID RTMPUpdateMlmeRate(
+       IN PRTMP_ADAPTER        pAd)
+{
+       UCHAR   MinimumRate;
+       UCHAR   ProperMlmeRate; //= RATE_54;
+       UCHAR   i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
+       BOOLEAN bMatch = FALSE;
+
+       switch (pAd->CommonCfg.PhyMode)
+       {
+               case PHY_11B:
+                       ProperMlmeRate = RATE_11;
+                       MinimumRate = RATE_1;
+                       break;
+               case PHY_11BG_MIXED:
+#ifdef DOT11_N_SUPPORT
+               case PHY_11ABGN_MIXED:
+               case PHY_11BGN_MIXED:
+#endif // DOT11_N_SUPPORT //
+                       if ((pAd->MlmeAux.SupRateLen == 4) &&
+                               (pAd->MlmeAux.ExtRateLen == 0))
+                               // B only AP
+                               ProperMlmeRate = RATE_11;
+                       else
+                               ProperMlmeRate = RATE_24;
+
+                       if (pAd->MlmeAux.Channel <= 14)
+                               MinimumRate = RATE_1;
+                       else
+                               MinimumRate = RATE_6;
+                       break;
+               case PHY_11A:
+#ifdef DOT11_N_SUPPORT
+               case PHY_11N_2_4G:      // rt2860 need to check mlmerate for 802.11n
+               case PHY_11GN_MIXED:
+               case PHY_11AGN_MIXED:
+               case PHY_11AN_MIXED:
+               case PHY_11N_5G:
+#endif // DOT11_N_SUPPORT //
+                       ProperMlmeRate = RATE_24;
+                       MinimumRate = RATE_6;
+                       break;
+               case PHY_11ABG_MIXED:
+                       ProperMlmeRate = RATE_24;
+                       if (pAd->MlmeAux.Channel <= 14)
+                          MinimumRate = RATE_1;
+                       else
+                               MinimumRate = RATE_6;
+                       break;
+               default: // error
+                       ProperMlmeRate = RATE_1;
+                       MinimumRate = RATE_1;
+                       break;
+       }
+
+       for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
+       {
+               for (j = 0; j < RateIdx; j++)
+               {
+                       if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
+                       {
+                               if (j == ProperMlmeRate)
+                               {
+                                       bMatch = TRUE;
+                                       break;
+                               }
+                       }
+               }
+
+               if (bMatch)
+                       break;
+       }
+
+       if (bMatch == FALSE)
+       {
+               for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
+               {
+                       for (j = 0; j < RateIdx; j++)
+                       {
+                               if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
+                               {
+                                       if (j == ProperMlmeRate)
+                                       {
+                                               bMatch = TRUE;
+                                               break;
+                                       }
+                               }
+                       }
+
+                       if (bMatch)
+                               break;
+               }
+       }
+
+       if (bMatch == FALSE)
+       {
+               ProperMlmeRate = MinimumRate;
+       }
+
+       pAd->CommonCfg.MlmeRate = MinimumRate;
+       pAd->CommonCfg.RtsRate = ProperMlmeRate;
+       if (pAd->CommonCfg.MlmeRate >= RATE_6)
+       {
+               pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+               pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+               pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
+               pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+       }
+       else
+       {
+               pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
+               pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
+               pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
+               pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==>   MlmeTransmit = 0x%x  \n" , pAd->CommonCfg.MlmeTransmit.word));
+}
+
+CHAR RTMPMaxRssi(
+       IN PRTMP_ADAPTER        pAd,
+       IN CHAR                         Rssi0,
+       IN CHAR                         Rssi1,
+       IN CHAR                         Rssi2)
+{
+       CHAR    larger = -127;
+
+       if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
+       {
+               larger = Rssi0;
+       }
+
+       if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
+       {
+               larger = max(Rssi0, Rssi1);
+       }
+
+       if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
+       {
+               larger = max(larger, Rssi2);
+       }
+
+       if (larger == -127)
+               larger = 0;
+
+       return larger;
+}
+
+/*
+    ========================================================================
+    Routine Description:
+        Periodic evaluate antenna link status
+
+    Arguments:
+        pAd         - Adapter pointer
+
+    Return Value:
+        None
+
+    ========================================================================
+*/
+VOID AsicEvaluateRxAnt(
+       IN PRTMP_ADAPTER        pAd)
+{
+       UCHAR   BBPR3 = 0;
+
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_HALT_IN_PROGRESS  |
+                                                               fRTMP_ADAPTER_RADIO_OFF                 |
+                                                               fRTMP_ADAPTER_NIC_NOT_EXIST             |
+                                                               fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+                       return;
+
+               if (pAd->StaCfg.Psm == PWR_SAVE)
+                       return;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
+       BBPR3 &= (~0x18);
+       if(pAd->Antenna.field.RxPath == 3)
+       {
+               BBPR3 |= (0x10);
+       }
+       else if(pAd->Antenna.field.RxPath == 2)
+       {
+               BBPR3 |= (0x8);
+       }
+       else if(pAd->Antenna.field.RxPath == 1)
+       {
+               BBPR3 |= (0x0);
+       }
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
+#ifdef CONFIG_STA_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+       if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
+               )
+       {
+               ULONG   TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
+                                                               pAd->RalinkCounters.OneSecTxRetryOkCount +
+                                                               pAd->RalinkCounters.OneSecTxFailCount;
+
+               if (TxTotalCnt > 50)
+               {
+                       RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
+                       pAd->Mlme.bLowThroughput = FALSE;
+               }
+               else
+               {
+                       RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
+                       pAd->Mlme.bLowThroughput = TRUE;
+               }
+       }
+}
+
+/*
+    ========================================================================
+    Routine Description:
+        After evaluation, check antenna link status
+
+    Arguments:
+        pAd         - Adapter pointer
+
+    Return Value:
+        None
+
+    ========================================================================
+*/
+VOID AsicRxAntEvalTimeout(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3)
+{
+       RTMP_ADAPTER    *pAd = (RTMP_ADAPTER *)FunctionContext;
+#ifdef CONFIG_STA_SUPPORT
+       UCHAR                   BBPR3 = 0;
+       CHAR                    larger = -127, rssi0, rssi1, rssi2;
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)        ||
+                       RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)             ||
+                       RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)                    ||
+                       RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+                       return;
+
+               if (pAd->StaCfg.Psm == PWR_SAVE)
+                       return;
+
+
+               // if the traffic is low, use average rssi as the criteria
+               if (pAd->Mlme.bLowThroughput == TRUE)
+               {
+                       rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
+                       rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
+                       rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
+               }
+               else
+               {
+                       rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
+                       rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
+                       rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
+               }
+
+               if(pAd->Antenna.field.RxPath == 3)
+               {
+                       larger = max(rssi0, rssi1);
+
+                       if (larger > (rssi2 + 20))
+                               pAd->Mlme.RealRxPath = 2;
+                       else
+                               pAd->Mlme.RealRxPath = 3;
+               }
+               else if(pAd->Antenna.field.RxPath == 2)
+               {
+                       if (rssi0 > (rssi1 + 20))
+                               pAd->Mlme.RealRxPath = 1;
+                       else
+                               pAd->Mlme.RealRxPath = 2;
+               }
+
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
+               BBPR3 &= (~0x18);
+               if(pAd->Mlme.RealRxPath == 3)
+               {
+                       BBPR3 |= (0x10);
+               }
+               else if(pAd->Mlme.RealRxPath == 2)
+               {
+                       BBPR3 |= (0x8);
+               }
+               else if(pAd->Mlme.RealRxPath == 1)
+               {
+                       BBPR3 |= (0x0);
+               }
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
+       }
+
+#endif // CONFIG_STA_SUPPORT //
+
+}
+
+
+
+VOID APSDPeriodicExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3)
+{
+       RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+       if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+               return;
+
+       pAd->CommonCfg.TriggerTimerCount++;
+
+// Driver should not send trigger frame, it should be send by application layer
+/*
+       if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
+               && (pAd->CommonCfg.bNeedSendTriggerFrame ||
+               (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
+       {
+               DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
+               RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
+               pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
+               pAd->CommonCfg.TriggerTimerCount = 0;
+               pAd->CommonCfg.bInServicePeriod = TRUE;
+       }*/
+}
+
+/*
+    ========================================================================
+    Routine Description:
+        Set/reset MAC registers according to bPiggyBack parameter
+
+    Arguments:
+        pAd         - Adapter pointer
+        bPiggyBack  - Enable / Disable Piggy-Back
+
+    Return Value:
+        None
+
+    ========================================================================
+*/
+VOID RTMPSetPiggyBack(
+    IN PRTMP_ADAPTER    pAd,
+    IN BOOLEAN          bPiggyBack)
+{
+       TX_LINK_CFG_STRUC  TxLinkCfg;
+
+       RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
+
+       TxLinkCfg.field.TxCFAckEn = bPiggyBack;
+       RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
+}
+
+/*
+    ========================================================================
+    Routine Description:
+        check if this entry need to switch rate automatically
+
+    Arguments:
+        pAd
+        pEntry
+
+    Return Value:
+        TURE
+        FALSE
+
+    ========================================================================
+*/
+BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
+       IN PRTMP_ADAPTER    pAd,
+       IN PMAC_TABLE_ENTRY     pEntry)
+{
+       BOOLEAN         result = TRUE;
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // only associated STA counts
+               if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
+               {
+                       result = pAd->StaCfg.bAutoTxRateSwitch;
+               }
+               else
+                       result = FALSE;
+
+#ifdef QOS_DLS_SUPPORT
+               if (pEntry && (pEntry->ValidAsDls))
+                       result = pAd->StaCfg.bAutoTxRateSwitch;
+#endif // QOS_DLS_SUPPORT //
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+
+
+       return result;
+}
+
+
+BOOLEAN RTMPAutoRateSwitchCheck(
+       IN PRTMP_ADAPTER    pAd)
+{
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               if (pAd->StaCfg.bAutoTxRateSwitch)
+                       return TRUE;
+       }
+#endif // CONFIG_STA_SUPPORT //
+       return FALSE;
+}
+
+
+/*
+    ========================================================================
+    Routine Description:
+        check if this entry need to fix tx legacy rate
+
+    Arguments:
+        pAd
+        pEntry
+
+    Return Value:
+        TURE
+        FALSE
+
+    ========================================================================
+*/
+UCHAR RTMPStaFixedTxMode(
+       IN PRTMP_ADAPTER    pAd,
+       IN PMAC_TABLE_ENTRY     pEntry)
+{
+       UCHAR   tx_mode = FIXED_TXMODE_HT;
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       return tx_mode;
+}
+
+/*
+    ========================================================================
+    Routine Description:
+        Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
+
+    Arguments:
+        pAd
+        pEntry
+
+    Return Value:
+        TURE
+        FALSE
+
+    ========================================================================
+*/
+VOID RTMPUpdateLegacyTxSetting(
+               UCHAR                           fixed_tx_mode,
+               PMAC_TABLE_ENTRY        pEntry)
+{
+       HTTRANSMIT_SETTING TransmitSetting;
+
+       if (fixed_tx_mode == FIXED_TXMODE_HT)
+               return;
+
+       TransmitSetting.word = 0;
+
+       TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
+       TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
+
+       if (fixed_tx_mode == FIXED_TXMODE_CCK)
+       {
+               TransmitSetting.field.MODE = MODE_CCK;
+               // CCK mode allow MCS 0~3
+               if (TransmitSetting.field.MCS > MCS_3)
+                       TransmitSetting.field.MCS = MCS_3;
+       }
+       else
+       {
+               TransmitSetting.field.MODE = MODE_OFDM;
+               // OFDM mode allow MCS 0~7
+               if (TransmitSetting.field.MCS > MCS_7)
+                       TransmitSetting.field.MCS = MCS_7;
+       }
+
+       if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
+       {
+               pEntry->HTPhyMode.word = TransmitSetting.word;
+               DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
+                               pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
+       }
+}
+
+#ifdef CONFIG_STA_SUPPORT
+/*
+       ==========================================================================
+       Description:
+               dynamic tune BBP R66 to find a balance between sensibility and
+               noise isolation
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AsicStaBbpTuning(
+       IN PRTMP_ADAPTER pAd)
+{
+       UCHAR   OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
+       CHAR    Rssi;
+
+       // 2860C did not support Fase CCA, therefore can't tune
+       if (pAd->MACVersion == 0x28600100)
+               return;
+
+       //
+       // work as a STA
+       //
+       if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)  // no R66 tuning when SCANNING
+               return;
+
+       if ((pAd->OpMode == OPMODE_STA)
+               && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
+                       )
+               && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+               )
+       {
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
+               R66 = OrigR66Value;
+
+               if (pAd->Antenna.field.RxPath > 1)
+                       Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
+               else
+                       Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
+
+               if (pAd->LatchRfRegs.Channel <= 14)
+               {       //BG band
+#ifdef RT2870
+                       // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
+                       // Otherwise, it will have some throughput side effect when low RSSI
+                       if (IS_RT3070(pAd))
+                       {
+                               if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
+                               {
+                                       R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
+                                       if (OrigR66Value != R66)
+                                       {
+                                               RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
+                                       }
+                               }
+                               else
+                               {
+                                       R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
+                                       if (OrigR66Value != R66)
+                                       {
+                                               RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
+                                       }
+                               }
+                       }
+                       else
+#endif // RT2870 //
+                       {
+                               if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
+                               {
+                                       R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
+                                       if (OrigR66Value != R66)
+                                       {
+                                               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+                                       }
+                               }
+                               else
+                               {
+                                       R66 = 0x2E + GET_LNA_GAIN(pAd);
+                                       if (OrigR66Value != R66)
+                                       {
+                                               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+                                       }
+                               }
+                       }
+               }
+               else
+               {       //A band
+                       if (pAd->CommonCfg.BBPCurrentBW == BW_20)
+                       {
+                               if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
+                               {
+                                       R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
+                                       if (OrigR66Value != R66)
+                                       {
+                                               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+                                       }
+                               }
+                               else
+                               {
+                                       R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
+                                       if (OrigR66Value != R66)
+                                       {
+                                               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
+                               {
+                                       R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
+                                       if (OrigR66Value != R66)
+                                       {
+                                               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+                                       }
+                               }
+                               else
+                               {
+                                       R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
+                                       if (OrigR66Value != R66)
+                                       {
+                                               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+                                       }
+                               }
+                       }
+               }
+
+
+       }
+}
+#endif // CONFIG_STA_SUPPORT //
+
+VOID RTMPSetAGCInitValue(
+       IN PRTMP_ADAPTER        pAd,
+       IN UCHAR                        BandWidth)
+{
+       UCHAR   R66 = 0x30;
+
+       if (pAd->LatchRfRegs.Channel <= 14)
+       {       // BG band
+               R66 = 0x2E + GET_LNA_GAIN(pAd);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+       }
+       else
+       {       //A band
+               if (BandWidth == BW_20)
+               {
+                       R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+               }
+#ifdef DOT11_N_SUPPORT
+               else
+               {
+                       R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+               }
+#endif // DOT11_N_SUPPORT //
+       }
+
+}
+
+VOID AsicTurnOffRFClk(
+       IN PRTMP_ADAPTER pAd,
+       IN      UCHAR           Channel)
+{
+
+       // RF R2 bit 18 = 0
+       UINT32                  R1 = 0, R2 = 0, R3 = 0;
+       UCHAR                   index;
+       RTMP_RF_REGS    *RFRegTable;
+
+       RFRegTable = RF2850RegTable;
+
+       switch (pAd->RfIcType)
+       {
+               case RFIC_2820:
+               case RFIC_2850:
+               case RFIC_2720:
+               case RFIC_2750:
+
+                       for (index = 0; index < NUM_OF_2850_CHNL; index++)
+                       {
+                               if (Channel == RFRegTable[index].Channel)
+                               {
+                                       R1 = RFRegTable[index].R1 & 0xffffdfff;
+                                       R2 = RFRegTable[index].R2 & 0xfffbffff;
+                                       R3 = RFRegTable[index].R3 & 0xfff3ffff;
+
+                                       RTMP_RF_IO_WRITE32(pAd, R1);
+                                       RTMP_RF_IO_WRITE32(pAd, R2);
+
+                                       // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
+                                       // Set RF R2 bit18=0, R3 bit[18:19]=0
+                                       //if (pAd->StaCfg.bRadio == FALSE)
+                                       if (1)
+                                       {
+                                               RTMP_RF_IO_WRITE32(pAd, R3);
+
+                                               DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x,  R3 = 0x%08x \n",
+                                                       Channel, pAd->RfIcType, R2, R3));
+                                       }
+                                       else
+                                               DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
+                                                       Channel, pAd->RfIcType, R2));
+                                       break;
+                               }
+                       }
+                       break;
+
+               default:
+                       break;
+       }
+}
+
+
+VOID AsicTurnOnRFClk(
+       IN PRTMP_ADAPTER pAd,
+       IN      UCHAR                   Channel)
+{
+
+       // RF R2 bit 18 = 0
+       UINT32                  R1 = 0, R2 = 0, R3 = 0;
+       UCHAR                   index;
+       RTMP_RF_REGS    *RFRegTable;
+
+       RFRegTable = RF2850RegTable;
+
+       switch (pAd->RfIcType)
+       {
+               case RFIC_2820:
+               case RFIC_2850:
+               case RFIC_2720:
+               case RFIC_2750:
+
+                       for (index = 0; index < NUM_OF_2850_CHNL; index++)
+                       {
+                               if (Channel == RFRegTable[index].Channel)
+                               {
+                                       R3 = pAd->LatchRfRegs.R3;
+                                       R3 &= 0xfff3ffff;
+                                       R3 |= 0x00080000;
+                                       RTMP_RF_IO_WRITE32(pAd, R3);
+
+                                       R1 = RFRegTable[index].R1;
+                                       RTMP_RF_IO_WRITE32(pAd, R1);
+
+                                       R2 = RFRegTable[index].R2;
+                                       if (pAd->Antenna.field.TxPath == 1)
+                                       {
+                                               R2 |= 0x4000;   // If TXpath is 1, bit 14 = 1;
+                                       }
+
+                                       if (pAd->Antenna.field.RxPath == 2)
+                                       {
+                                               R2 |= 0x40;     // write 1 to off Rxpath.
+                                       }
+                                       else if (pAd->Antenna.field.RxPath == 1)
+                                       {
+                                               R2 |= 0x20040;  // write 1 to off RxPath
+                                       }
+                                       RTMP_RF_IO_WRITE32(pAd, R2);
+
+                                       break;
+                               }
+                       }
+                       break;
+
+               default:
+                       break;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
+               Channel,
+               pAd->RfIcType,
+               R2));
+}
+
diff --git a/drivers/staging/rt2870/common/netif_block.c b/drivers/staging/rt2870/common/netif_block.c
new file mode 100644 (file)
index 0000000..d3f7d08
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#include "../rt_config.h"
+#include "netif_block.h"
+
+static NETIF_ENTRY freeNetIfEntryPool[FREE_NETIF_POOL_SIZE];
+static LIST_HEADER freeNetIfEntryList;
+
+void initblockQueueTab(
+       IN PRTMP_ADAPTER pAd)
+{
+       int i;
+
+       initList(&freeNetIfEntryList);
+       for (i = 0; i < FREE_NETIF_POOL_SIZE; i++)
+               insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)&freeNetIfEntryPool[i]);
+
+       for (i=0; i < NUM_OF_TX_RING; i++)
+               initList(&pAd->blockQueueTab[i].NetIfList);
+
+       return;
+}
+
+BOOLEAN blockNetIf(
+       IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry,
+       IN PNET_DEV pNetDev)
+{
+       PNETIF_ENTRY pNetIfEntry = NULL;
+
+       if ((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(&freeNetIfEntryList)) != NULL)
+       {
+               netif_stop_queue(pNetDev);
+               pNetIfEntry->pNetDev = pNetDev;
+               insertTailList(&pBlockQueueEntry->NetIfList, (PLIST_ENTRY)pNetIfEntry);
+
+               pBlockQueueEntry->SwTxQueueBlockFlag = TRUE;
+               DBGPRINT(RT_DEBUG_TRACE, ("netif_stop_queue(%s)\n", pNetDev->name));
+       }
+       else
+               return FALSE;
+
+       return TRUE;
+}
+
+VOID releaseNetIf(
+       IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry)
+{
+       PNETIF_ENTRY pNetIfEntry = NULL;
+       PLIST_HEADER pNetIfList = &pBlockQueueEntry->NetIfList;
+
+       while((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(pNetIfList)) !=  NULL)
+       {
+               PNET_DEV pNetDev = pNetIfEntry->pNetDev;
+               netif_wake_queue(pNetDev);
+               insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)pNetIfEntry);
+
+               DBGPRINT(RT_DEBUG_TRACE, ("netif_wake_queue(%s)\n", pNetDev->name));
+       }
+       pBlockQueueEntry->SwTxQueueBlockFlag = FALSE;
+       return;
+}
+
+
+VOID StopNetIfQueue(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR QueIdx,
+       IN PNDIS_PACKET pPacket)
+{
+       PNET_DEV NetDev = NULL;
+       UCHAR IfIdx = 0;
+       BOOLEAN valid = FALSE;
+
+#ifdef APCLI_SUPPORT
+       if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_APCLI)
+       {
+               IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_APCLI) % MAX_APCLI_NUM;
+               NetDev = pAd->ApCfg.ApCliTab[IfIdx].dev;
+       }
+       else
+#endif // APCLI_SUPPORT //
+#ifdef WDS_SUPPORT
+       if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_WDS)
+       {
+               IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_WDS) % MAX_WDS_ENTRY;
+               NetDev = pAd->WdsTab.WdsEntry[IfIdx].dev;
+       }
+       else
+#endif // WDS_SUPPORT //
+       {
+#ifdef MBSS_SUPPORT
+               if (pAd->OpMode == OPMODE_AP)
+               {
+                       IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_MBSSID) % MAX_MBSSID_NUM;
+                       NetDev = pAd->ApCfg.MBSSID[IfIdx].MSSIDDev;
+               }
+               else
+               {
+                       IfIdx = MAIN_MBSSID;
+                       NetDev = pAd->net_dev;
+               }
+#else
+               IfIdx = MAIN_MBSSID;
+               NetDev = pAd->net_dev;
+#endif
+       }
+
+       // WMM support 4 software queues.
+       // One software queue full doesn't mean device have no capbility to transmit packet.
+       // So disable block Net-If queue function while WMM enable.
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               valid = (pAd->CommonCfg.bWmmCapable == TRUE) ? FALSE : TRUE;
+#endif // CONFIG_STA_SUPPORT //
+
+       if (valid)
+               blockNetIf(&pAd->blockQueueTab[QueIdx], NetDev);
+       return;
+}
+
diff --git a/drivers/staging/rt2870/common/rtmp_init.c b/drivers/staging/rt2870/common/rtmp_init.c
new file mode 100644 (file)
index 0000000..87028fd
--- /dev/null
@@ -0,0 +1,4132 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       rtmp_init.c
+
+       Abstract:
+       Miniport generic portion header file
+
+       Revision History:
+       Who         When          What
+       --------    ----------    ----------------------------------------------
+       Paul Lin    2002-08-01    created
+    John Chang  2004-08-20    RT2561/2661 use scatter-gather scheme
+    Jan Lee  2006-09-15    RT2860. Change for 802.11n , EEPROM, Led, BA, HT.
+*/
+#include "../rt_config.h"
+#include "firmware.h"
+
+//#define BIN_IN_FILE /* use *.bin firmware */
+
+UCHAR    BIT8[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
+ULONG    BIT32[] = {0x00000001, 0x00000002, 0x00000004, 0x00000008,
+                                       0x00000010, 0x00000020, 0x00000040, 0x00000080,
+                                       0x00000100, 0x00000200, 0x00000400, 0x00000800,
+                                       0x00001000, 0x00002000, 0x00004000, 0x00008000,
+                                       0x00010000, 0x00020000, 0x00040000, 0x00080000,
+                                       0x00100000, 0x00200000, 0x00400000, 0x00800000,
+                                       0x01000000, 0x02000000, 0x04000000, 0x08000000,
+                                       0x10000000, 0x20000000, 0x40000000, 0x80000000};
+
+char*   CipherName[] = {"none","wep64","wep128","TKIP","AES","CKIP64","CKIP128"};
+
+const unsigned short ccitt_16Table[] = {
+       0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+       0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
+       0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
+       0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
+       0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
+       0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
+       0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
+       0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
+       0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
+       0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
+       0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
+       0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
+       0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
+       0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
+       0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
+       0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
+       0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
+       0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
+       0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
+       0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
+       0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
+       0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+       0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
+       0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
+       0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
+       0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
+       0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
+       0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
+       0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
+       0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
+       0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
+       0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
+};
+#define ByteCRC16(v, crc) \
+       (unsigned short)((crc << 8) ^  ccitt_16Table[((crc >> 8) ^ (v)) & 255])
+
+unsigned char BitReverse(unsigned char x)
+{
+       int i;
+       unsigned char Temp=0;
+       for(i=0; ; i++)
+       {
+               if(x & 0x80)    Temp |= 0x80;
+               if(i==7)                break;
+               x       <<= 1;
+               Temp >>= 1;
+       }
+       return Temp;
+}
+
+//
+// BBP register initialization set
+//
+REG_PAIR   BBPRegTable[] = {
+       {BBP_R65,               0x2C},          // fix rssi issue
+       {BBP_R66,               0x38},  // Also set this default value to pAd->BbpTuning.R66CurrentValue at initial
+       {BBP_R69,               0x12},
+       {BBP_R70,               0xa},   // BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa
+       {BBP_R73,               0x10},
+       {BBP_R81,               0x37},
+       {BBP_R82,               0x62},
+       {BBP_R83,               0x6A},
+       {BBP_R84,               0x99},  // 0x19 is for rt2860E and after. This is for extension channel overlapping IOT. 0x99 is for rt2860D and before
+       {BBP_R86,               0x00},  // middle range issue, Rory @2008-01-28
+       {BBP_R91,               0x04},  // middle range issue, Rory @2008-01-28
+       {BBP_R92,               0x00},  // middle range issue, Rory @2008-01-28
+       {BBP_R103,      0x00},  // near range high-power issue, requested from Gary @2008-0528
+       {BBP_R105,              0x05},  // 0x05 is for rt2860E to turn on FEQ control. It is safe for rt2860D and before, because Bit 7:2 are reserved in rt2860D and before.
+};
+#define        NUM_BBP_REG_PARMS       (sizeof(BBPRegTable) / sizeof(REG_PAIR))
+
+//
+// RF register initialization set
+//
+#ifdef RT2870
+REG_PAIR   RT30xx_RFRegTable[] = {
+        {RF_R04,          0x40},
+        {RF_R05,          0x03},
+        {RF_R06,          0x02},
+        {RF_R07,          0x70},
+        {RF_R09,          0x0F},
+        {RF_R10,          0x71},
+        {RF_R11,          0x21},
+        {RF_R12,          0x7B},
+        {RF_R14,          0x90},
+        {RF_R15,          0x58},
+        {RF_R16,          0xB3},
+        {RF_R17,          0x92},
+        {RF_R18,          0x2C},
+        {RF_R19,          0x02},
+        {RF_R20,          0xBA},
+        {RF_R21,          0xDB},
+        {RF_R24,          0x16},
+        {RF_R25,          0x01},
+        {RF_R27,          0x03},
+        {RF_R29,          0x1F},
+};
+#define        NUM_RF_REG_PARMS        (sizeof(RT30xx_RFRegTable) / sizeof(REG_PAIR))
+#endif // RT2870 //
+
+//
+// ASIC register initialization sets
+//
+
+RTMP_REG_PAIR  MACRegTable[] = {
+#if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200)
+       {BCN_OFFSET0,                   0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */
+       {BCN_OFFSET1,                   0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */
+#elif defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x100)
+       {BCN_OFFSET0,                   0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */
+       {BCN_OFFSET1,                   0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */
+#else
+    #error You must re-calculate new value for BCN_OFFSET0 & BCN_OFFSET1 in MACRegTable[]!!!
+#endif // HW_BEACON_OFFSET //
+
+       {LEGACY_BASIC_RATE,             0x0000013f}, //  Basic rate set bitmap
+       {HT_BASIC_RATE,         0x00008003}, // Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI.
+       {MAC_SYS_CTRL,          0x00}, // 0x1004, , default Disable RX
+       {RX_FILTR_CFG,          0x17f97}, //0x1400  , RX filter control,
+       {BKOFF_SLOT_CFG,        0x209}, // default set short slot time, CC_DELAY_TIME should be 2
+       {TX_SW_CFG0,            0x0},           // Gary,2008-05-21 for CWC test
+       {TX_SW_CFG1,            0x80606}, // Gary,2006-08-23
+       {TX_LINK_CFG,           0x1020},                // Gary,2006-08-23
+       //{TX_TIMEOUT_CFG,      0x00182090},    // CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT
+       {TX_TIMEOUT_CFG,        0x000a2090},    // CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT , Modify for 2860E ,2007-08-01
+       {MAX_LEN_CFG,           MAX_AGGREGATION_SIZE | 0x00001000},     // 0x3018, MAX frame length. Max PSDU = 16kbytes.
+       {LED_CFG,               0x7f031e46}, // Gary, 2006-08-23
+       {PBF_MAX_PCNT,                  0x1F3FBF9F},    //0x1F3f7f9f},          //Jan, 2006/04/20
+       //{TX_RTY_CFG,                  0x6bb80408},    // Jan, 2006/11/16
+       {TX_RTY_CFG,                    0x47d01f0f},    // Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03
+       {AUTO_RSP_CFG,                  0x00000013},    // Initial Auto_Responder, because QA will turn off Auto-Responder
+       {CCK_PROT_CFG,                  0x05740003 /*0x01740003*/},     // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled.
+       {OFDM_PROT_CFG,                 0x05740003 /*0x01740003*/},     // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled.
+#ifdef RT2870
+       {PBF_CFG,                               0xf40006},              // Only enable Queue 2
+       {MM40_PROT_CFG,                 0x3F44084},             // Initial Auto_Responder, because QA will turn off Auto-Responder
+       {WPDMA_GLO_CFG,                 0x00000030},
+#endif // RT2870 //
+       {GF20_PROT_CFG,                 0x01744004},    // set 19:18 --> Short NAV for MIMO PS
+       {GF40_PROT_CFG,                 0x03F44084},
+       {MM20_PROT_CFG,                 0x01744004},
+       {TXOP_CTRL_CFG,                 0x0000583f, /*0x0000243f*/ /*0x000024bf*/},     //Extension channel backoff.
+       {TX_RTS_CFG,                    0x00092b20},
+//#ifdef WIFI_TEST
+       {EXP_ACK_TIME,                  0x002400ca},    // default value
+//#else
+//     {EXP_ACK_TIME,                  0x005400ca},    // suggested by Gray @ 20070323 for 11n intel-sta throughput
+//#endif // end - WIFI_TEST //
+       {TXOP_HLDR_ET,                  0x00000002},
+
+       /* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us
+               is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0
+               and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping
+               will always lost. So we change the SIFS of CCK from 10us to 16us. */
+       {XIFS_TIME_CFG,                 0x33a41010},
+       {PWR_PIN_CFG,                   0x00000003},    // patch for 2880-E
+};
+
+
+#ifdef CONFIG_STA_SUPPORT
+RTMP_REG_PAIR  STAMACRegTable[] =      {
+       {WMM_AIFSN_CFG,         0x00002273},
+       {WMM_CWMIN_CFG, 0x00002344},
+       {WMM_CWMAX_CFG, 0x000034aa},
+};
+#endif // CONFIG_STA_SUPPORT //
+
+#define        NUM_MAC_REG_PARMS               (sizeof(MACRegTable) / sizeof(RTMP_REG_PAIR))
+#ifdef CONFIG_STA_SUPPORT
+#define        NUM_STA_MAC_REG_PARMS   (sizeof(STAMACRegTable) / sizeof(RTMP_REG_PAIR))
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef RT2870
+//
+// RT2870 Firmware Spec only used 1 oct for version expression
+//
+#define FIRMWARE_MINOR_VERSION 7
+
+#endif // RT2870 //
+
+// New 8k byte firmware size for RT3071/RT3072
+#define FIRMWAREIMAGE_MAX_LENGTH       0x2000
+#define FIRMWAREIMAGE_LENGTH           (sizeof (FirmwareImage) / sizeof(UCHAR))
+#define FIRMWARE_MAJOR_VERSION 0
+
+#define FIRMWAREIMAGEV1_LENGTH 0x1000
+#define FIRMWAREIMAGEV2_LENGTH 0x1000
+
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Allocate RTMP_ADAPTER data block and do some initialization
+
+       Arguments:
+               Adapter         Pointer to our adapter
+
+       Return Value:
+               NDIS_STATUS_SUCCESS
+               NDIS_STATUS_FAILURE
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+NDIS_STATUS    RTMPAllocAdapterBlock(
+       IN  PVOID       handle,
+       OUT     PRTMP_ADAPTER   *ppAdapter)
+{
+       PRTMP_ADAPTER   pAd;
+       NDIS_STATUS             Status;
+       INT                     index;
+       UCHAR                   *pBeaconBuf = NULL;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocAdapterBlock\n"));
+
+       *ppAdapter = NULL;
+
+       do
+       {
+               // Allocate RTMP_ADAPTER memory block
+               pBeaconBuf = kmalloc(MAX_BEACON_SIZE, MEM_ALLOC_FLAG);
+               if (pBeaconBuf == NULL)
+               {
+                       Status = NDIS_STATUS_FAILURE;
+                       DBGPRINT_ERR(("Failed to allocate memory - BeaconBuf!\n"));
+                       break;
+               }
+
+               Status = AdapterBlockAllocateMemory(handle, (PVOID *)&pAd);
+               if (Status != NDIS_STATUS_SUCCESS)
+               {
+                       DBGPRINT_ERR(("Failed to allocate memory - ADAPTER\n"));
+                       break;
+               }
+               pAd->BeaconBuf = pBeaconBuf;
+               printk("\n\n=== pAd = %p, size = %d ===\n\n", pAd, (UINT32)sizeof(RTMP_ADAPTER));
+
+
+               // Init spin locks
+               NdisAllocateSpinLock(&pAd->MgmtRingLock);
+
+               for (index =0 ; index < NUM_OF_TX_RING; index++)
+               {
+                       NdisAllocateSpinLock(&pAd->TxSwQueueLock[index]);
+                       NdisAllocateSpinLock(&pAd->DeQueueLock[index]);
+                       pAd->DeQueueRunning[index] = FALSE;
+               }
+
+               NdisAllocateSpinLock(&pAd->irq_lock);
+
+       } while (FALSE);
+
+       if ((Status != NDIS_STATUS_SUCCESS) && (pBeaconBuf))
+               kfree(pBeaconBuf);
+
+       *ppAdapter = pAd;
+
+       DBGPRINT_S(Status, ("<-- RTMPAllocAdapterBlock, Status=%x\n", Status));
+       return Status;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Read initial Tx power per MCS and BW from EEPROM
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPReadTxPwrPerRate(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       ULONG           data, Adata, Gdata;
+       USHORT          i, value, value2;
+       INT                     Apwrdelta, Gpwrdelta;
+       UCHAR           t1,t2,t3,t4;
+       BOOLEAN         bValid, bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE;
+
+       //
+       // Get power delta for 20MHz and 40MHz.
+       //
+       DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n"));
+       RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2);
+       Apwrdelta = 0;
+       Gpwrdelta = 0;
+
+       if ((value2 & 0xff) != 0xff)
+       {
+               if ((value2 & 0x80))
+                       Gpwrdelta = (value2&0xf);
+
+               if ((value2 & 0x40))
+                       bGpwrdeltaMinus = FALSE;
+               else
+                       bGpwrdeltaMinus = TRUE;
+       }
+       if ((value2 & 0xff00) != 0xff00)
+       {
+               if ((value2 & 0x8000))
+                       Apwrdelta = ((value2&0xf00)>>8);
+
+               if ((value2 & 0x4000))
+                       bApwrdeltaMinus = FALSE;
+               else
+                       bApwrdeltaMinus = TRUE;
+       }
+       DBGPRINT(RT_DEBUG_TRACE, ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta));
+
+       //
+       // Get Txpower per MCS for 20MHz in 2.4G.
+       //
+       for (i=0; i<5; i++)
+       {
+               RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4, value);
+               data = value;
+               if (bApwrdeltaMinus == FALSE)
+               {
+                       t1 = (value&0xf)+(Apwrdelta);
+                       if (t1 > 0xf)
+                               t1 = 0xf;
+                       t2 = ((value&0xf0)>>4)+(Apwrdelta);
+                       if (t2 > 0xf)
+                               t2 = 0xf;
+                       t3 = ((value&0xf00)>>8)+(Apwrdelta);
+                       if (t3 > 0xf)
+                               t3 = 0xf;
+                       t4 = ((value&0xf000)>>12)+(Apwrdelta);
+                       if (t4 > 0xf)
+                               t4 = 0xf;
+               }
+               else
+               {
+                       if ((value&0xf) > Apwrdelta)
+                               t1 = (value&0xf)-(Apwrdelta);
+                       else
+                               t1 = 0;
+                       if (((value&0xf0)>>4) > Apwrdelta)
+                               t2 = ((value&0xf0)>>4)-(Apwrdelta);
+                       else
+                               t2 = 0;
+                       if (((value&0xf00)>>8) > Apwrdelta)
+                               t3 = ((value&0xf00)>>8)-(Apwrdelta);
+                       else
+                               t3 = 0;
+                       if (((value&0xf000)>>12) > Apwrdelta)
+                               t4 = ((value&0xf000)>>12)-(Apwrdelta);
+                       else
+                               t4 = 0;
+               }
+               Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+               if (bGpwrdeltaMinus == FALSE)
+               {
+                       t1 = (value&0xf)+(Gpwrdelta);
+                       if (t1 > 0xf)
+                               t1 = 0xf;
+                       t2 = ((value&0xf0)>>4)+(Gpwrdelta);
+                       if (t2 > 0xf)
+                               t2 = 0xf;
+                       t3 = ((value&0xf00)>>8)+(Gpwrdelta);
+                       if (t3 > 0xf)
+                               t3 = 0xf;
+                       t4 = ((value&0xf000)>>12)+(Gpwrdelta);
+                       if (t4 > 0xf)
+                               t4 = 0xf;
+               }
+               else
+               {
+                       if ((value&0xf) > Gpwrdelta)
+                               t1 = (value&0xf)-(Gpwrdelta);
+                       else
+                               t1 = 0;
+                       if (((value&0xf0)>>4) > Gpwrdelta)
+                               t2 = ((value&0xf0)>>4)-(Gpwrdelta);
+                       else
+                               t2 = 0;
+                       if (((value&0xf00)>>8) > Gpwrdelta)
+                               t3 = ((value&0xf00)>>8)-(Gpwrdelta);
+                       else
+                               t3 = 0;
+                       if (((value&0xf000)>>12) > Gpwrdelta)
+                               t4 = ((value&0xf000)>>12)-(Gpwrdelta);
+                       else
+                               t4 = 0;
+               }
+               Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+
+               RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4 + 2, value);
+               if (bApwrdeltaMinus == FALSE)
+               {
+                       t1 = (value&0xf)+(Apwrdelta);
+                       if (t1 > 0xf)
+                               t1 = 0xf;
+                       t2 = ((value&0xf0)>>4)+(Apwrdelta);
+                       if (t2 > 0xf)
+                               t2 = 0xf;
+                       t3 = ((value&0xf00)>>8)+(Apwrdelta);
+                       if (t3 > 0xf)
+                               t3 = 0xf;
+                       t4 = ((value&0xf000)>>12)+(Apwrdelta);
+                       if (t4 > 0xf)
+                               t4 = 0xf;
+               }
+               else
+               {
+                       if ((value&0xf) > Apwrdelta)
+                               t1 = (value&0xf)-(Apwrdelta);
+                       else
+                               t1 = 0;
+                       if (((value&0xf0)>>4) > Apwrdelta)
+                               t2 = ((value&0xf0)>>4)-(Apwrdelta);
+                       else
+                               t2 = 0;
+                       if (((value&0xf00)>>8) > Apwrdelta)
+                               t3 = ((value&0xf00)>>8)-(Apwrdelta);
+                       else
+                               t3 = 0;
+                       if (((value&0xf000)>>12) > Apwrdelta)
+                               t4 = ((value&0xf000)>>12)-(Apwrdelta);
+                       else
+                               t4 = 0;
+               }
+               Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+               if (bGpwrdeltaMinus == FALSE)
+               {
+                       t1 = (value&0xf)+(Gpwrdelta);
+                       if (t1 > 0xf)
+                               t1 = 0xf;
+                       t2 = ((value&0xf0)>>4)+(Gpwrdelta);
+                       if (t2 > 0xf)
+                               t2 = 0xf;
+                       t3 = ((value&0xf00)>>8)+(Gpwrdelta);
+                       if (t3 > 0xf)
+                               t3 = 0xf;
+                       t4 = ((value&0xf000)>>12)+(Gpwrdelta);
+                       if (t4 > 0xf)
+                               t4 = 0xf;
+               }
+               else
+               {
+                       if ((value&0xf) > Gpwrdelta)
+                               t1 = (value&0xf)-(Gpwrdelta);
+                       else
+                               t1 = 0;
+                       if (((value&0xf0)>>4) > Gpwrdelta)
+                               t2 = ((value&0xf0)>>4)-(Gpwrdelta);
+                       else
+                               t2 = 0;
+                       if (((value&0xf00)>>8) > Gpwrdelta)
+                               t3 = ((value&0xf00)>>8)-(Gpwrdelta);
+                       else
+                               t3 = 0;
+                       if (((value&0xf000)>>12) > Gpwrdelta)
+                               t4 = ((value&0xf000)>>12)-(Gpwrdelta);
+                       else
+                               t4 = 0;
+               }
+               Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+               data |= (value<<16);
+
+               pAd->Tx20MPwrCfgABand[i] = pAd->Tx40MPwrCfgABand[i] = Adata;
+               pAd->Tx20MPwrCfgGBand[i] = pAd->Tx40MPwrCfgGBand[i] = Gdata;
+
+               if (data != 0xffffffff)
+                       RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data);
+               DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx,  Adata = %lx,  Gdata = %lx \n", data, Adata, Gdata));
+       }
+
+       //
+       // Check this block is valid for 40MHz in 2.4G. If invalid, use parameter for 20MHz in 2.4G
+       //
+       bValid = TRUE;
+       for (i=0; i<6; i++)
+       {
+               RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 2 + i*2, value);
+               if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00))
+               {
+                       bValid = FALSE;
+                       break;
+               }
+       }
+
+       //
+       // Get Txpower per MCS for 40MHz in 2.4G.
+       //
+       if (bValid)
+       {
+               for (i=0; i<4; i++)
+               {
+                       RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4, value);
+                       if (bGpwrdeltaMinus == FALSE)
+                       {
+                               t1 = (value&0xf)+(Gpwrdelta);
+                               if (t1 > 0xf)
+                                       t1 = 0xf;
+                               t2 = ((value&0xf0)>>4)+(Gpwrdelta);
+                               if (t2 > 0xf)
+                                       t2 = 0xf;
+                               t3 = ((value&0xf00)>>8)+(Gpwrdelta);
+                               if (t3 > 0xf)
+                                       t3 = 0xf;
+                               t4 = ((value&0xf000)>>12)+(Gpwrdelta);
+                               if (t4 > 0xf)
+                                       t4 = 0xf;
+                       }
+                       else
+                       {
+                               if ((value&0xf) > Gpwrdelta)
+                                       t1 = (value&0xf)-(Gpwrdelta);
+                               else
+                                       t1 = 0;
+                               if (((value&0xf0)>>4) > Gpwrdelta)
+                                       t2 = ((value&0xf0)>>4)-(Gpwrdelta);
+                               else
+                                       t2 = 0;
+                               if (((value&0xf00)>>8) > Gpwrdelta)
+                                       t3 = ((value&0xf00)>>8)-(Gpwrdelta);
+                               else
+                                       t3 = 0;
+                               if (((value&0xf000)>>12) > Gpwrdelta)
+                                       t4 = ((value&0xf000)>>12)-(Gpwrdelta);
+                               else
+                                       t4 = 0;
+                       }
+                       Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+
+                       RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4 + 2, value);
+                       if (bGpwrdeltaMinus == FALSE)
+                       {
+                               t1 = (value&0xf)+(Gpwrdelta);
+                               if (t1 > 0xf)
+                                       t1 = 0xf;
+                               t2 = ((value&0xf0)>>4)+(Gpwrdelta);
+                               if (t2 > 0xf)
+                                       t2 = 0xf;
+                               t3 = ((value&0xf00)>>8)+(Gpwrdelta);
+                               if (t3 > 0xf)
+                                       t3 = 0xf;
+                               t4 = ((value&0xf000)>>12)+(Gpwrdelta);
+                               if (t4 > 0xf)
+                                       t4 = 0xf;
+                       }
+                       else
+                       {
+                               if ((value&0xf) > Gpwrdelta)
+                                       t1 = (value&0xf)-(Gpwrdelta);
+                               else
+                                       t1 = 0;
+                               if (((value&0xf0)>>4) > Gpwrdelta)
+                                       t2 = ((value&0xf0)>>4)-(Gpwrdelta);
+                               else
+                                       t2 = 0;
+                               if (((value&0xf00)>>8) > Gpwrdelta)
+                                       t3 = ((value&0xf00)>>8)-(Gpwrdelta);
+                               else
+                                       t3 = 0;
+                               if (((value&0xf000)>>12) > Gpwrdelta)
+                                       t4 = ((value&0xf000)>>12)-(Gpwrdelta);
+                               else
+                                       t4 = 0;
+                       }
+                       Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+
+                       if (i == 0)
+                               pAd->Tx40MPwrCfgGBand[i+1] = (pAd->Tx40MPwrCfgGBand[i+1] & 0x0000FFFF) | (Gdata & 0xFFFF0000);
+                       else
+                               pAd->Tx40MPwrCfgGBand[i+1] = Gdata;
+
+                       DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 2.4G band, Gdata = %lx \n", Gdata));
+               }
+       }
+
+       //
+       // Check this block is valid for 20MHz in 5G. If invalid, use parameter for 20MHz in 2.4G
+       //
+       bValid = TRUE;
+       for (i=0; i<8; i++)
+       {
+               RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 2 + i*2, value);
+               if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00))
+               {
+                       bValid = FALSE;
+                       break;
+               }
+       }
+
+       //
+       // Get Txpower per MCS for 20MHz in 5G.
+       //
+       if (bValid)
+       {
+               for (i=0; i<5; i++)
+               {
+                       RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4, value);
+                       if (bApwrdeltaMinus == FALSE)
+                       {
+                               t1 = (value&0xf)+(Apwrdelta);
+                               if (t1 > 0xf)
+                                       t1 = 0xf;
+                               t2 = ((value&0xf0)>>4)+(Apwrdelta);
+                               if (t2 > 0xf)
+                                       t2 = 0xf;
+                               t3 = ((value&0xf00)>>8)+(Apwrdelta);
+                               if (t3 > 0xf)
+                                       t3 = 0xf;
+                               t4 = ((value&0xf000)>>12)+(Apwrdelta);
+                               if (t4 > 0xf)
+                                       t4 = 0xf;
+                       }
+                       else
+                       {
+                               if ((value&0xf) > Apwrdelta)
+                                       t1 = (value&0xf)-(Apwrdelta);
+                               else
+                                       t1 = 0;
+                               if (((value&0xf0)>>4) > Apwrdelta)
+                                       t2 = ((value&0xf0)>>4)-(Apwrdelta);
+                               else
+                                       t2 = 0;
+                               if (((value&0xf00)>>8) > Apwrdelta)
+                                       t3 = ((value&0xf00)>>8)-(Apwrdelta);
+                               else
+                                       t3 = 0;
+                               if (((value&0xf000)>>12) > Apwrdelta)
+                                       t4 = ((value&0xf000)>>12)-(Apwrdelta);
+                               else
+                                       t4 = 0;
+                       }
+                       Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+
+                       RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4 + 2, value);
+                       if (bApwrdeltaMinus == FALSE)
+                       {
+                               t1 = (value&0xf)+(Apwrdelta);
+                               if (t1 > 0xf)
+                                       t1 = 0xf;
+                               t2 = ((value&0xf0)>>4)+(Apwrdelta);
+                               if (t2 > 0xf)
+                                       t2 = 0xf;
+                               t3 = ((value&0xf00)>>8)+(Apwrdelta);
+                               if (t3 > 0xf)
+                                       t3 = 0xf;
+                               t4 = ((value&0xf000)>>12)+(Apwrdelta);
+                               if (t4 > 0xf)
+                                       t4 = 0xf;
+                       }
+                       else
+                       {
+                               if ((value&0xf) > Apwrdelta)
+                                       t1 = (value&0xf)-(Apwrdelta);
+                               else
+                                       t1 = 0;
+                               if (((value&0xf0)>>4) > Apwrdelta)
+                                       t2 = ((value&0xf0)>>4)-(Apwrdelta);
+                               else
+                                       t2 = 0;
+                               if (((value&0xf00)>>8) > Apwrdelta)
+                                       t3 = ((value&0xf00)>>8)-(Apwrdelta);
+                               else
+                                       t3 = 0;
+                               if (((value&0xf000)>>12) > Apwrdelta)
+                                       t4 = ((value&0xf000)>>12)-(Apwrdelta);
+                               else
+                                       t4 = 0;
+                       }
+                       Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+
+                       if (i == 0)
+                               pAd->Tx20MPwrCfgABand[i] = (pAd->Tx20MPwrCfgABand[i] & 0x0000FFFF) | (Adata & 0xFFFF0000);
+                       else
+                               pAd->Tx20MPwrCfgABand[i] = Adata;
+
+                       DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 5GHz band, Adata = %lx \n", Adata));
+               }
+       }
+
+       //
+       // Check this block is valid for 40MHz in 5G. If invalid, use parameter for 20MHz in 2.4G
+       //
+       bValid = TRUE;
+       for (i=0; i<6; i++)
+       {
+               RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 2 + i*2, value);
+               if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00))
+               {
+                       bValid = FALSE;
+                       break;
+               }
+       }
+
+       //
+       // Get Txpower per MCS for 40MHz in 5G.
+       //
+       if (bValid)
+       {
+               for (i=0; i<4; i++)
+               {
+                       RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4, value);
+                       if (bApwrdeltaMinus == FALSE)
+                       {
+                               t1 = (value&0xf)+(Apwrdelta);
+                               if (t1 > 0xf)
+                                       t1 = 0xf;
+                               t2 = ((value&0xf0)>>4)+(Apwrdelta);
+                               if (t2 > 0xf)
+                                       t2 = 0xf;
+                               t3 = ((value&0xf00)>>8)+(Apwrdelta);
+                               if (t3 > 0xf)
+                                       t3 = 0xf;
+                               t4 = ((value&0xf000)>>12)+(Apwrdelta);
+                               if (t4 > 0xf)
+                                       t4 = 0xf;
+                       }
+                       else
+                       {
+                               if ((value&0xf) > Apwrdelta)
+                                       t1 = (value&0xf)-(Apwrdelta);
+                               else
+                                       t1 = 0;
+                               if (((value&0xf0)>>4) > Apwrdelta)
+                                       t2 = ((value&0xf0)>>4)-(Apwrdelta);
+                               else
+                                       t2 = 0;
+                               if (((value&0xf00)>>8) > Apwrdelta)
+                                       t3 = ((value&0xf00)>>8)-(Apwrdelta);
+                               else
+                                       t3 = 0;
+                               if (((value&0xf000)>>12) > Apwrdelta)
+                                       t4 = ((value&0xf000)>>12)-(Apwrdelta);
+                               else
+                                       t4 = 0;
+                       }
+                       Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+
+                       RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4 + 2, value);
+                       if (bApwrdeltaMinus == FALSE)
+                       {
+                               t1 = (value&0xf)+(Apwrdelta);
+                               if (t1 > 0xf)
+                                       t1 = 0xf;
+                               t2 = ((value&0xf0)>>4)+(Apwrdelta);
+                               if (t2 > 0xf)
+                                       t2 = 0xf;
+                               t3 = ((value&0xf00)>>8)+(Apwrdelta);
+                               if (t3 > 0xf)
+                                       t3 = 0xf;
+                               t4 = ((value&0xf000)>>12)+(Apwrdelta);
+                               if (t4 > 0xf)
+                                       t4 = 0xf;
+                       }
+                       else
+                       {
+                               if ((value&0xf) > Apwrdelta)
+                                       t1 = (value&0xf)-(Apwrdelta);
+                               else
+                                       t1 = 0;
+                               if (((value&0xf0)>>4) > Apwrdelta)
+                                       t2 = ((value&0xf0)>>4)-(Apwrdelta);
+                               else
+                                       t2 = 0;
+                               if (((value&0xf00)>>8) > Apwrdelta)
+                                       t3 = ((value&0xf00)>>8)-(Apwrdelta);
+                               else
+                                       t3 = 0;
+                               if (((value&0xf000)>>12) > Apwrdelta)
+                                       t4 = ((value&0xf000)>>12)-(Apwrdelta);
+                               else
+                                       t4 = 0;
+                       }
+                       Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+
+                       if (i == 0)
+                               pAd->Tx40MPwrCfgABand[i+1] = (pAd->Tx40MPwrCfgABand[i+1] & 0x0000FFFF) | (Adata & 0xFFFF0000);
+                       else
+                               pAd->Tx40MPwrCfgABand[i+1] = Adata;
+
+                       DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 5GHz band, Adata = %lx \n", Adata));
+               }
+       }
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Read initial channel power parameters from EEPROM
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPReadChannelPwr(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       UCHAR                           i, choffset;
+       EEPROM_TX_PWR_STRUC         Power;
+       EEPROM_TX_PWR_STRUC         Power2;
+
+       // Read Tx power value for all channels
+       // Value from 1 - 0x7f. Default value is 24.
+       // Power value : 2.4G 0x00 (0) ~ 0x1F (31)
+       //             : 5.5G 0xF9 (-7) ~ 0x0F (15)
+
+       // 0. 11b/g, ch1 - ch 14
+       for (i = 0; i < 7; i++)
+       {
+//             Power.word = RTMP_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2);
+//             Power2.word = RTMP_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2);
+               RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, Power.word);
+               RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, Power2.word);
+               pAd->TxPower[i * 2].Channel = i * 2 + 1;
+               pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2;
+
+               if ((Power.field.Byte0 > 31) || (Power.field.Byte0 < 0))
+                       pAd->TxPower[i * 2].Power = DEFAULT_RF_TX_POWER;
+               else
+                       pAd->TxPower[i * 2].Power = Power.field.Byte0;
+
+               if ((Power.field.Byte1 > 31) || (Power.field.Byte1 < 0))
+                       pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER;
+               else
+                       pAd->TxPower[i * 2 + 1].Power = Power.field.Byte1;
+
+               if ((Power2.field.Byte0 > 31) || (Power2.field.Byte0 < 0))
+                       pAd->TxPower[i * 2].Power2 = DEFAULT_RF_TX_POWER;
+               else
+                       pAd->TxPower[i * 2].Power2 = Power2.field.Byte0;
+
+               if ((Power2.field.Byte1 > 31) || (Power2.field.Byte1 < 0))
+                       pAd->TxPower[i * 2 + 1].Power2 = DEFAULT_RF_TX_POWER;
+               else
+                       pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1;
+       }
+
+       // 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz)
+       // 1.1 Fill up channel
+       choffset = 14;
+       for (i = 0; i < 4; i++)
+       {
+               pAd->TxPower[3 * i + choffset + 0].Channel      = 36 + i * 8 + 0;
+               pAd->TxPower[3 * i + choffset + 0].Power        = DEFAULT_RF_TX_POWER;
+               pAd->TxPower[3 * i + choffset + 0].Power2       = DEFAULT_RF_TX_POWER;
+
+               pAd->TxPower[3 * i + choffset + 1].Channel      = 36 + i * 8 + 2;
+               pAd->TxPower[3 * i + choffset + 1].Power        = DEFAULT_RF_TX_POWER;
+               pAd->TxPower[3 * i + choffset + 1].Power2       = DEFAULT_RF_TX_POWER;
+
+               pAd->TxPower[3 * i + choffset + 2].Channel      = 36 + i * 8 + 4;
+               pAd->TxPower[3 * i + choffset + 2].Power        = DEFAULT_RF_TX_POWER;
+               pAd->TxPower[3 * i + choffset + 2].Power2       = DEFAULT_RF_TX_POWER;
+       }
+
+       // 1.2 Fill up power
+       for (i = 0; i < 6; i++)
+       {
+//             Power.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2);
+//             Power2.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2);
+               RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, Power.word);
+               RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, Power2.word);
+
+               if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
+
+               if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
+
+               if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
+
+               if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
+       }
+
+       // 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz)
+       // 2.1 Fill up channel
+       choffset = 14 + 12;
+       for (i = 0; i < 5; i++)
+       {
+               pAd->TxPower[3 * i + choffset + 0].Channel      = 100 + i * 8 + 0;
+               pAd->TxPower[3 * i + choffset + 0].Power        = DEFAULT_RF_TX_POWER;
+               pAd->TxPower[3 * i + choffset + 0].Power2       = DEFAULT_RF_TX_POWER;
+
+               pAd->TxPower[3 * i + choffset + 1].Channel      = 100 + i * 8 + 2;
+               pAd->TxPower[3 * i + choffset + 1].Power        = DEFAULT_RF_TX_POWER;
+               pAd->TxPower[3 * i + choffset + 1].Power2       = DEFAULT_RF_TX_POWER;
+
+               pAd->TxPower[3 * i + choffset + 2].Channel      = 100 + i * 8 + 4;
+               pAd->TxPower[3 * i + choffset + 2].Power        = DEFAULT_RF_TX_POWER;
+               pAd->TxPower[3 * i + choffset + 2].Power2       = DEFAULT_RF_TX_POWER;
+       }
+       pAd->TxPower[3 * 5 + choffset + 0].Channel              = 140;
+       pAd->TxPower[3 * 5 + choffset + 0].Power                = DEFAULT_RF_TX_POWER;
+       pAd->TxPower[3 * 5 + choffset + 0].Power2               = DEFAULT_RF_TX_POWER;
+
+       // 2.2 Fill up power
+       for (i = 0; i < 8; i++)
+       {
+//             Power.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2);
+//             Power2.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2);
+               RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word);
+               RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word);
+
+               if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
+
+               if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
+
+               if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
+
+               if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
+       }
+
+       // 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165 (including central frequency in BW 40MHz)
+       // 3.1 Fill up channel
+       choffset = 14 + 12 + 16;
+       for (i = 0; i < 2; i++)
+       {
+               pAd->TxPower[3 * i + choffset + 0].Channel      = 149 + i * 8 + 0;
+               pAd->TxPower[3 * i + choffset + 0].Power        = DEFAULT_RF_TX_POWER;
+               pAd->TxPower[3 * i + choffset + 0].Power2       = DEFAULT_RF_TX_POWER;
+
+               pAd->TxPower[3 * i + choffset + 1].Channel      = 149 + i * 8 + 2;
+               pAd->TxPower[3 * i + choffset + 1].Power        = DEFAULT_RF_TX_POWER;
+               pAd->TxPower[3 * i + choffset + 1].Power2       = DEFAULT_RF_TX_POWER;
+
+               pAd->TxPower[3 * i + choffset + 2].Channel      = 149 + i * 8 + 4;
+               pAd->TxPower[3 * i + choffset + 2].Power        = DEFAULT_RF_TX_POWER;
+               pAd->TxPower[3 * i + choffset + 2].Power2       = DEFAULT_RF_TX_POWER;
+       }
+       pAd->TxPower[3 * 2 + choffset + 0].Channel              = 165;
+       pAd->TxPower[3 * 2 + choffset + 0].Power                = DEFAULT_RF_TX_POWER;
+       pAd->TxPower[3 * 2 + choffset + 0].Power2               = DEFAULT_RF_TX_POWER;
+
+       // 3.2 Fill up power
+       for (i = 0; i < 4; i++)
+       {
+//             Power.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2);
+//             Power2.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2);
+               RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word);
+               RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word);
+
+               if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
+
+               if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
+
+               if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
+
+               if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
+                       pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
+       }
+
+       // 4. Print and Debug
+       choffset = 14 + 12 + 16 + 7;
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Read the following from the registry
+               1. All the parameters
+               2. NetworkAddres
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+               WrapperConfigurationContext     For use by NdisOpenConfiguration
+
+       Return Value:
+               NDIS_STATUS_SUCCESS
+               NDIS_STATUS_FAILURE
+               NDIS_STATUS_RESOURCES
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+NDIS_STATUS    NICReadRegParameters(
+       IN      PRTMP_ADAPTER           pAd,
+       IN      NDIS_HANDLE                     WrapperConfigurationContext
+       )
+{
+       NDIS_STATUS                                             Status = NDIS_STATUS_SUCCESS;
+       DBGPRINT_S(Status, ("<-- NICReadRegParameters, Status=%x\n", Status));
+       return Status;
+}
+
+
+#ifdef RT2870
+/*
+       ========================================================================
+
+       Routine Description:
+               For RF filter calibration purpose
+
+       Arguments:
+               pAd                          Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       ========================================================================
+*/
+VOID RTUSBFilterCalibration(
+       IN PRTMP_ADAPTER pAd)
+{
+       UCHAR   R55x = 0, value, FilterTarget = 0x1E, BBPValue;
+       UINT    loop = 0, count = 0, loopcnt = 0, ReTry = 0;
+       UCHAR   RF_R24_Value = 0;
+
+       // Give bbp filter initial value
+       pAd->Mlme.CaliBW20RfR24 = 0x16;
+       pAd->Mlme.CaliBW40RfR24 = 0x36;  //Bit[5] must be 1 for BW 40
+
+       do
+       {
+               if (loop == 1)  //BandWidth = 40 MHz
+               {
+                       // Write 0x27 to RF_R24 to program filter
+                       RF_R24_Value = 0x27;
+                       RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value);
+                       FilterTarget = 0x19;
+
+                       // when calibrate BW40, BBP mask must set to BW40.
+                       RTUSBReadBBPRegister(pAd, BBP_R4, &BBPValue);
+                       BBPValue&= (~0x18);
+                       BBPValue|= (0x10);
+                       RTUSBWriteBBPRegister(pAd, BBP_R4, BBPValue);
+               }
+               else                    //BandWidth = 20 MHz
+               {
+                       // Write 0x07 to RF_R24 to program filter
+                       RF_R24_Value = 0x07;
+                       RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value);
+                       FilterTarget = 0x16;
+               }
+
+               // Write 0x01 to RF_R22 to enable baseband loopback mode
+               RT30xxReadRFRegister(pAd, RF_R22, &value);
+               value |= 0x01;
+               RT30xxWriteRFRegister(pAd, RF_R22, value);
+
+               // Write 0x00 to BBP_R24 to set power & frequency of passband test tone
+               RTUSBWriteBBPRegister(pAd, BBP_R24, 0);
+
+               do
+               {
+                       // Write 0x90 to BBP_R25 to transmit test tone
+                       RTUSBWriteBBPRegister(pAd, BBP_R25, 0x90);
+
+                       RTMPusecDelay(1000);
+                       // Read BBP_R55[6:0] for received power, set R55x = BBP_R55[6:0]
+                       RTUSBReadBBPRegister(pAd, BBP_R55, &value);
+                       R55x = value & 0xFF;
+
+               } while ((ReTry++ < 100) && (R55x == 0));
+
+               // Write 0x06 to BBP_R24 to set power & frequency of stopband test tone
+               RTUSBWriteBBPRegister(pAd, BBP_R24, 0x06);
+
+               while(TRUE)
+               {
+                       // Write 0x90 to BBP_R25 to transmit test tone
+                       RTUSBWriteBBPRegister(pAd, BBP_R25, 0x90);
+
+                       //We need to wait for calibration
+                       RTMPusecDelay(1000);
+                       RTUSBReadBBPRegister(pAd, BBP_R55, &value);
+                       value &= 0xFF;
+                       if ((R55x - value) < FilterTarget)
+                       {
+                               RF_R24_Value ++;
+                       }
+                       else if ((R55x - value) == FilterTarget)
+                       {
+                               RF_R24_Value ++;
+                               count ++;
+                       }
+                       else
+                       {
+                               break;
+                       }
+
+                       // prevent infinite loop cause driver hang.
+                       if (loopcnt++ > 100)
+                       {
+                               DBGPRINT(RT_DEBUG_ERROR, ("RTUSBFilterCalibration - can't find a valid value, loopcnt=%d stop calibrating", loopcnt));
+                               break;
+                       }
+
+                       // Write RF_R24 to program filter
+                       RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value);
+               }
+
+               if (count > 0)
+               {
+                       RF_R24_Value = RF_R24_Value - ((count) ? (1) : (0));
+               }
+
+               // Store for future usage
+               if (loopcnt < 100)
+               {
+                       if (loop++ == 0)
+                       {
+                               //BandWidth = 20 MHz
+                               pAd->Mlme.CaliBW20RfR24 = (UCHAR)RF_R24_Value;
+                       }
+                       else
+                       {
+                               //BandWidth = 40 MHz
+                               pAd->Mlme.CaliBW40RfR24 = (UCHAR)RF_R24_Value;
+                               break;
+                       }
+               }
+               else
+                       break;
+
+               RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value);
+
+               // reset count
+               count = 0;
+       } while(TRUE);
+
+       //
+       // Set back to initial state
+       //
+       RTUSBWriteBBPRegister(pAd, BBP_R24, 0);
+
+       RT30xxReadRFRegister(pAd, RF_R22, &value);
+       value &= ~(0x01);
+       RT30xxWriteRFRegister(pAd, RF_R22, value);
+
+       // set BBP back to BW20
+       RTUSBReadBBPRegister(pAd, BBP_R4, &BBPValue);
+       BBPValue&= (~0x18);
+       RTUSBWriteBBPRegister(pAd, BBP_R4, BBPValue);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("RTUSBFilterCalibration - CaliBW20RfR24=0x%x, CaliBW40RfR24=0x%x\n", pAd->Mlme.CaliBW20RfR24, pAd->Mlme.CaliBW40RfR24));
+}
+
+
+VOID NICInitRT30xxRFRegisters(IN PRTMP_ADAPTER pAd)
+{
+       INT i;
+       // Driver must read EEPROM to get RfIcType before initial RF registers
+       // Initialize RF register to default value
+        if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) ||(pAd->RfIcType == RFIC_2020)))
+        {
+                // Init RF calibration
+                // Driver should toggle RF R30 bit7 before init RF registers
+                ULONG RfReg = 0;
+                RT30xxReadRFRegister(pAd, RF_R30, (PUCHAR)&RfReg);
+                RfReg |= 0x80;
+                RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg);
+                RTMPusecDelay(1000);
+                RfReg &= 0x7F;
+                RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg);
+
+                // Initialize RF register to default value
+                for (i = 0; i < NUM_RF_REG_PARMS; i++)
+                {
+                        RT30xxWriteRFRegister(pAd, RT30xx_RFRegTable[i].Register, RT30xx_RFRegTable[i].Value);
+                }
+
+                //For RF filter Calibration
+                RTUSBFilterCalibration(pAd);
+        }
+
+}
+#endif // RT2870 //
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Read initial parameters from EEPROM
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   NICReadEEPROMParameters(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  mac_addr)
+{
+       UINT32                  data = 0;
+       USHORT                  i, value, value2;
+       UCHAR                   TmpPhy;
+       EEPROM_TX_PWR_STRUC         Power;
+       EEPROM_VERSION_STRUC    Version;
+       EEPROM_ANTENNA_STRUC    Antenna;
+       EEPROM_NIC_CONFIG2_STRUC    NicConfig2;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--> NICReadEEPROMParameters\n"));
+
+       // Init EEPROM Address Number, before access EEPROM; if 93c46, EEPROMAddressNum=6, else if 93c66, EEPROMAddressNum=8
+       RTMP_IO_READ32(pAd, E2PROM_CSR, &data);
+       DBGPRINT(RT_DEBUG_TRACE, ("--> E2PROM_CSR = 0x%x\n", data));
+
+       if((data & 0x30) == 0)
+               pAd->EEPROMAddressNum = 6;              // 93C46
+       else if((data & 0x30) == 0x10)
+               pAd->EEPROMAddressNum = 8;     // 93C66
+       else
+               pAd->EEPROMAddressNum = 8;     // 93C86
+       DBGPRINT(RT_DEBUG_TRACE, ("--> EEPROMAddressNum = %d\n", pAd->EEPROMAddressNum ));
+
+       // RT2860 MAC no longer auto load MAC address from E2PROM. Driver has to intialize
+       // MAC address registers according to E2PROM setting
+       if (mac_addr == NULL ||
+               strlen(mac_addr) != 17 ||
+               mac_addr[2] != ':'  || mac_addr[5] != ':'  || mac_addr[8] != ':' ||
+               mac_addr[11] != ':' || mac_addr[14] != ':')
+       {
+               USHORT  Addr01,Addr23,Addr45 ;
+
+               RT28xx_EEPROM_READ16(pAd, 0x04, Addr01);
+               RT28xx_EEPROM_READ16(pAd, 0x06, Addr23);
+               RT28xx_EEPROM_READ16(pAd, 0x08, Addr45);
+
+               pAd->PermanentAddress[0] = (UCHAR)(Addr01 & 0xff);
+               pAd->PermanentAddress[1] = (UCHAR)(Addr01 >> 8);
+               pAd->PermanentAddress[2] = (UCHAR)(Addr23 & 0xff);
+               pAd->PermanentAddress[3] = (UCHAR)(Addr23 >> 8);
+               pAd->PermanentAddress[4] = (UCHAR)(Addr45 & 0xff);
+               pAd->PermanentAddress[5] = (UCHAR)(Addr45 >> 8);
+
+               DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from E2PROM \n"));
+       }
+       else
+       {
+               INT             j;
+               PUCHAR  macptr;
+
+               macptr = mac_addr;
+
+               for (j=0; j<MAC_ADDR_LEN; j++)
+               {
+                       AtoH(macptr, &pAd->PermanentAddress[j], 1);
+                       macptr=macptr+3;
+               }
+
+               DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from module parameter \n"));
+       }
+
+
+       {
+#if 0
+               USHORT  Addr01,Addr23,Addr45 ;
+
+               Addr01=RTMP_EEPROM_READ16(pAd, 0x04);
+               Addr23=RTMP_EEPROM_READ16(pAd, 0x06);
+               Addr45=RTMP_EEPROM_READ16(pAd, 0x08);
+
+               pAd->PermanentAddress[0] = (UCHAR)(Addr01 & 0xff);
+               pAd->PermanentAddress[1] = (UCHAR)(Addr01 >> 8);
+               pAd->PermanentAddress[2] = (UCHAR)(Addr23 & 0xff);
+               pAd->PermanentAddress[3] = (UCHAR)(Addr23 >> 8);
+               pAd->PermanentAddress[4] = (UCHAR)(Addr45 & 0xff);
+               pAd->PermanentAddress[5] = (UCHAR)(Addr45 >> 8);
+#endif
+               //more conveninet to test mbssid, so ap's bssid &0xf1
+               if (pAd->PermanentAddress[0] == 0xff)
+                       pAd->PermanentAddress[0] = RandomByte(pAd)&0xf8;
+
+               //if (pAd->PermanentAddress[5] == 0xff)
+               //      pAd->PermanentAddress[5] = RandomByte(pAd)&0xf8;
+
+               DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n",
+                       pAd->PermanentAddress[0], pAd->PermanentAddress[1],
+                       pAd->PermanentAddress[2], pAd->PermanentAddress[3],
+                       pAd->PermanentAddress[4], pAd->PermanentAddress[5]));
+               if (pAd->bLocalAdminMAC == FALSE)
+               {
+                       MAC_DW0_STRUC csr2;
+                       MAC_DW1_STRUC csr3;
+                       COPY_MAC_ADDR(pAd->CurrentAddress, pAd->PermanentAddress);
+                       csr2.field.Byte0 = pAd->CurrentAddress[0];
+                       csr2.field.Byte1 = pAd->CurrentAddress[1];
+                       csr2.field.Byte2 = pAd->CurrentAddress[2];
+                       csr2.field.Byte3 = pAd->CurrentAddress[3];
+                       RTMP_IO_WRITE32(pAd, MAC_ADDR_DW0, csr2.word);
+                       csr3.word = 0;
+                       csr3.field.Byte4 = pAd->CurrentAddress[4];
+                       csr3.field.Byte5 = pAd->CurrentAddress[5];
+                       csr3.field.U2MeMask = 0xff;
+                       RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word);
+                       DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n",
+                               pAd->PermanentAddress[0], pAd->PermanentAddress[1],
+                               pAd->PermanentAddress[2], pAd->PermanentAddress[3],
+                               pAd->PermanentAddress[4], pAd->PermanentAddress[5]));
+               }
+       }
+
+       // if not return early. cause fail at emulation.
+       // Init the channel number for TX channel power
+       RTMPReadChannelPwr(pAd);
+
+       // if E2PROM version mismatch with driver's expectation, then skip
+       // all subsequent E2RPOM retieval and set a system error bit to notify GUI
+       RT28xx_EEPROM_READ16(pAd, EEPROM_VERSION_OFFSET, Version.word);
+       pAd->EepromVersion = Version.field.Version + Version.field.FaeReleaseNumber * 256;
+       DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: Version = %d, FAE release #%d\n", Version.field.Version, Version.field.FaeReleaseNumber));
+
+       if (Version.field.Version > VALID_EEPROM_VERSION)
+       {
+               DBGPRINT_ERR(("E2PROM: WRONG VERSION 0x%x, should be %d\n",Version.field.Version, VALID_EEPROM_VERSION));
+               /*pAd->SystemErrorBitmap |= 0x00000001;
+
+               // hard-code default value when no proper E2PROM installed
+               pAd->bAutoTxAgcA = FALSE;
+               pAd->bAutoTxAgcG = FALSE;
+
+               // Default the channel power
+               for (i = 0; i < MAX_NUM_OF_CHANNELS; i++)
+                       pAd->TxPower[i].Power = DEFAULT_RF_TX_POWER;
+
+               // Default the channel power
+               for (i = 0; i < MAX_NUM_OF_11JCHANNELS; i++)
+                       pAd->TxPower11J[i].Power = DEFAULT_RF_TX_POWER;
+
+               for(i = 0; i < NUM_EEPROM_BBP_PARMS; i++)
+                       pAd->EEPROMDefaultValue[i] = 0xffff;
+               return;  */
+       }
+
+       // Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd
+       RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, value);
+       pAd->EEPROMDefaultValue[0] = value;
+
+       RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value);
+       pAd->EEPROMDefaultValue[1] = value;
+
+       RT28xx_EEPROM_READ16(pAd, 0x38, value); // Country Region
+       pAd->EEPROMDefaultValue[2] = value;
+
+       for(i = 0; i < 8; i++)
+       {
+               RT28xx_EEPROM_READ16(pAd, EEPROM_BBP_BASE_OFFSET + i*2, value);
+               pAd->EEPROMDefaultValue[i+3] = value;
+       }
+
+       // We have to parse NIC configuration 0 at here.
+       // If TSSI did not have preloaded value, it should reset the TxAutoAgc to false
+       // Therefore, we have to read TxAutoAgc control beforehand.
+       // Read Tx AGC control bit
+       Antenna.word = pAd->EEPROMDefaultValue[0];
+       if (Antenna.word == 0xFFFF)
+       {
+               Antenna.word = 0;
+               Antenna.field.RfIcType = RFIC_2820;
+               Antenna.field.TxPath = 1;
+               Antenna.field.RxPath = 2;
+               DBGPRINT(RT_DEBUG_WARN, ("E2PROM error, hard code as 0x%04x\n", Antenna.word));
+       }
+
+       // Choose the desired Tx&Rx stream.
+       if ((pAd->CommonCfg.TxStream == 0) || (pAd->CommonCfg.TxStream > Antenna.field.TxPath))
+               pAd->CommonCfg.TxStream = Antenna.field.TxPath;
+
+       if ((pAd->CommonCfg.RxStream == 0) || (pAd->CommonCfg.RxStream > Antenna.field.RxPath))
+       {
+               pAd->CommonCfg.RxStream = Antenna.field.RxPath;
+
+               if ((pAd->MACVersion < RALINK_2883_VERSION) &&
+                       (pAd->CommonCfg.RxStream > 2))
+               {
+                       // only 2 Rx streams for RT2860 series
+                       pAd->CommonCfg.RxStream = 2;
+               }
+       }
+
+       // 3*3
+       // read value from EEPROM and set them to CSR174 ~ 177 in chain0 ~ chain2
+       // yet implement
+       for(i=0; i<3; i++)
+       {
+       }
+
+       NicConfig2.word = pAd->EEPROMDefaultValue[1];
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               NicConfig2.word = 0;
+               if ((NicConfig2.word & 0x00ff) == 0xff)
+               {
+                       NicConfig2.word &= 0xff00;
+               }
+
+               if ((NicConfig2.word >> 8) == 0xff)
+               {
+                       NicConfig2.word &= 0x00ff;
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       if (NicConfig2.field.DynamicTxAgcControl == 1)
+               pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE;
+       else
+               pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE;
+
+       DBGPRINT_RAW(RT_DEBUG_TRACE, ("NICReadEEPROMParameters: RxPath = %d, TxPath = %d\n", Antenna.field.RxPath, Antenna.field.TxPath));
+
+       // Save the antenna for future use
+       pAd->Antenna.word = Antenna.word;
+
+       //
+       // Reset PhyMode if we don't support 802.11a
+       // Only RFIC_2850 & RFIC_2750 support 802.11a
+       //
+       if ((Antenna.field.RfIcType != RFIC_2850) && (Antenna.field.RfIcType != RFIC_2750))
+       {
+               if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) ||
+                       (pAd->CommonCfg.PhyMode == PHY_11A))
+                       pAd->CommonCfg.PhyMode = PHY_11BG_MIXED;
+#ifdef DOT11_N_SUPPORT
+               else if ((pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED)   ||
+                                (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED)     ||
+                                (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED)    ||
+                                (pAd->CommonCfg.PhyMode == PHY_11N_5G))
+                       pAd->CommonCfg.PhyMode = PHY_11BGN_MIXED;
+#endif // DOT11_N_SUPPORT //
+       }
+
+       // Read TSSI reference and TSSI boundary for temperature compensation. This is ugly
+       // 0. 11b/g
+       {
+               /* these are tempature reference value (0x00 ~ 0xFE)
+                  ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
+                  TssiPlusBoundaryG [4] [3] [2] [1] [0] (smaller) +
+                  TssiMinusBoundaryG[0] [1] [2] [3] [4] (larger) */
+               RT28xx_EEPROM_READ16(pAd, 0x6E, Power.word);
+               pAd->TssiMinusBoundaryG[4] = Power.field.Byte0;
+               pAd->TssiMinusBoundaryG[3] = Power.field.Byte1;
+               RT28xx_EEPROM_READ16(pAd, 0x70, Power.word);
+               pAd->TssiMinusBoundaryG[2] = Power.field.Byte0;
+               pAd->TssiMinusBoundaryG[1] = Power.field.Byte1;
+               RT28xx_EEPROM_READ16(pAd, 0x72, Power.word);
+               pAd->TssiRefG   = Power.field.Byte0; /* reference value [0] */
+               pAd->TssiPlusBoundaryG[1] = Power.field.Byte1;
+               RT28xx_EEPROM_READ16(pAd, 0x74, Power.word);
+               pAd->TssiPlusBoundaryG[2] = Power.field.Byte0;
+               pAd->TssiPlusBoundaryG[3] = Power.field.Byte1;
+               RT28xx_EEPROM_READ16(pAd, 0x76, Power.word);
+               pAd->TssiPlusBoundaryG[4] = Power.field.Byte0;
+               pAd->TxAgcStepG = Power.field.Byte1;
+               pAd->TxAgcCompensateG = 0;
+               pAd->TssiMinusBoundaryG[0] = pAd->TssiRefG;
+               pAd->TssiPlusBoundaryG[0]  = pAd->TssiRefG;
+
+               // Disable TxAgc if the based value is not right
+               if (pAd->TssiRefG == 0xff)
+                       pAd->bAutoTxAgcG = FALSE;
+
+               DBGPRINT(RT_DEBUG_TRACE,("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n",
+                       pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1],
+                       pAd->TssiRefG,
+                       pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4],
+                       pAd->TxAgcStepG, pAd->bAutoTxAgcG));
+       }
+       // 1. 11a
+       {
+               RT28xx_EEPROM_READ16(pAd, 0xD4, Power.word);
+               pAd->TssiMinusBoundaryA[4] = Power.field.Byte0;
+               pAd->TssiMinusBoundaryA[3] = Power.field.Byte1;
+               RT28xx_EEPROM_READ16(pAd, 0xD6, Power.word);
+               pAd->TssiMinusBoundaryA[2] = Power.field.Byte0;
+               pAd->TssiMinusBoundaryA[1] = Power.field.Byte1;
+               RT28xx_EEPROM_READ16(pAd, 0xD8, Power.word);
+               pAd->TssiRefA   = Power.field.Byte0;
+               pAd->TssiPlusBoundaryA[1] = Power.field.Byte1;
+               RT28xx_EEPROM_READ16(pAd, 0xDA, Power.word);
+               pAd->TssiPlusBoundaryA[2] = Power.field.Byte0;
+               pAd->TssiPlusBoundaryA[3] = Power.field.Byte1;
+               RT28xx_EEPROM_READ16(pAd, 0xDC, Power.word);
+               pAd->TssiPlusBoundaryA[4] = Power.field.Byte0;
+               pAd->TxAgcStepA = Power.field.Byte1;
+               pAd->TxAgcCompensateA = 0;
+               pAd->TssiMinusBoundaryA[0] = pAd->TssiRefA;
+               pAd->TssiPlusBoundaryA[0]  = pAd->TssiRefA;
+
+               // Disable TxAgc if the based value is not right
+               if (pAd->TssiRefA == 0xff)
+                       pAd->bAutoTxAgcA = FALSE;
+
+               DBGPRINT(RT_DEBUG_TRACE,("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n",
+                       pAd->TssiMinusBoundaryA[4], pAd->TssiMinusBoundaryA[3], pAd->TssiMinusBoundaryA[2], pAd->TssiMinusBoundaryA[1],
+                       pAd->TssiRefA,
+                       pAd->TssiPlusBoundaryA[1], pAd->TssiPlusBoundaryA[2], pAd->TssiPlusBoundaryA[3], pAd->TssiPlusBoundaryA[4],
+                       pAd->TxAgcStepA, pAd->bAutoTxAgcA));
+       }
+       pAd->BbpRssiToDbmDelta = 0x0;
+
+       // Read frequency offset setting for RF
+       RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value);
+       if ((value & 0x00FF) != 0x00FF)
+               pAd->RfFreqOffset = (ULONG) (value & 0x00FF);
+       else
+               pAd->RfFreqOffset = 0;
+       DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: RF FreqOffset=0x%lx \n", pAd->RfFreqOffset));
+
+       //CountryRegion byte offset (38h)
+       value = pAd->EEPROMDefaultValue[2] >> 8;                // 2.4G band
+       value2 = pAd->EEPROMDefaultValue[2] & 0x00FF;   // 5G band
+
+       if ((value <= REGION_MAXIMUM_BG_BAND) && (value2 <= REGION_MAXIMUM_A_BAND))
+       {
+               pAd->CommonCfg.CountryRegion = ((UCHAR) value) | 0x80;
+               pAd->CommonCfg.CountryRegionForABand = ((UCHAR) value2) | 0x80;
+               TmpPhy = pAd->CommonCfg.PhyMode;
+               pAd->CommonCfg.PhyMode = 0xff;
+               RTMPSetPhyMode(pAd, TmpPhy);
+#ifdef DOT11_N_SUPPORT
+               SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+       }
+
+       //
+       // Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch.
+       // The valid value are (-10 ~ 10)
+       //
+       RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value);
+       pAd->BGRssiOffset0 = value & 0x00ff;
+       pAd->BGRssiOffset1 = (value >> 8);
+       RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET+2, value);
+       pAd->BGRssiOffset2 = value & 0x00ff;
+       pAd->ALNAGain1 = (value >> 8);
+       RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value);
+       pAd->BLNAGain = value & 0x00ff;
+       pAd->ALNAGain0 = (value >> 8);
+
+       // Validate 11b/g RSSI_0 offset.
+       if ((pAd->BGRssiOffset0 < -10) || (pAd->BGRssiOffset0 > 10))
+               pAd->BGRssiOffset0 = 0;
+
+       // Validate 11b/g RSSI_1 offset.
+       if ((pAd->BGRssiOffset1 < -10) || (pAd->BGRssiOffset1 > 10))
+               pAd->BGRssiOffset1 = 0;
+
+       // Validate 11b/g RSSI_2 offset.
+       if ((pAd->BGRssiOffset2 < -10) || (pAd->BGRssiOffset2 > 10))
+               pAd->BGRssiOffset2 = 0;
+
+       RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value);
+       pAd->ARssiOffset0 = value & 0x00ff;
+       pAd->ARssiOffset1 = (value >> 8);
+       RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET+2), value);
+       pAd->ARssiOffset2 = value & 0x00ff;
+       pAd->ALNAGain2 = (value >> 8);
+
+       if (((UCHAR)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00))
+               pAd->ALNAGain1 = pAd->ALNAGain0;
+       if (((UCHAR)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00))
+               pAd->ALNAGain2 = pAd->ALNAGain0;
+
+       // Validate 11a RSSI_0 offset.
+       if ((pAd->ARssiOffset0 < -10) || (pAd->ARssiOffset0 > 10))
+               pAd->ARssiOffset0 = 0;
+
+       // Validate 11a RSSI_1 offset.
+       if ((pAd->ARssiOffset1 < -10) || (pAd->ARssiOffset1 > 10))
+               pAd->ARssiOffset1 = 0;
+
+       //Validate 11a RSSI_2 offset.
+       if ((pAd->ARssiOffset2 < -10) || (pAd->ARssiOffset2 > 10))
+               pAd->ARssiOffset2 = 0;
+
+       //
+       // Get LED Setting.
+       //
+       RT28xx_EEPROM_READ16(pAd, 0x3a, value);
+       pAd->LedCntl.word = (value&0xff00) >> 8;
+       RT28xx_EEPROM_READ16(pAd, EEPROM_LED1_OFFSET, value);
+       pAd->Led1 = value;
+       RT28xx_EEPROM_READ16(pAd, EEPROM_LED2_OFFSET, value);
+       pAd->Led2 = value;
+       RT28xx_EEPROM_READ16(pAd, EEPROM_LED3_OFFSET, value);
+       pAd->Led3 = value;
+
+       RTMPReadTxPwrPerRate(pAd);
+
+#ifdef SINGLE_SKU
+       //pAd->CommonCfg.DefineMaxTxPwr = RTMP_EEPROM_READ16(pAd, EEPROM_DEFINE_MAX_TXPWR);
+       RT28xx_EEPROM_READ16(pAd, EEPROM_DEFINE_MAX_TXPWR, pAd->CommonCfg.DefineMaxTxPwr);
+#endif // SINGLE_SKU //
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<-- NICReadEEPROMParameters\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Set default value from EEPROM
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   NICInitAsicFromEEPROM(
+       IN      PRTMP_ADAPTER   pAd)
+{
+#ifdef CONFIG_STA_SUPPORT
+       UINT32                                  data = 0;
+       UCHAR   BBPR1 = 0;
+#endif // CONFIG_STA_SUPPORT //
+       USHORT                                  i;
+       EEPROM_ANTENNA_STRUC    Antenna;
+       EEPROM_NIC_CONFIG2_STRUC    NicConfig2;
+       UCHAR   BBPR3 = 0;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n"));
+       for(i = 3; i < NUM_EEPROM_BBP_PARMS; i++)
+       {
+               UCHAR BbpRegIdx, BbpValue;
+
+               if ((pAd->EEPROMDefaultValue[i] != 0xFFFF) && (pAd->EEPROMDefaultValue[i] != 0))
+               {
+                       BbpRegIdx = (UCHAR)(pAd->EEPROMDefaultValue[i] >> 8);
+                       BbpValue  = (UCHAR)(pAd->EEPROMDefaultValue[i] & 0xff);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BbpRegIdx, BbpValue);
+               }
+       }
+
+       Antenna.word = pAd->Antenna.word;
+       pAd->Mlme.RealRxPath = (UCHAR) Antenna.field.RxPath;
+       pAd->RfIcType = (UCHAR) Antenna.field.RfIcType;
+
+       NicConfig2.word = pAd->EEPROMDefaultValue[1];
+
+
+       // Save the antenna for future use
+       pAd->NicConfig2.word = NicConfig2.word;
+
+       //
+       // Send LED Setting to MCU.
+       //
+       if (pAd->LedCntl.word == 0xFF)
+       {
+               pAd->LedCntl.word = 0x01;
+               pAd->Led1 = 0x5555;
+               pAd->Led2 = 0x2221;
+
+#ifdef RT2870
+               pAd->Led3 = 0x5627;
+#endif // RT2870 //
+       }
+
+       AsicSendCommandToMcu(pAd, 0x52, 0xff, (UCHAR)pAd->Led1, (UCHAR)(pAd->Led1 >> 8));
+       AsicSendCommandToMcu(pAd, 0x53, 0xff, (UCHAR)pAd->Led2, (UCHAR)(pAd->Led2 >> 8));
+       AsicSendCommandToMcu(pAd, 0x54, 0xff, (UCHAR)pAd->Led3, (UCHAR)(pAd->Led3 >> 8));
+    pAd->LedIndicatorStregth = 0xFF;
+    RTMPSetSignalLED(pAd, -100);       // Force signal strength Led to be turned off, before link up
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // Read Hardware controlled Radio state enable bit
+               if (NicConfig2.field.HardwareRadioControl == 1)
+               {
+                       pAd->StaCfg.bHardwareRadio = TRUE;
+
+                       // Read GPIO pin2 as Hardware controlled radio state
+                       RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
+                       if ((data & 0x04) == 0)
+                       {
+                               pAd->StaCfg.bHwRadio = FALSE;
+                               pAd->StaCfg.bRadio = FALSE;
+//                             RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818);
+                               RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+                       }
+               }
+               else
+                       pAd->StaCfg.bHardwareRadio = FALSE;
+
+               if (pAd->StaCfg.bRadio == FALSE)
+               {
+                       RTMPSetLED(pAd, LED_RADIO_OFF);
+               }
+               else
+               {
+                       RTMPSetLED(pAd, LED_RADIO_ON);
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       // Turn off patching for cardbus controller
+       if (NicConfig2.field.CardbusAcceleration == 1)
+       {
+//             pAd->bTest1 = TRUE;
+       }
+
+       if (NicConfig2.field.DynamicTxAgcControl == 1)
+               pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE;
+       else
+               pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE;
+       //
+       // Since BBP has been progamed, to make sure BBP setting will be
+       // upate inside of AsicAntennaSelect, so reset to UNKNOWN_BAND!!
+       //
+       pAd->CommonCfg.BandState = UNKNOWN_BAND;
+
+       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
+       BBPR3 &= (~0x18);
+       if(pAd->Antenna.field.RxPath == 3)
+       {
+               BBPR3 |= (0x10);
+       }
+       else if(pAd->Antenna.field.RxPath == 2)
+       {
+               BBPR3 |= (0x8);
+       }
+       else if(pAd->Antenna.field.RxPath == 1)
+       {
+               BBPR3 |= (0x0);
+       }
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // Handle the difference when 1T
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1);
+               if(pAd->Antenna.field.TxPath == 1)
+               {
+               BBPR1 &= (~0x18);
+               }
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1);
+
+               DBGPRINT(RT_DEBUG_TRACE, ("Use Hw Radio Control Pin=%d; if used Pin=%d;\n", pAd->CommonCfg.bHardwareRadio, pAd->CommonCfg.bHardwareRadio));
+       }
+#endif // CONFIG_STA_SUPPORT //
+       DBGPRINT(RT_DEBUG_TRACE, ("TxPath = %d, RxPath = %d, RFIC=%d, Polar+LED mode=%x\n", pAd->Antenna.field.TxPath, pAd->Antenna.field.RxPath, pAd->RfIcType, pAd->LedCntl.word));
+       DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitAsicFromEEPROM\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Initialize NIC hardware
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+NDIS_STATUS    NICInitializeAdapter(
+       IN      PRTMP_ADAPTER   pAd,
+       IN   BOOLEAN    bHardReset)
+{
+       NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
+       WPDMA_GLO_CFG_STRUC     GloCfg;
+//     INT_MASK_CSR_STRUC              IntMask;
+       ULONG   i =0, j=0;
+       AC_TXOP_CSR0_STRUC      csr0;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAdapter\n"));
+
+       // 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits:
+retry:
+       i = 0;
+       do
+       {
+               RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
+               if ((GloCfg.field.TxDMABusy == 0)  && (GloCfg.field.RxDMABusy == 0))
+                       break;
+
+               RTMPusecDelay(1000);
+               i++;
+       }while ( i<100);
+       DBGPRINT(RT_DEBUG_TRACE, ("<== DMA offset 0x208 = 0x%x\n", GloCfg.word));
+       GloCfg.word &= 0xff0;
+       GloCfg.field.EnTXWriteBackDDONE =1;
+       RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
+
+       // Record HW Beacon offset
+       pAd->BeaconOffset[0] = HW_BEACON_BASE0;
+       pAd->BeaconOffset[1] = HW_BEACON_BASE1;
+       pAd->BeaconOffset[2] = HW_BEACON_BASE2;
+       pAd->BeaconOffset[3] = HW_BEACON_BASE3;
+       pAd->BeaconOffset[4] = HW_BEACON_BASE4;
+       pAd->BeaconOffset[5] = HW_BEACON_BASE5;
+       pAd->BeaconOffset[6] = HW_BEACON_BASE6;
+       pAd->BeaconOffset[7] = HW_BEACON_BASE7;
+
+       //
+       // write all shared Ring's base address into ASIC
+       //
+
+       // asic simulation sequence put this ahead before loading firmware.
+       // pbf hardware reset
+
+       // Initialze ASIC for TX & Rx operation
+       if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS)
+       {
+               if (j++ == 0)
+               {
+                       NICLoadFirmware(pAd);
+                       goto retry;
+               }
+               return NDIS_STATUS_FAILURE;
+       }
+
+
+
+
+       // WMM parameter
+       csr0.word = 0;
+       RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
+       if (pAd->CommonCfg.PhyMode == PHY_11B)
+       {
+               csr0.field.Ac0Txop = 192;       // AC_VI: 192*32us ~= 6ms
+               csr0.field.Ac1Txop = 96;        // AC_VO: 96*32us  ~= 3ms
+       }
+       else
+       {
+               csr0.field.Ac0Txop = 96;        // AC_VI: 96*32us ~= 3ms
+               csr0.field.Ac1Txop = 48;        // AC_VO: 48*32us ~= 1.5ms
+       }
+       RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr0.word);
+
+
+
+
+       // reset action
+       // Load firmware
+       //  Status = NICLoadFirmware(pAd);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAdapter\n"));
+       return Status;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Initialize ASIC
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+NDIS_STATUS    NICInitializeAsic(
+       IN      PRTMP_ADAPTER   pAd,
+       IN  BOOLEAN             bHardReset)
+{
+       ULONG                   Index = 0;
+       UCHAR                   R0 = 0xff;
+       UINT32                  MacCsr12 = 0, Counter = 0;
+#ifdef RT2870
+       UINT32                  MacCsr0 = 0;
+       NTSTATUS                Status;
+       UCHAR                   Value = 0xff;
+#endif // RT2870 //
+       USHORT                  KeyIdx;
+       INT                             i,apidx;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n"));
+
+
+#ifdef RT2870
+       //
+       // Make sure MAC gets ready after NICLoadFirmware().
+       //
+       Index = 0;
+
+       //To avoid hang-on issue when interface up in kernel 2.4,
+       //we use a local variable "MacCsr0" instead of using "pAd->MACVersion" directly.
+       do
+       {
+               RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0);
+
+               if ((MacCsr0 != 0x00) && (MacCsr0 != 0xFFFFFFFF))
+                       break;
+
+               RTMPusecDelay(10);
+       } while (Index++ < 100);
+
+       pAd->MACVersion = MacCsr0;
+       DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0  [ Ver:Rev=0x%08x]\n", pAd->MACVersion));
+       // turn on bit13 (set to zero) after rt2860D. This is to solve high-current issue.
+       RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacCsr12);
+       MacCsr12 &= (~0x2000);
+       RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, MacCsr12);
+
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3);
+       RTMP_IO_WRITE32(pAd, USB_DMA_CFG, 0x0);
+       Status = RTUSBVenderReset(pAd);
+
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
+
+       // Initialize MAC register to default value
+       for(Index=0; Index<NUM_MAC_REG_PARMS; Index++)
+       {
+               RTMP_IO_WRITE32(pAd, (USHORT)MACRegTable[Index].Register, MACRegTable[Index].Value);
+       }
+
+       if(IS_RT3070(pAd))
+       {
+               // According to Frank Hsu (from Gary Tsao)
+               RTMP_IO_WRITE32(pAd, (USHORT)TX_SW_CFG0, 0x00000400);
+
+               // Initialize RT3070 serial MAC registers which is different from RT2870 serial
+               RTUSBWriteMACRegister(pAd, TX_SW_CFG1, 0);
+               RTUSBWriteMACRegister(pAd, TX_SW_CFG2, 0);
+       }
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               for (Index = 0; Index < NUM_STA_MAC_REG_PARMS; Index++)
+               {
+                       RTMP_IO_WRITE32(pAd, (USHORT)STAMACRegTable[Index].Register, STAMACRegTable[Index].Value);
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+#endif // RT2870 //
+
+       //
+       // Before program BBP, we need to wait BBP/RF get wake up.
+       //
+       Index = 0;
+       do
+       {
+               RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12);
+
+               if ((MacCsr12 & 0x03) == 0)     // if BB.RF is stable
+                       break;
+
+               DBGPRINT(RT_DEBUG_TRACE, ("Check MAC_STATUS_CFG  = Busy = %x\n", MacCsr12));
+               RTMPusecDelay(1000);
+       } while (Index++ < 100);
+
+    // The commands to firmware should be after these commands, these commands will init firmware
+       // PCI and USB are not the same because PCI driver needs to wait for PCI bus ready
+       RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0); // initialize BBP R/W access agent
+       RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0);
+       RTMPusecDelay(1000);
+
+       // Read BBP register, make sure BBP is up and running before write new data
+       Index = 0;
+       do
+       {
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R0, &R0);
+               DBGPRINT(RT_DEBUG_TRACE, ("BBP version = %x\n", R0));
+       } while ((++Index < 20) && ((R0 == 0xff) || (R0 == 0x00)));
+       //ASSERT(Index < 20); //this will cause BSOD on Check-build driver
+
+       if ((R0 == 0xff) || (R0 == 0x00))
+               return NDIS_STATUS_FAILURE;
+
+       // Initialize BBP register to default value
+       for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++)
+       {
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, BBPRegTable[Index].Value);
+       }
+
+       // for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT.
+       if ((pAd->MACVersion&0xffff) != 0x0101)
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19);
+
+#ifdef RT2870
+       //write RT3070 BBP wchich different with 2870 after write RT2870 BBP
+       if (IS_RT3070(pAd))
+       {
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0a);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x99);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R105, 0x05);
+       }
+#endif // RT2870 //
+
+       if (pAd->MACVersion == 0x28600100)
+       {
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12);
+    }
+
+       if (pAd->MACVersion >= RALINK_2880E_VERSION && pAd->MACVersion < RALINK_3070_VERSION) // 3*3
+       {
+               // enlarge MAX_LEN_CFG
+               UINT32 csr;
+               RTMP_IO_READ32(pAd, MAX_LEN_CFG, &csr);
+               csr &= 0xFFF;
+               csr |= 0x2000;
+               RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, csr);
+       }
+
+#ifdef RT2870
+{
+       UCHAR   MAC_Value[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0,0};
+
+       //Initialize WCID table
+       Value = 0xff;
+       for(Index =0 ;Index < 254;Index++)
+       {
+               RTUSBMultiWrite(pAd, (USHORT)(MAC_WCID_BASE + Index * 8), MAC_Value, 8);
+       }
+}
+#endif // RT2870 //
+
+       // Add radio off control
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               if (pAd->StaCfg.bRadio == FALSE)
+               {
+//                     RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818);
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set Radio Off\n"));
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       // Clear raw counters
+       RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter);
+       RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter);
+       RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter);
+       RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter);
+       RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter);
+       RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter);
+
+       // ASIC will keep garbage value after boot
+       // Clear all seared key table when initial
+       // This routine can be ignored in radio-ON/OFF operation.
+       if (bHardReset)
+       {
+               for (KeyIdx = 0; KeyIdx < 4; KeyIdx++)
+               {
+                       RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4*KeyIdx, 0);
+               }
+
+               // Clear all pairwise key table when initial
+               for (KeyIdx = 0; KeyIdx < 256; KeyIdx++)
+               {
+                       RTMP_IO_WRITE32(pAd, MAC_WCID_ATTRIBUTE_BASE + (KeyIdx * HW_WCID_ATTRI_SIZE), 1);
+               }
+       }
+
+       // assert HOST ready bit
+//  RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x0); // 2004-09-14 asked by Mark
+//  RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x4);
+
+       // It isn't necessary to clear this space when not hard reset.
+       if (bHardReset == TRUE)
+       {
+               // clear all on-chip BEACON frame space
+               for (apidx = 0; apidx < HW_BEACON_MAX_COUNT; apidx++)
+               {
+                       for (i = 0; i < HW_BEACON_OFFSET>>2; i+=4)
+                               RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[apidx] + i, 0x00);
+               }
+       }
+#ifdef RT2870
+       AsicDisableSync(pAd);
+       // Clear raw counters
+       RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter);
+       RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter);
+       RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter);
+       RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter);
+       RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter);
+       RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter);
+       // Default PCI clock cycle per ms is different as default setting, which is based on PCI.
+       RTMP_IO_READ32(pAd, USB_CYC_CFG, &Counter);
+       Counter&=0xffffff00;
+       Counter|=0x000001e;
+       RTMP_IO_WRITE32(pAd, USB_CYC_CFG, Counter);
+#endif // RT2870 //
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // for rt2860E and after, init TXOP_CTRL_CFG with 0x583f. This is for extension channel overlapping IOT.
+               if ((pAd->MACVersion&0xffff) != 0x0101)
+                       RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x583f);
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAsic\n"));
+       return NDIS_STATUS_SUCCESS;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Reset NIC Asics
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+               Reset NIC to initial state AS IS system boot up time.
+
+       ========================================================================
+*/
+VOID   NICIssueReset(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       UINT32  Value = 0;
+       DBGPRINT(RT_DEBUG_TRACE, ("--> NICIssueReset\n"));
+
+       // Abort Tx, prevent ASIC from writing to Host memory
+       //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x001f0000);
+
+       // Disable Rx, register value supposed will remain after reset
+       RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+       Value &= (0xfffffff3);
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+       // Issue reset and clear from reset state
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x03); // 2004-09-17 change from 0x01
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<-- NICIssueReset\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Check ASIC registers and find any reason the system might hang
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       ========================================================================
+*/
+BOOLEAN        NICCheckForHang(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       return (FALSE);
+}
+
+VOID NICUpdateFifoStaCounters(
+       IN PRTMP_ADAPTER pAd)
+{
+       TX_STA_FIFO_STRUC       StaFifo;
+       MAC_TABLE_ENTRY         *pEntry;
+       UCHAR                           i = 0;
+       UCHAR                   pid = 0, wcid = 0;
+       CHAR                            reTry;
+       UCHAR                           succMCS;
+
+#ifdef RALINK_ATE
+       /* Nothing to do in ATE mode */
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+               do
+               {
+                       RTMP_IO_READ32(pAd, TX_STA_FIFO, &StaFifo.word);
+
+                       if (StaFifo.field.bValid == 0)
+                               break;
+
+                       wcid = (UCHAR)StaFifo.field.wcid;
+
+
+               /* ignore NoACK and MGMT frame use 0xFF as WCID */
+                       if ((StaFifo.field.TxAckRequired == 0) || (wcid >= MAX_LEN_OF_MAC_TABLE))
+                       {
+                               i++;
+                               continue;
+                       }
+
+                       /* PID store Tx MCS Rate */
+                       pid = (UCHAR)StaFifo.field.PidType;
+
+                       pEntry = &pAd->MacTab.Content[wcid];
+
+                       pEntry->DebugFIFOCount++;
+
+#ifdef DOT11_N_SUPPORT
+                       if (StaFifo.field.TxBF) // 3*3
+                               pEntry->TxBFCount++;
+#endif // DOT11_N_SUPPORT //
+
+#ifdef UAPSD_AP_SUPPORT
+                       UAPSD_SP_AUE_Handle(pAd, pEntry, StaFifo.field.TxSuccess);
+#endif // UAPSD_AP_SUPPORT //
+
+                       if (!StaFifo.field.TxSuccess)
+                       {
+                               pEntry->FIFOCount++;
+                               pEntry->OneSecTxFailCount++;
+
+                               if (pEntry->FIFOCount >= 1)
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("#"));
+#if 0
+                                       SendRefreshBAR(pAd, pEntry);
+                                       pEntry->NoBADataCountDown = 64;
+#else
+#ifdef DOT11_N_SUPPORT
+                                       pEntry->NoBADataCountDown = 64;
+#endif // DOT11_N_SUPPORT //
+
+                                       if(pEntry->PsMode == PWR_ACTIVE)
+                                       {
+#ifdef DOT11_N_SUPPORT
+                                               int tid;
+                                               for (tid=0; tid<NUM_OF_TID; tid++)
+                                               {
+                                                       BAOriSessionTearDown(pAd, pEntry->Aid,  tid, FALSE, FALSE);
+                                               }
+#endif // DOT11_N_SUPPORT //
+
+                                               // Update the continuous transmission counter except PS mode
+                                               pEntry->ContinueTxFailCnt++;
+                                       }
+                                       else
+                                       {
+                                               // Clear the FIFOCount when sta in Power Save mode. Basically we assume
+                                               //     this tx error happened due to sta just go to sleep.
+                                               pEntry->FIFOCount = 0;
+                                               pEntry->ContinueTxFailCnt = 0;
+                                       }
+#endif
+                                       //pEntry->FIFOCount = 0;
+                               }
+                               //pEntry->bSendBAR = TRUE;
+                       }
+                       else
+                       {
+#ifdef DOT11_N_SUPPORT
+                               if ((pEntry->PsMode != PWR_SAVE) && (pEntry->NoBADataCountDown > 0))
+                               {
+                                       pEntry->NoBADataCountDown--;
+                                       if (pEntry->NoBADataCountDown==0)
+                                       {
+                                               DBGPRINT(RT_DEBUG_TRACE, ("@\n"));
+                                       }
+                               }
+#endif // DOT11_N_SUPPORT //
+                               pEntry->FIFOCount = 0;
+                               pEntry->OneSecTxNoRetryOkCount++;
+                               // update NoDataIdleCount when sucessful send packet to STA.
+                               pEntry->NoDataIdleCount = 0;
+                               pEntry->ContinueTxFailCnt = 0;
+                       }
+
+                       succMCS = StaFifo.field.SuccessRate & 0x7F;
+
+                       reTry = pid - succMCS;
+
+                       if (StaFifo.field.TxSuccess)
+                       {
+                               pEntry->TXMCSExpected[pid]++;
+                               if (pid == succMCS)
+                               {
+                                       pEntry->TXMCSSuccessful[pid]++;
+                               }
+                               else
+                               {
+                                       pEntry->TXMCSAutoFallBack[pid][succMCS]++;
+                               }
+                       }
+                       else
+                       {
+                               pEntry->TXMCSFailed[pid]++;
+                       }
+
+                       if (reTry > 0)
+                       {
+                               if ((pid >= 12) && succMCS <=7)
+                               {
+                                       reTry -= 4;
+                               }
+                               pEntry->OneSecTxRetryOkCount += reTry;
+                       }
+
+                       i++;
+                       // ASIC store 16 stack
+               } while ( i < (2*TX_RING_SIZE) );
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Read statistical counters from hardware registers and record them
+               in software variables for later on query
+
+       Arguments:
+               pAd                                     Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       ========================================================================
+*/
+VOID NICUpdateRawCounters(
+       IN PRTMP_ADAPTER pAd)
+{
+       UINT32  OldValue;
+       RX_STA_CNT0_STRUC        RxStaCnt0;
+       RX_STA_CNT1_STRUC   RxStaCnt1;
+       RX_STA_CNT2_STRUC   RxStaCnt2;
+       TX_STA_CNT0_STRUC        TxStaCnt0;
+       TX_STA_CNT1_STRUC        StaTx1;
+       TX_STA_CNT2_STRUC        StaTx2;
+       TX_AGG_CNT_STRUC        TxAggCnt;
+       TX_AGG_CNT0_STRUC       TxAggCnt0;
+       TX_AGG_CNT1_STRUC       TxAggCnt1;
+       TX_AGG_CNT2_STRUC       TxAggCnt2;
+       TX_AGG_CNT3_STRUC       TxAggCnt3;
+       TX_AGG_CNT4_STRUC       TxAggCnt4;
+       TX_AGG_CNT5_STRUC       TxAggCnt5;
+       TX_AGG_CNT6_STRUC       TxAggCnt6;
+       TX_AGG_CNT7_STRUC       TxAggCnt7;
+
+
+       RTMP_IO_READ32(pAd, RX_STA_CNT0, &RxStaCnt0.word);
+       RTMP_IO_READ32(pAd, RX_STA_CNT2, &RxStaCnt2.word);
+
+       {
+               RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word);
+           // Update RX PLCP error counter
+           pAd->PrivateInfo.PhyRxErrCnt += RxStaCnt1.field.PlcpErr;
+               // Update False CCA counter
+               pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca;
+       }
+
+       // Update FCS counters
+       OldValue= pAd->WlanCounters.FCSErrorCount.u.LowPart;
+       pAd->WlanCounters.FCSErrorCount.u.LowPart += (RxStaCnt0.field.CrcErr); // >> 7);
+       if (pAd->WlanCounters.FCSErrorCount.u.LowPart < OldValue)
+               pAd->WlanCounters.FCSErrorCount.u.HighPart++;
+
+       // Add FCS error count to private counters
+       pAd->RalinkCounters.OneSecRxFcsErrCnt += RxStaCnt0.field.CrcErr;
+       OldValue = pAd->RalinkCounters.RealFcsErrCount.u.LowPart;
+       pAd->RalinkCounters.RealFcsErrCount.u.LowPart += RxStaCnt0.field.CrcErr;
+       if (pAd->RalinkCounters.RealFcsErrCount.u.LowPart < OldValue)
+               pAd->RalinkCounters.RealFcsErrCount.u.HighPart++;
+
+       // Update Duplicate Rcv check
+       pAd->RalinkCounters.DuplicateRcv += RxStaCnt2.field.RxDupliCount;
+       pAd->WlanCounters.FrameDuplicateCount.u.LowPart += RxStaCnt2.field.RxDupliCount;
+       // Update RX Overflow counter
+       pAd->Counters8023.RxNoBuffer += (RxStaCnt2.field.RxFifoOverflowCount);
+
+       //pAd->RalinkCounters.RxCount = 0;
+#ifdef RT2870
+       if (pAd->RalinkCounters.RxCount != pAd->watchDogRxCnt)
+       {
+               pAd->watchDogRxCnt = pAd->RalinkCounters.RxCount;
+               pAd->watchDogRxOverFlowCnt = 0;
+       }
+       else
+       {
+               if (RxStaCnt2.field.RxFifoOverflowCount)
+                       pAd->watchDogRxOverFlowCnt++;
+               else
+                       pAd->watchDogRxOverFlowCnt = 0;
+       }
+#endif // RT2870 //
+
+
+       //if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) ||
+       //      (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) && (pAd->MacTab.Size != 1)))
+       if (!pAd->bUpdateBcnCntDone)
+       {
+       // Update BEACON sent count
+       RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
+       RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
+       RTMP_IO_READ32(pAd, TX_STA_CNT2, &StaTx2.word);
+       pAd->RalinkCounters.OneSecBeaconSentCnt += TxStaCnt0.field.TxBeaconCount;
+       pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
+       pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
+       pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
+       pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
+       pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
+       pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
+       }
+
+#if 0
+       Retry = StaTx1.field.TxRetransmit;
+       Fail = TxStaCnt0.field.TxFailCount;
+       TxErrorRatio = 0;
+       OneSecTransmitCount = pAd->WlanCounters.TransmittedFragmentCount.u.LowPart- pAd->WlanCounters.LastTransmittedFragmentCount.u.LowPart;
+       if ((OneSecTransmitCount+Retry + Fail) > 0)
+               TxErrorRatio = (( Retry + Fail) *100) / (OneSecTransmitCount+Retry + Fail);
+
+       if ((OneSecTransmitCount+Retry + Fail) > 0)
+               TxErrorRatio = (( Retry + Fail) *100) / (OneSecTransmitCount+Retry + Fail);
+       DBGPRINT(RT_DEBUG_INFO, ("TX ERROR Rate = %ld %%, Retry = %ld, Fail = %ld, Total = %ld  \n",TxErrorRatio, Retry, Fail, (OneSecTransmitCount+Retry + Fail)));
+       pAd->WlanCounters.LastTransmittedFragmentCount.u.LowPart = pAd->WlanCounters.TransmittedFragmentCount.u.LowPart;
+#endif
+
+       //if (pAd->bStaFifoTest == TRUE)
+       {
+               RTMP_IO_READ32(pAd, TX_AGG_CNT, &TxAggCnt.word);
+               RTMP_IO_READ32(pAd, TX_AGG_CNT0, &TxAggCnt0.word);
+               RTMP_IO_READ32(pAd, TX_AGG_CNT1, &TxAggCnt1.word);
+               RTMP_IO_READ32(pAd, TX_AGG_CNT2, &TxAggCnt2.word);
+               RTMP_IO_READ32(pAd, TX_AGG_CNT3, &TxAggCnt3.word);
+               RTMP_IO_READ32(pAd, TX_AGG_CNT4, &TxAggCnt4.word);
+               RTMP_IO_READ32(pAd, TX_AGG_CNT5, &TxAggCnt5.word);
+               RTMP_IO_READ32(pAd, TX_AGG_CNT6, &TxAggCnt6.word);
+               RTMP_IO_READ32(pAd, TX_AGG_CNT7, &TxAggCnt7.word);
+               pAd->RalinkCounters.TxAggCount += TxAggCnt.field.AggTxCount;
+               pAd->RalinkCounters.TxNonAggCount += TxAggCnt.field.NonAggTxCount;
+               pAd->RalinkCounters.TxAgg1MPDUCount += TxAggCnt0.field.AggSize1Count;
+               pAd->RalinkCounters.TxAgg2MPDUCount += TxAggCnt0.field.AggSize2Count;
+
+               pAd->RalinkCounters.TxAgg3MPDUCount += TxAggCnt1.field.AggSize3Count;
+               pAd->RalinkCounters.TxAgg4MPDUCount += TxAggCnt1.field.AggSize4Count;
+               pAd->RalinkCounters.TxAgg5MPDUCount += TxAggCnt2.field.AggSize5Count;
+               pAd->RalinkCounters.TxAgg6MPDUCount += TxAggCnt2.field.AggSize6Count;
+
+               pAd->RalinkCounters.TxAgg7MPDUCount += TxAggCnt3.field.AggSize7Count;
+               pAd->RalinkCounters.TxAgg8MPDUCount += TxAggCnt3.field.AggSize8Count;
+               pAd->RalinkCounters.TxAgg9MPDUCount += TxAggCnt4.field.AggSize9Count;
+               pAd->RalinkCounters.TxAgg10MPDUCount += TxAggCnt4.field.AggSize10Count;
+
+               pAd->RalinkCounters.TxAgg11MPDUCount += TxAggCnt5.field.AggSize11Count;
+               pAd->RalinkCounters.TxAgg12MPDUCount += TxAggCnt5.field.AggSize12Count;
+               pAd->RalinkCounters.TxAgg13MPDUCount += TxAggCnt6.field.AggSize13Count;
+               pAd->RalinkCounters.TxAgg14MPDUCount += TxAggCnt6.field.AggSize14Count;
+
+               pAd->RalinkCounters.TxAgg15MPDUCount += TxAggCnt7.field.AggSize15Count;
+               pAd->RalinkCounters.TxAgg16MPDUCount += TxAggCnt7.field.AggSize16Count;
+
+               // Calculate the transmitted A-MPDU count
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += TxAggCnt0.field.AggSize1Count;
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt0.field.AggSize2Count / 2);
+
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize3Count / 3);
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize4Count / 4);
+
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize5Count / 5);
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize6Count / 6);
+
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize7Count / 7);
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize8Count / 8);
+
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize9Count / 9);
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize10Count / 10);
+
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize11Count / 11);
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize12Count / 12);
+
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize13Count / 13);
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize14Count / 14);
+
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize15Count / 15);
+               pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize16Count / 16);
+       }
+
+#ifdef DBG_DIAGNOSE
+       {
+               RtmpDiagStruct  *pDiag;
+               COUNTER_RALINK  *pRalinkCounters;
+               UCHAR                   ArrayCurIdx, i;
+
+               pDiag = &pAd->DiagStruct;
+               pRalinkCounters = &pAd->RalinkCounters;
+               ArrayCurIdx = pDiag->ArrayCurIdx;
+
+               if (pDiag->inited == 0)
+               {
+                       NdisZeroMemory(pDiag, sizeof(struct _RtmpDiagStrcut_));
+                       pDiag->ArrayStartIdx = pDiag->ArrayCurIdx = 0;
+                       pDiag->inited = 1;
+               }
+               else
+               {
+                       // Tx
+                       pDiag->TxFailCnt[ArrayCurIdx] = TxStaCnt0.field.TxFailCount;
+                       pDiag->TxAggCnt[ArrayCurIdx] = TxAggCnt.field.AggTxCount;
+                       pDiag->TxNonAggCnt[ArrayCurIdx] = TxAggCnt.field.NonAggTxCount;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][0] = TxAggCnt0.field.AggSize1Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][1] = TxAggCnt0.field.AggSize2Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][2] = TxAggCnt1.field.AggSize3Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][3] = TxAggCnt1.field.AggSize4Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][4] = TxAggCnt2.field.AggSize5Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][5] = TxAggCnt2.field.AggSize6Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][6] = TxAggCnt3.field.AggSize7Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][7] = TxAggCnt3.field.AggSize8Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][8] = TxAggCnt4.field.AggSize9Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][9] = TxAggCnt4.field.AggSize10Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][10] = TxAggCnt5.field.AggSize11Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][11] = TxAggCnt5.field.AggSize12Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][12] = TxAggCnt6.field.AggSize13Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][13] = TxAggCnt6.field.AggSize14Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][14] = TxAggCnt7.field.AggSize15Count;
+                       pDiag->TxAMPDUCnt[ArrayCurIdx][15] = TxAggCnt7.field.AggSize16Count;
+
+                       pDiag->RxCrcErrCnt[ArrayCurIdx] = RxStaCnt0.field.CrcErr;
+
+                       INC_RING_INDEX(pDiag->ArrayCurIdx,  DIAGNOSE_TIME);
+                       ArrayCurIdx = pDiag->ArrayCurIdx;
+                       for (i =0; i < 9; i++)
+                       {
+                               pDiag->TxDescCnt[ArrayCurIdx][i]= 0;
+                               pDiag->TxSWQueCnt[ArrayCurIdx][i] =0;
+                               pDiag->TxMcsCnt[ArrayCurIdx][i] = 0;
+                               pDiag->RxMcsCnt[ArrayCurIdx][i] = 0;
+                       }
+                       pDiag->TxDataCnt[ArrayCurIdx] = 0;
+                       pDiag->TxFailCnt[ArrayCurIdx] = 0;
+                       pDiag->RxDataCnt[ArrayCurIdx] = 0;
+                       pDiag->RxCrcErrCnt[ArrayCurIdx]  = 0;
+//                     for (i = 9; i < 16; i++)
+                       for (i = 9; i < 24; i++) // 3*3
+                       {
+                               pDiag->TxDescCnt[ArrayCurIdx][i] = 0;
+                               pDiag->TxMcsCnt[ArrayCurIdx][i] = 0;
+                               pDiag->RxMcsCnt[ArrayCurIdx][i] = 0;
+}
+
+                       if (pDiag->ArrayCurIdx == pDiag->ArrayStartIdx)
+                               INC_RING_INDEX(pDiag->ArrayStartIdx,  DIAGNOSE_TIME);
+               }
+
+       }
+#endif // DBG_DIAGNOSE //
+
+
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Reset NIC from error
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+               Reset NIC from error state
+
+       ========================================================================
+*/
+VOID   NICResetFromError(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       // Reset BBP (according to alex, reset ASIC will force reset BBP
+       // Therefore, skip the reset BBP
+       // RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x2);
+
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
+       // Remove ASIC from reset state
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
+
+       NICInitializeAdapter(pAd, FALSE);
+       NICInitAsicFromEEPROM(pAd);
+
+       // Switch to current channel, since during reset process, the connection should remains on.
+       AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+       AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               erase 8051 firmware image in MAC ASIC
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       IRQL = PASSIVE_LEVEL
+
+       ========================================================================
+*/
+VOID NICEraseFirmware(
+       IN PRTMP_ADAPTER pAd)
+{
+       ULONG i;
+
+       for(i=0; i<MAX_FIRMWARE_IMAGE_SIZE; i+=4)
+               RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, 0);
+
+}/* End of NICEraseFirmware */
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Load 8051 firmware RT2561.BIN file into MAC ASIC
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               NDIS_STATUS_SUCCESS         firmware image load ok
+               NDIS_STATUS_FAILURE         image not found
+
+       IRQL = PASSIVE_LEVEL
+
+       ========================================================================
+*/
+NDIS_STATUS NICLoadFirmware(
+       IN PRTMP_ADAPTER pAd)
+{
+#ifdef BIN_IN_FILE
+#define NICLF_DEFAULT_USE()    \
+       flg_default_firm_use = TRUE; \
+       printk("%s - Use default firmware!\n", __FUNCTION__);
+
+       NDIS_STATUS             Status = NDIS_STATUS_SUCCESS;
+       PUCHAR                  src;
+       struct file             *srcf;
+       INT                     retval, orgfsuid, orgfsgid, i;
+       mm_segment_t    orgfs;
+       PUCHAR                  pFirmwareImage;
+       UINT                    FileLength = 0;
+       UINT32                  MacReg;
+       ULONG                   Index;
+       ULONG                   firm;
+       BOOLEAN                 flg_default_firm_use = FALSE;
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("===> %s\n", __FUNCTION__));
+
+       /* init */
+       pFirmwareImage = NULL;
+       src = RTMP_FIRMWARE_FILE_NAME;
+
+       /* save uid and gid used for filesystem access.
+          set user and group to 0 (root) */
+       orgfsuid = current->fsuid;
+       orgfsgid = current->fsgid;
+       current->fsuid = current->fsgid = 0;
+    orgfs = get_fs();
+    set_fs(KERNEL_DS);
+
+       pAd->FirmwareVersion = (FIRMWARE_MAJOR_VERSION << 8) + \
+                                                  FIRMWARE_MINOR_VERSION;
+
+
+       /* allocate firmware buffer */
+    pFirmwareImage = kmalloc(MAX_FIRMWARE_IMAGE_SIZE, MEM_ALLOC_FLAG);
+    if (pFirmwareImage == NULL)
+       {
+               /* allocate fail, use default firmware array in firmware.h */
+               printk("%s - Allocate memory fail!\n", __FUNCTION__);
+               NICLF_DEFAULT_USE();
+    }
+       else
+       {
+               /* allocate ok! zero the firmware buffer */
+               memset(pFirmwareImage, 0x00, MAX_FIRMWARE_IMAGE_SIZE);
+       } /* End of if */
+
+
+       /* if ok, read firmware file from *.bin file */
+       if (flg_default_firm_use == FALSE)
+       {
+               do
+               {
+                       /* open the bin file */
+                       srcf = filp_open(src, O_RDONLY, 0);
+
+                       if (IS_ERR(srcf))
+                       {
+                               printk("%s - Error %ld opening %s\n",
+                                          __FUNCTION__, -PTR_ERR(srcf), src);
+                               NICLF_DEFAULT_USE();
+                               break;
+                       } /* End of if */
+
+                       /* the object must have a read method */
+                       if ((srcf->f_op == NULL) || (srcf->f_op->read == NULL))
+                       {
+                               printk("%s - %s does not have a write method\n", __FUNCTION__, src);
+                               NICLF_DEFAULT_USE();
+                               break;
+                       } /* End of if */
+
+                       /* read the firmware from the file *.bin */
+                       FileLength = srcf->f_op->read(srcf,
+                                                                                 pFirmwareImage,
+                                                                                 MAX_FIRMWARE_IMAGE_SIZE,
+                                                                                 &srcf->f_pos);
+
+                       if (FileLength != MAX_FIRMWARE_IMAGE_SIZE)
+                       {
+                               printk("%s: error file length (=%d) in RT2860AP.BIN\n",
+                                          __FUNCTION__, FileLength);
+                               NICLF_DEFAULT_USE();
+                               break;
+                       }
+                       else
+                       {
+                               PUCHAR ptr = pFirmwareImage;
+                               USHORT crc = 0xffff;
+
+
+                               /* calculate firmware CRC */
+                               for(i=0; i<(MAX_FIRMWARE_IMAGE_SIZE-2); i++, ptr++)
+                                       crc = ByteCRC16(BitReverse(*ptr), crc);
+                               /* End of for */
+
+                               if ((pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2] != \
+                                                               (UCHAR)BitReverse((UCHAR)(crc>>8))) ||
+                                       (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1] != \
+                                                               (UCHAR)BitReverse((UCHAR)crc)))
+                               {
+                                       /* CRC fail */
+                                       printk("%s: CRC = 0x%02x 0x%02x "
+                                                  "error, should be 0x%02x 0x%02x\n",
+                                                  __FUNCTION__,
+                                                  pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2],
+                                                  pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1],
+                                                  (UCHAR)(crc>>8), (UCHAR)(crc));
+                                       NICLF_DEFAULT_USE();
+                                       break;
+                               }
+                               else
+                               {
+                                       /* firmware is ok */
+                                       pAd->FirmwareVersion = \
+                                               (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4] << 8) +
+                                               pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3];
+
+                                       /* check if firmware version of the file is too old */
+                                       if ((pAd->FirmwareVersion) < \
+                                                                                       ((FIRMWARE_MAJOR_VERSION << 8) +
+                                                                                        FIRMWARE_MINOR_VERSION))
+                                       {
+                                               printk("%s: firmware version too old!\n", __FUNCTION__);
+                                               NICLF_DEFAULT_USE();
+                                               break;
+                                       } /* End of if */
+                               } /* End of if */
+
+                               DBGPRINT(RT_DEBUG_TRACE,
+                                                ("NICLoadFirmware: CRC ok, ver=%d.%d\n",
+                                                 pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4],
+                                                 pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3]));
+                       } /* End of if (FileLength == MAX_FIRMWARE_IMAGE_SIZE) */
+                       break;
+               } while(TRUE);
+
+               /* close firmware file */
+               if (IS_ERR(srcf))
+                       ;
+               else
+               {
+                       retval = filp_close(srcf, NULL);
+                       if (retval)
+                       {
+                               DBGPRINT(RT_DEBUG_ERROR,
+                                                ("--> Error %d closing %s\n", -retval, src));
+                       } /* End of if */
+               } /* End of if */
+       } /* End of if */
+
+
+       /* write firmware to ASIC */
+       if (flg_default_firm_use == TRUE)
+       {
+               /* use default fimeware, free allocated buffer */
+               if (pFirmwareImage != NULL)
+                       kfree(pFirmwareImage);
+               /* End of if */
+
+               /* use default *.bin array */
+               pFirmwareImage = FirmwareImage;
+               FileLength = sizeof(FirmwareImage);
+       } /* End of if */
+
+       /* enable Host program ram write selection */
+       RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x10000);
+
+       for(i=0; i<FileLength; i+=4)
+       {
+               firm = pFirmwareImage[i] +
+                          (pFirmwareImage[i+3] << 24) +
+                          (pFirmwareImage[i+2] << 16) +
+                          (pFirmwareImage[i+1] << 8);
+
+               RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, firm);
+       } /* End of for */
+
+       RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x00000);
+       RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x00001);
+
+       /* initialize BBP R/W access agent */
+       RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0);
+       RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0);
+
+       if (flg_default_firm_use == FALSE)
+       {
+               /* use file firmware, free allocated buffer */
+               if (pFirmwareImage != NULL)
+                       kfree(pFirmwareImage);
+               /* End of if */
+       } /* End of if */
+
+       set_fs(orgfs);
+       current->fsuid = orgfsuid;
+       current->fsgid = orgfsgid;
+#else
+
+       NDIS_STATUS             Status = NDIS_STATUS_SUCCESS;
+       PUCHAR                  pFirmwareImage;
+       ULONG                   FileLength, Index;
+       //ULONG                 firm;
+       UINT32                  MacReg = 0;
+#ifdef RT2870
+       UINT32                  Version = (pAd->MACVersion >> 16);
+#endif // RT2870 //
+
+       pFirmwareImage = FirmwareImage;
+       FileLength = sizeof(FirmwareImage);
+#ifdef RT2870
+       // New 8k byte firmware size for RT3071/RT3072
+       //printk("Usb Chip\n");
+       if (FIRMWAREIMAGE_LENGTH == FIRMWAREIMAGE_MAX_LENGTH)
+       //The firmware image consists of two parts. One is the origianl and the other is the new.
+       //Use Second Part
+       {
+               if ((Version != 0x2860) && (Version != 0x2872) && (Version != 0x3070))
+               {       // Use Firmware V2.
+                       //printk("KH:Use New Version,part2\n");
+                       pFirmwareImage = (PUCHAR)&FirmwareImage[FIRMWAREIMAGEV1_LENGTH];
+                       FileLength = FIRMWAREIMAGEV2_LENGTH;
+               }
+               else
+               {
+                       //printk("KH:Use New Version,part1\n");
+                       pFirmwareImage = FirmwareImage;
+                       FileLength = FIRMWAREIMAGEV1_LENGTH;
+               }
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("KH: bin file should be 8KB.\n"));
+               Status = NDIS_STATUS_FAILURE;
+       }
+
+#endif // RT2870 //
+
+#if 0
+       /* enable Host program ram write selection */
+       RT28XX_FIRMUD_INIT(pAd);
+
+       for(i=0; i<FileLength; i+=4)
+       {
+               firm = pFirmwareImage[i] +
+                          (pFirmwareImage[i+3] << 24) +
+                          (pFirmwareImage[i+2] << 16) +
+                          (pFirmwareImage[i+1] << 8);
+
+               RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, firm);
+       } /* End of for */
+
+       RT28XX_FIRMUD_END(pAd);
+#else
+       RT28XX_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength);
+#endif
+
+#endif
+
+       /* check if MCU is ready */
+       Index = 0;
+       do
+       {
+               RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacReg);
+
+               if (MacReg & 0x80)
+                       break;
+
+               RTMPusecDelay(1000);
+       } while (Index++ < 1000);
+
+    if (Index >= 1000)
+       {
+               Status = NDIS_STATUS_FAILURE;
+               DBGPRINT(RT_DEBUG_ERROR, ("NICLoadFirmware: MCU is not ready\n\n\n"));
+       } /* End of if */
+
+#if 0
+    DBGPRINT(RT_DEBUG_TRACE,
+                        ("<=== %s (src=%s, status=%d)\n", __FUNCTION__, src, Status));
+#else
+    DBGPRINT(RT_DEBUG_TRACE,
+                        ("<=== %s (status=%d)\n", __FUNCTION__, Status));
+#endif
+    return Status;
+} /* End of NICLoadFirmware */
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Load Tx rate switching parameters
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               NDIS_STATUS_SUCCESS         firmware image load ok
+               NDIS_STATUS_FAILURE         image not found
+
+       IRQL = PASSIVE_LEVEL
+
+       Rate Table Format:
+               1. (B0: Valid Item number) (B1:Initial item from zero)
+               2. Item Number(Dec)      Mode(Hex)     Current MCS(Dec)    TrainUp(Dec)    TrainDown(Dec)
+
+       ========================================================================
+*/
+NDIS_STATUS NICLoadRateSwitchingParams(
+       IN PRTMP_ADAPTER pAd)
+{
+#if 0
+       NDIS_STATUS Status;
+
+       NDIS_HANDLE FileHandle;
+       UINT FileLength = 0, i, j;
+       PUCHAR pFirmwareImage;
+       NDIS_STRING FileName;
+       NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
+
+       DBGPRINT(RT_DEBUG_TRACE,("===> NICLoadRateSwitchingParams \n"));
+       pAd->CommonCfg.TxRateTableSize = 0;
+
+       if ((pAd->DeviceID == NIC2860_PCI_DEVICE_ID) || (pAd->DeviceID == NIC2860_PCIe_DEVICE_ID))
+       {
+               NdisInitializeString(&FileName,"rate.bin");
+               DBGPRINT(RT_DEBUG_TRACE, ("NICLoadRateSwitchingParams: load file - rate.bin for tx rate switch \n"));
+       }
+       else
+       {
+               DBGPRINT_ERR(("NICLoadRateSwitchingParams: wrong DeviceID = 0x%04x, can't find Tx rate switch parameters file\n", pAd->DeviceID));
+               return NDIS_STATUS_SUCCESS;
+       }
+       NdisOpenFile(&Status, &FileHandle, &FileLength, &FileName, HighestAcceptableMax);
+       NdisFreeString(FileName);
+
+       if (Status != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("NICLoadRateSwitchingParams: NdisOpenFile() failed, used RateSwitchTable instead\n"));
+               return NDIS_STATUS_SUCCESS;
+       }
+
+       if ((FileLength == 0) || (FileLength > (MAX_STEP_OF_TX_RATE_SWITCH+1)*16))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("NICLoadRateSwitchingParams: file size is not reasonable, used RateSwitchTable instead\n"));
+
+               NdisCloseFile(FileHandle);
+               return NDIS_STATUS_SUCCESS;
+       }
+       else
+       {
+               //
+               // NDIS_STATUS_SUCCESS means
+               // The handle at FileHandle is valid for a subsequent call to NdisMapFile.
+               //
+               NdisMapFile(&Status, &pFirmwareImage, FileHandle);
+               DBGPRINT(RT_DEBUG_TRACE, ("NdisMapFile FileLength=%d\n", FileLength));
+       }
+
+       for (i=0, j=0; i<FileLength; i++)
+       {
+               if ((i%16) <= 4)        // trim reserved field
+               {
+                       if (i%16 == 1)  // deal with DEC and HEX, only row0 is Hex, others are Dec
+                       {
+                               RateSwitchTable[j] = *(pFirmwareImage + i);
+                       }
+                       else
+                       {
+                               RateSwitchTable[j] = (*(pFirmwareImage + i)>>4) * 10 + (*(pFirmwareImage + i) & 0x0F);
+                       }
+
+                       j++;
+               }
+       }
+
+       pAd->CommonCfg.TxRateTableSize = RateSwitchTable[0];            // backup table size
+
+       if (Status == NDIS_STATUS_SUCCESS)
+       {
+               NdisUnmapFile(FileHandle);
+               NdisCloseFile(FileHandle);
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE,("<=== NICLoadRateSwitchingParams(Valid TxRateTable item number=%d)\n", pAd->CommonCfg.TxRateTableSize));
+#endif
+       return NDIS_STATUS_SUCCESS;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               if  pSrc1 all zero with length Length, return 0.
+               If not all zero, return 1
+
+       Arguments:
+               pSrc1
+
+       Return Value:
+               1:                      not all zero
+               0:                      all zero
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+ULONG  RTMPNotAllZero(
+       IN      PVOID   pSrc1,
+       IN      ULONG   Length)
+{
+       PUCHAR  pMem1;
+       ULONG   Index = 0;
+
+       pMem1 = (PUCHAR) pSrc1;
+
+       for (Index = 0; Index < Length; Index++)
+       {
+               if (pMem1[Index] != 0x0)
+               {
+                       break;
+               }
+       }
+
+       if (Index == Length)
+       {
+               return (0);
+       }
+       else
+       {
+               return (1);
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Compare two memory block
+
+       Arguments:
+               pSrc1           Pointer to first memory address
+               pSrc2           Pointer to second memory address
+
+       Return Value:
+               0:                      memory is equal
+               1:                      pSrc1 memory is larger
+               2:                      pSrc2 memory is larger
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+ULONG  RTMPCompareMemory(
+       IN      PVOID   pSrc1,
+       IN      PVOID   pSrc2,
+       IN      ULONG   Length)
+{
+       PUCHAR  pMem1;
+       PUCHAR  pMem2;
+       ULONG   Index = 0;
+
+       pMem1 = (PUCHAR) pSrc1;
+       pMem2 = (PUCHAR) pSrc2;
+
+       for (Index = 0; Index < Length; Index++)
+       {
+               if (pMem1[Index] > pMem2[Index])
+                       return (1);
+               else if (pMem1[Index] < pMem2[Index])
+                       return (2);
+       }
+
+       // Equal
+       return (0);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Zero out memory block
+
+       Arguments:
+               pSrc1           Pointer to memory address
+               Length          Size
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPZeroMemory(
+       IN      PVOID   pSrc,
+       IN      ULONG   Length)
+{
+       PUCHAR  pMem;
+       ULONG   Index = 0;
+
+       pMem = (PUCHAR) pSrc;
+
+       for (Index = 0; Index < Length; Index++)
+       {
+               pMem[Index] = 0x00;
+       }
+}
+
+VOID   RTMPFillMemory(
+       IN      PVOID   pSrc,
+       IN      ULONG   Length,
+       IN      UCHAR   Fill)
+{
+       PUCHAR  pMem;
+       ULONG   Index = 0;
+
+       pMem = (PUCHAR) pSrc;
+
+       for (Index = 0; Index < Length; Index++)
+       {
+               pMem[Index] = Fill;
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Copy data from memory block 1 to memory block 2
+
+       Arguments:
+               pDest           Pointer to destination memory address
+               pSrc            Pointer to source memory address
+               Length          Copy size
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPMoveMemory(
+       OUT     PVOID   pDest,
+       IN      PVOID   pSrc,
+       IN      ULONG   Length)
+{
+       PUCHAR  pMem1;
+       PUCHAR  pMem2;
+       UINT    Index;
+
+       ASSERT((Length==0) || (pDest && pSrc));
+
+       pMem1 = (PUCHAR) pDest;
+       pMem2 = (PUCHAR) pSrc;
+
+       for (Index = 0; Index < Length; Index++)
+       {
+               pMem1[Index] = pMem2[Index];
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Initialize port configuration structure
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   UserCfgInit(
+       IN      PRTMP_ADAPTER pAd)
+{
+//     EDCA_PARM DefaultEdcaParm;
+    UINT key_index, bss_index;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit\n"));
+
+       //
+       //  part I. intialize common configuration
+       //
+#ifdef RT2870
+       pAd->BulkOutReq = 0;
+
+       pAd->BulkOutComplete = 0;
+       pAd->BulkOutCompleteOther = 0;
+       pAd->BulkOutCompleteCancel = 0;
+       pAd->BulkInReq = 0;
+       pAd->BulkInComplete = 0;
+       pAd->BulkInCompleteFail = 0;
+
+       //pAd->QuickTimerP = 100;
+       //pAd->TurnAggrBulkInCount = 0;
+       pAd->bUsbTxBulkAggre = 0;
+
+       // init as unsed value to ensure driver will set to MCU once.
+       pAd->LedIndicatorStregth = 0xFF;
+
+       pAd->CommonCfg.MaxPktOneTxBulk = 2;
+       pAd->CommonCfg.TxBulkFactor = 1;
+       pAd->CommonCfg.RxBulkFactor =1;
+
+       pAd->CommonCfg.TxPower = 100; //mW
+
+       NdisZeroMemory(&pAd->CommonCfg.IOTestParm, sizeof(pAd->CommonCfg.IOTestParm));
+#endif // RT2870 //
+
+       for(key_index=0; key_index<SHARE_KEY_NUM; key_index++)
+       {
+               for(bss_index = 0; bss_index < MAX_MBSSID_NUM; bss_index++)
+               {
+                       pAd->SharedKey[bss_index][key_index].KeyLen = 0;
+                       pAd->SharedKey[bss_index][key_index].CipherAlg = CIPHER_NONE;
+               }
+       }
+
+       pAd->Antenna.word = 0;
+       pAd->CommonCfg.BBPCurrentBW = BW_20;
+
+       pAd->LedCntl.word = 0;
+
+       pAd->bAutoTxAgcA = FALSE;                       // Default is OFF
+       pAd->bAutoTxAgcG = FALSE;                       // Default is OFF
+       pAd->RfIcType = RFIC_2820;
+
+       // Init timer for reset complete event
+       pAd->CommonCfg.CentralChannel = 1;
+       pAd->bForcePrintTX = FALSE;
+       pAd->bForcePrintRX = FALSE;
+       pAd->bStaFifoTest = FALSE;
+       pAd->bProtectionTest = FALSE;
+       pAd->bHCCATest = FALSE;
+       pAd->bGenOneHCCA = FALSE;
+       pAd->CommonCfg.Dsifs = 10;      // in units of usec
+       pAd->CommonCfg.TxPower = 100; //mW
+       pAd->CommonCfg.TxPowerPercentage = 0xffffffff; // AUTO
+       pAd->CommonCfg.TxPowerDefault = 0xffffffff; // AUTO
+       pAd->CommonCfg.TxPreamble = Rt802_11PreambleAuto; // use Long preamble on TX by defaut
+       pAd->CommonCfg.bUseZeroToDisableFragment = FALSE;
+       pAd->CommonCfg.RtsThreshold = 2347;
+       pAd->CommonCfg.FragmentThreshold = 2346;
+       pAd->CommonCfg.UseBGProtection = 0;    // 0: AUTO
+       pAd->CommonCfg.bEnableTxBurst = TRUE; //0;
+       pAd->CommonCfg.PhyMode = 0xff;     // unknown
+       pAd->CommonCfg.BandState = UNKNOWN_BAND;
+       pAd->CommonCfg.RadarDetect.CSPeriod = 10;
+       pAd->CommonCfg.RadarDetect.CSCount = 0;
+       pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE;
+       pAd->CommonCfg.RadarDetect.ChMovingTime = 65;
+       pAd->CommonCfg.RadarDetect.LongPulseRadarTh = 3;
+       pAd->CommonCfg.bAPSDCapable = FALSE;
+       pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
+       pAd->CommonCfg.TriggerTimerCount = 0;
+       pAd->CommonCfg.bAPSDForcePowerSave = FALSE;
+       pAd->CommonCfg.bCountryFlag = FALSE;
+       pAd->CommonCfg.TxStream = 0;
+       pAd->CommonCfg.RxStream = 0;
+
+       NdisZeroMemory(&pAd->BeaconTxWI, sizeof(pAd->BeaconTxWI));
+
+#ifdef DOT11_N_SUPPORT
+       NdisZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability));
+       pAd->HTCEnable = FALSE;
+       pAd->bBroadComHT = FALSE;
+       pAd->CommonCfg.bRdg = FALSE;
+
+#ifdef DOT11N_DRAFT3
+       pAd->CommonCfg.Dot11OBssScanPassiveDwell = dot11OBSSScanPassiveDwell;   // Unit : TU. 5~1000
+       pAd->CommonCfg.Dot11OBssScanActiveDwell = dot11OBSSScanActiveDwell;     // Unit : TU. 10~1000
+       pAd->CommonCfg.Dot11BssWidthTriggerScanInt = dot11BSSWidthTriggerScanInterval;  // Unit : Second
+       pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = dot11OBSSScanPassiveTotalPerChannel;       // Unit : TU. 200~10000
+       pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = dot11OBSSScanActiveTotalPerChannel; // Unit : TU. 20~10000
+       pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = dot11BSSWidthChannelTransactionDelayFactor;
+       pAd->CommonCfg.Dot11OBssScanActivityThre = dot11BSSScanActivityThreshold;       // Unit : percentage
+       pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor);
+#endif  // DOT11N_DRAFT3 //
+
+       NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo));
+       pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE;
+       pAd->CommonCfg.BACapability.field.MpduDensity = 0;
+       pAd->CommonCfg.BACapability.field.Policy = IMMED_BA;
+       pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; //32;
+       pAd->CommonCfg.BACapability.field.TxBAWinLimit = 64; //32;
+       DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit. BACapability = 0x%x\n", pAd->CommonCfg.BACapability.word));
+
+       pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+       BATableInit(pAd, &pAd->BATable);
+
+       pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1;
+       pAd->CommonCfg.bHTProtect = 1;
+       pAd->CommonCfg.bMIMOPSEnable = TRUE;
+       pAd->CommonCfg.bBADecline = FALSE;
+       pAd->CommonCfg.bDisableReordering = FALSE;
+
+       pAd->CommonCfg.TxBASize = 7;
+
+       pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word;
+#endif // DOT11_N_SUPPORT //
+
+       //pAd->CommonCfg.HTPhyMode.field.BW = BW_20;
+       //pAd->CommonCfg.HTPhyMode.field.MCS = MCS_AUTO;
+       //pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_800;
+       //pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE;
+       pAd->CommonCfg.TxRate = RATE_6;
+
+       pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6;
+       pAd->CommonCfg.MlmeTransmit.field.BW = BW_20;
+       pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+
+       pAd->CommonCfg.BeaconPeriod = 100;     // in mSec
+
+       //
+       // part II. intialize STA specific configuration
+       //
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_DIRECT);
+               RX_FILTER_CLEAR_FLAG(pAd, fRX_FILTER_ACCEPT_MULTICAST);
+               RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_BROADCAST);
+               RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_ALL_MULTICAST);
+
+               pAd->StaCfg.Psm = PWR_ACTIVE;
+
+               pAd->StaCfg.OrigWepStatus = Ndis802_11EncryptionDisabled;
+               pAd->StaCfg.PairCipher = Ndis802_11EncryptionDisabled;
+               pAd->StaCfg.GroupCipher = Ndis802_11EncryptionDisabled;
+               pAd->StaCfg.bMixCipher = FALSE;
+               pAd->StaCfg.DefaultKeyId = 0;
+
+               // 802.1x port control
+               pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
+               pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+               pAd->StaCfg.LastMicErrorTime = 0;
+               pAd->StaCfg.MicErrCnt        = 0;
+               pAd->StaCfg.bBlockAssoc      = FALSE;
+               pAd->StaCfg.WpaState         = SS_NOTUSE;
+
+               pAd->CommonCfg.NdisRadioStateOff = FALSE;               // New to support microsoft disable radio with OID command
+
+               pAd->StaCfg.RssiTrigger = 0;
+               NdisZeroMemory(&pAd->StaCfg.RssiSample, sizeof(RSSI_SAMPLE));
+               pAd->StaCfg.RssiTriggerMode = RSSI_TRIGGERED_UPON_BELOW_THRESHOLD;
+               pAd->StaCfg.AtimWin = 0;
+               pAd->StaCfg.DefaultListenCount = 3;//default listen count;
+               pAd->StaCfg.BssType = BSS_INFRA;  // BSS_INFRA or BSS_ADHOC or BSS_MONITOR
+               pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
+
+               pAd->StaCfg.bAutoTxRateSwitch = TRUE;
+               pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+       }
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+       pAd->StaCfg.IEEE80211dClientMode = Rt802_11_D_None;
+#endif // EXT_BUILD_CHANNEL_LIST //
+#endif // CONFIG_STA_SUPPORT //
+
+       // global variables mXXXX used in MAC protocol state machines
+       OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON);
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON);
+
+       // PHY specification
+       pAd->CommonCfg.PhyMode = PHY_11BG_MIXED;                // default PHY mode
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);  // CCK use LONG preamble
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // user desired power mode
+               pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM;
+               pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM;
+               pAd->StaCfg.bWindowsACCAMEnable = FALSE;
+
+#ifdef LEAP_SUPPORT
+               // CCX v1.0 releated init value
+               RTMPInitTimer(pAd, &pAd->StaCfg.LeapAuthTimer, GET_TIMER_FUNCTION(LeapAuthTimeout), pAd, FALSE);
+               pAd->StaCfg.LeapAuthMode = CISCO_AuthModeLEAPNone;
+               pAd->StaCfg.bCkipOn = FALSE;
+#endif // LEAP_SUPPORT //
+
+               RTMPInitTimer(pAd, &pAd->StaCfg.StaQuickResponeForRateUpTimer, GET_TIMER_FUNCTION(StaQuickResponeForRateUpExec), pAd, FALSE);
+               pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
+
+               // Patch for Ndtest
+               pAd->StaCfg.ScanCnt = 0;
+
+               // CCX 2.0 control flag init
+               pAd->StaCfg.CCXEnable = FALSE;
+               pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED;
+               pAd->StaCfg.CCXQosECWMin        = 4;
+               pAd->StaCfg.CCXQosECWMax        = 10;
+
+               pAd->StaCfg.bHwRadio  = TRUE; // Default Hardware Radio status is On
+               pAd->StaCfg.bSwRadio  = TRUE; // Default Software Radio status is On
+               pAd->StaCfg.bRadio    = TRUE; // bHwRadio && bSwRadio
+               pAd->StaCfg.bHardwareRadio = FALSE;             // Default is OFF
+               pAd->StaCfg.bShowHiddenSSID = FALSE;            // Default no show
+
+               // Nitro mode control
+               pAd->StaCfg.bAutoReconnect = TRUE;
+
+               // Save the init time as last scan time, the system should do scan after 2 seconds.
+               // This patch is for driver wake up from standby mode, system will do scan right away.
+               pAd->StaCfg.LastScanTime = 0;
+               NdisZeroMemory(pAd->nickname, IW_ESSID_MAX_SIZE+1);
+               sprintf(pAd->nickname, "%s", STA_NIC_DEVICE_NAME);
+               RTMPInitTimer(pAd, &pAd->StaCfg.WpaDisassocAndBlockAssocTimer, GET_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc), pAd, FALSE);
+#ifdef WPA_SUPPLICANT_SUPPORT
+               pAd->StaCfg.IEEE8021X = FALSE;
+               pAd->StaCfg.IEEE8021x_required_keys = FALSE;
+               pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE;
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+               pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE;
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       // Default for extra information is not valid
+       pAd->ExtraInfo = EXTRA_INFO_CLEAR;
+
+       // Default Config change flag
+       pAd->bConfigChanged = FALSE;
+
+       //
+       // part III. AP configurations
+       //
+
+
+       //
+       // part IV. others
+       //
+       // dynamic BBP R66:sensibity tuning to overcome background noise
+       pAd->BbpTuning.bEnable                = TRUE;
+       pAd->BbpTuning.FalseCcaLowerThreshold = 100;
+       pAd->BbpTuning.FalseCcaUpperThreshold = 512;
+       pAd->BbpTuning.R66Delta               = 4;
+       pAd->Mlme.bEnableAutoAntennaCheck = TRUE;
+
+       //
+       // Also initial R66CurrentValue, RTUSBResumeMsduTransmission might use this value.
+       // if not initial this value, the default value will be 0.
+       //
+       pAd->BbpTuning.R66CurrentValue = 0x38;
+
+       pAd->Bbp94 = BBPR94_DEFAULT;
+       pAd->BbpForCCK = FALSE;
+
+       // Default is FALSE for test bit 1
+       //pAd->bTest1 = FALSE;
+
+       // initialize MAC table and allocate spin lock
+       NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE));
+       InitializeQueueHeader(&pAd->MacTab.McastPsQueue);
+       NdisAllocateSpinLock(&pAd->MacTabLock);
+
+       //RTMPInitTimer(pAd, &pAd->RECBATimer, RECBATimerTimeout, pAd, TRUE);
+       //RTMPSetTimer(&pAd->RECBATimer, REORDER_EXEC_INTV);
+
+#ifdef RALINK_ATE
+       NdisZeroMemory(&pAd->ate, sizeof(ATE_INFO));
+       pAd->ate.Mode = ATE_STOP;
+       pAd->ate.TxCount = 200;/* to exceed TX_RING_SIZE ... */
+       pAd->ate.TxLength = 1024;
+       pAd->ate.TxWI.ShortGI = 0;// LONG GI : 800 ns
+       pAd->ate.TxWI.PHYMODE = MODE_CCK;
+       pAd->ate.TxWI.MCS = 3;
+       pAd->ate.TxWI.BW = BW_20;
+       pAd->ate.Channel = 1;
+       pAd->ate.QID = QID_AC_BE;
+       pAd->ate.Addr1[0] = 0x00;
+       pAd->ate.Addr1[1] = 0x11;
+       pAd->ate.Addr1[2] = 0x22;
+       pAd->ate.Addr1[3] = 0xAA;
+       pAd->ate.Addr1[4] = 0xBB;
+       pAd->ate.Addr1[5] = 0xCC;
+       NdisMoveMemory(pAd->ate.Addr2, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS);
+       NdisMoveMemory(pAd->ate.Addr3, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS);
+       pAd->ate.bRxFer = 0;
+       pAd->ate.bQATxStart = FALSE;
+       pAd->ate.bQARxStart = FALSE;
+#ifdef RALINK_28xx_QA
+       //pAd->ate.Repeat = 0;
+       pAd->ate.TxStatus = 0;
+       pAd->ate.AtePid = THREAD_PID_INIT_VALUE;
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+
+       pAd->CommonCfg.bWiFiTest = FALSE;
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n"));
+}
+
+// IRQL = PASSIVE_LEVEL
+UCHAR BtoH(char ch)
+{
+       if (ch >= '0' && ch <= '9') return (ch - '0');        // Handle numerals
+       if (ch >= 'A' && ch <= 'F') return (ch - 'A' + 0xA);  // Handle capitol hex digits
+       if (ch >= 'a' && ch <= 'f') return (ch - 'a' + 0xA);  // Handle small hex digits
+       return(255);
+}
+
+//
+//  FUNCTION: AtoH(char *, UCHAR *, int)
+//
+//  PURPOSE:  Converts ascii string to network order hex
+//
+//  PARAMETERS:
+//    src    - pointer to input ascii string
+//    dest   - pointer to output hex
+//    destlen - size of dest
+//
+//  COMMENTS:
+//
+//    2 ascii bytes make a hex byte so must put 1st ascii byte of pair
+//    into upper nibble and 2nd ascii byte of pair into lower nibble.
+//
+// IRQL = PASSIVE_LEVEL
+
+void AtoH(char * src, UCHAR * dest, int destlen)
+{
+       char * srcptr;
+       PUCHAR destTemp;
+
+       srcptr = src;
+       destTemp = (PUCHAR) dest;
+
+       while(destlen--)
+       {
+               *destTemp = BtoH(*srcptr++) << 4;    // Put 1st ascii byte in upper nibble.
+               *destTemp += BtoH(*srcptr++);      // Add 2nd ascii byte to above.
+               destTemp++;
+       }
+}
+
+VOID   RTMPPatchMacBbpBug(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       ULONG   Index;
+
+       // Initialize BBP register to default value
+       for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++)
+       {
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, (UCHAR)BBPRegTable[Index].Value);
+       }
+
+       // Initialize RF register to default value
+       AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+       AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+
+       // Re-init BBP register from EEPROM value
+       NICInitAsicFromEEPROM(pAd);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Init timer objects
+
+       Arguments:
+               pAd                     Pointer to our adapter
+               pTimer                          Timer structure
+               pTimerFunc                      Function to execute when timer expired
+               Repeat                          Ture for period timer
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPInitTimer(
+       IN      PRTMP_ADAPTER                   pAd,
+       IN      PRALINK_TIMER_STRUCT    pTimer,
+       IN      PVOID                                   pTimerFunc,
+       IN      PVOID                                   pData,
+       IN      BOOLEAN                                 Repeat)
+{
+       //
+       // Set Valid to TRUE for later used.
+       // It will crash if we cancel a timer or set a timer
+       // that we haven't initialize before.
+       //
+       pTimer->Valid      = TRUE;
+
+       pTimer->PeriodicType = Repeat;
+       pTimer->State      = FALSE;
+       pTimer->cookie = (ULONG) pData;
+
+#ifdef RT2870
+       pTimer->pAd = pAd;
+#endif // RT2870 //
+
+       RTMP_OS_Init_Timer(pAd, &pTimer->TimerObj,      pTimerFunc, (PVOID) pTimer);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Init timer objects
+
+       Arguments:
+               pTimer                          Timer structure
+               Value                           Timer value in milliseconds
+
+       Return Value:
+               None
+
+       Note:
+               To use this routine, must call RTMPInitTimer before.
+
+       ========================================================================
+*/
+VOID   RTMPSetTimer(
+       IN      PRALINK_TIMER_STRUCT    pTimer,
+       IN      ULONG                                   Value)
+{
+       if (pTimer->Valid)
+       {
+               pTimer->TimerValue = Value;
+               pTimer->State      = FALSE;
+               if (pTimer->PeriodicType == TRUE)
+               {
+                       pTimer->Repeat = TRUE;
+                       RTMP_SetPeriodicTimer(&pTimer->TimerObj, Value);
+               }
+               else
+               {
+                       pTimer->Repeat = FALSE;
+                       RTMP_OS_Add_Timer(&pTimer->TimerObj, Value);
+               }
+       }
+       else
+       {
+               DBGPRINT_ERR(("RTMPSetTimer failed, Timer hasn't been initialize!\n"));
+       }
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Init timer objects
+
+       Arguments:
+               pTimer                          Timer structure
+               Value                           Timer value in milliseconds
+
+       Return Value:
+               None
+
+       Note:
+               To use this routine, must call RTMPInitTimer before.
+
+       ========================================================================
+*/
+VOID   RTMPModTimer(
+       IN      PRALINK_TIMER_STRUCT    pTimer,
+       IN      ULONG                                   Value)
+{
+       BOOLEAN Cancel;
+
+       if (pTimer->Valid)
+       {
+               pTimer->TimerValue = Value;
+               pTimer->State      = FALSE;
+               if (pTimer->PeriodicType == TRUE)
+               {
+                       RTMPCancelTimer(pTimer, &Cancel);
+                       RTMPSetTimer(pTimer, Value);
+               }
+               else
+               {
+                       RTMP_OS_Mod_Timer(&pTimer->TimerObj, Value);
+               }
+       }
+       else
+       {
+               DBGPRINT_ERR(("RTMPModTimer failed, Timer hasn't been initialize!\n"));
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Cancel timer objects
+
+       Arguments:
+               Adapter                                         Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+               1.) To use this routine, must call RTMPInitTimer before.
+               2.) Reset NIC to initial state AS IS system boot up time.
+
+       ========================================================================
+*/
+VOID   RTMPCancelTimer(
+       IN      PRALINK_TIMER_STRUCT    pTimer,
+       OUT     BOOLEAN                                 *pCancelled)
+{
+       if (pTimer->Valid)
+       {
+               if (pTimer->State == FALSE)
+                       pTimer->Repeat = FALSE;
+                       RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled);
+
+               if (*pCancelled == TRUE)
+                       pTimer->State = TRUE;
+
+#ifdef RT2870
+               // We need to go-through the TimerQ to findout this timer handler and remove it if
+               //              it's still waiting for execution.
+
+               RT2870_TimerQ_Remove(pTimer->pAd, pTimer);
+#endif // RT2870 //
+       }
+       else
+       {
+               //
+               // NdisMCancelTimer just canced the timer and not mean release the timer.
+               // And don't set the "Valid" to False. So that we can use this timer again.
+               //
+               DBGPRINT_ERR(("RTMPCancelTimer failed, Timer hasn't been initialize!\n"));
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Set LED Status
+
+       Arguments:
+               pAd                                             Pointer to our adapter
+               Status                                  LED Status
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID RTMPSetLED(
+       IN PRTMP_ADAPTER        pAd,
+       IN UCHAR                        Status)
+{
+       //ULONG                 data;
+       UCHAR                   HighByte = 0;
+       UCHAR                   LowByte;
+
+// In ATE mode of RT2860 AP/STA, we have erased 8051 firmware.
+// So LED mode is not supported when ATE is running.
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+       LowByte = pAd->LedCntl.field.LedMode&0x7f;
+       switch (Status)
+       {
+               case LED_LINK_DOWN:
+                       HighByte = 0x20;
+                       AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+                       pAd->LedIndicatorStregth = 0;
+                       break;
+               case LED_LINK_UP:
+                       if (pAd->CommonCfg.Channel > 14)
+                               HighByte = 0xa0;
+                       else
+                               HighByte = 0x60;
+                       AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+                       break;
+               case LED_RADIO_ON:
+                       HighByte = 0x20;
+                       AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+                       break;
+               case LED_HALT:
+                       LowByte = 0; // Driver sets MAC register and MAC controls LED
+               case LED_RADIO_OFF:
+                       HighByte = 0;
+                       AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+                       break;
+        case LED_WPS:
+                       HighByte = 0x10;
+                       AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+                       break;
+               case LED_ON_SITE_SURVEY:
+                       HighByte = 0x08;
+                       AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+                       break;
+               case LED_POWER_UP:
+                       HighByte = 0x04;
+                       AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+                       break;
+               default:
+                       DBGPRINT(RT_DEBUG_WARN, ("RTMPSetLED::Unknown Status %d\n", Status));
+                       break;
+       }
+
+    //
+       // Keep LED status for LED SiteSurvey mode.
+       // After SiteSurvey, we will set the LED mode to previous status.
+       //
+       if ((Status != LED_ON_SITE_SURVEY) && (Status != LED_POWER_UP))
+               pAd->LedStatus = Status;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetLED::Mode=%d,HighByte=0x%02x,LowByte=0x%02x\n", pAd->LedCntl.field.LedMode, HighByte, LowByte));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Set LED Signal Stregth
+
+       Arguments:
+               pAd                                             Pointer to our adapter
+               Dbm                                             Signal Stregth
+
+       Return Value:
+               None
+
+       IRQL = PASSIVE_LEVEL
+
+       Note:
+               Can be run on any IRQL level.
+
+               According to Microsoft Zero Config Wireless Signal Stregth definition as belows.
+               <= -90  No Signal
+               <= -81  Very Low
+               <= -71  Low
+               <= -67  Good
+               <= -57  Very Good
+                > -57  Excellent
+       ========================================================================
+*/
+VOID RTMPSetSignalLED(
+       IN PRTMP_ADAPTER        pAd,
+       IN NDIS_802_11_RSSI Dbm)
+{
+       UCHAR           nLed = 0;
+
+       //
+       // if not Signal Stregth, then do nothing.
+       //
+       if (pAd->LedCntl.field.LedMode != LED_MODE_SIGNAL_STREGTH)
+       {
+               return;
+       }
+
+       if (Dbm <= -90)
+               nLed = 0;
+       else if (Dbm <= -81)
+               nLed = 1;
+       else if (Dbm <= -71)
+               nLed = 3;
+       else if (Dbm <= -67)
+               nLed = 7;
+       else if (Dbm <= -57)
+               nLed = 15;
+       else
+               nLed = 31;
+
+       //
+       // Update Signal Stregth to firmware if changed.
+       //
+       if (pAd->LedIndicatorStregth != nLed)
+       {
+               AsicSendCommandToMcu(pAd, 0x51, 0xff, nLed, pAd->LedCntl.field.Polarity);
+               pAd->LedIndicatorStregth = nLed;
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Enable RX
+
+       Arguments:
+               pAd                                             Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL <= DISPATCH_LEVEL
+
+       Note:
+               Before Enable RX, make sure you have enabled Interrupt.
+       ========================================================================
+*/
+VOID RTMPEnableRxTx(
+       IN PRTMP_ADAPTER        pAd)
+{
+//     WPDMA_GLO_CFG_STRUC     GloCfg;
+//     ULONG   i = 0;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPEnableRxTx\n"));
+
+#if 0
+       // Enable Rx DMA.
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
+       do
+       {
+               RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
+               if ((GloCfg.field.TxDMABusy == 0)  && (GloCfg.field.RxDMABusy == 0))
+                       break;
+
+               DBGPRINT(RT_DEBUG_TRACE, ("==>  DMABusy\n"));
+               RTMPusecDelay(1000);
+               i++;
+       }while ( i <200);
+
+       RTMPusecDelay(50);
+       RT28XX_DMA_WRITE_INIT(GloCfg);
+       DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
+       RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
+
+       RT28XX_DMA_POST_WRITE(pAd);
+#else
+       // Enable Rx DMA.
+       RT28XXDMAEnable(pAd);
+#endif
+
+       // enable RX of MAC block
+       if (pAd->OpMode == OPMODE_AP)
+       {
+               UINT32 rx_filter_flag = APNORMAL;
+
+
+               RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag);     // enable RX of DMA block
+       }
+       else
+       {
+               RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL);     // Staion not drop control frame will fail WiFi Certification.
+       }
+
+       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
+       DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n"));
+}
+
+
diff --git a/drivers/staging/rt2870/common/rtmp_tkip.c b/drivers/staging/rt2870/common/rtmp_tkip.c
new file mode 100644 (file)
index 0000000..2847409
--- /dev/null
@@ -0,0 +1,1613 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       rtmp_tkip.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Paul Wu         02-25-02                Initial
+*/
+
+#include "../rt_config.h"
+
+// Rotation functions on 32 bit values
+#define ROL32( A, n ) \
+       ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) )
+#define ROR32( A, n ) ROL32( (A), 32-(n) )
+
+UINT Tkip_Sbox_Lower[256] =
+{
+       0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54,
+       0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A,
+       0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B,
+       0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B,
+       0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F,
+       0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F,
+       0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5,
+       0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F,
+       0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB,
+       0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97,
+       0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED,
+       0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A,
+       0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94,
+       0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3,
+       0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04,
+       0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D,
+       0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39,
+       0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95,
+       0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83,
+       0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76,
+       0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4,
+       0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B,
+       0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0,
+       0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18,
+       0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51,
+       0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85,
+       0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12,
+       0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9,
+       0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7,
+       0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A,
+       0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8,
+       0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A
+};
+
+UINT Tkip_Sbox_Upper[256] =
+{
+       0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91,
+       0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC,
+       0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB,
+       0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B,
+       0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83,
+       0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A,
+       0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F,
+       0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA,
+       0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B,
+       0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13,
+       0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6,
+       0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85,
+       0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11,
+       0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B,
+       0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1,
+       0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF,
+       0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E,
+       0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6,
+       0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B,
+       0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD,
+       0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8,
+       0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2,
+       0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49,
+       0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10,
+       0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97,
+       0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F,
+       0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C,
+       0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27,
+       0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33,
+       0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5,
+       0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0,
+       0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C
+};
+
+/*****************************/
+/******** SBOX Table *********/
+/*****************************/
+
+UCHAR SboxTable[256] =
+{
+       0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+       0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+       0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+       0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+       0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+       0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+       0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+       0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+       0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+       0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+       0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+       0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+       0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+       0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+       0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+       0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+       0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+       0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+       0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+       0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+       0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+       0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+       0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+       0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+       0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+       0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+       0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+       0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+       0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+       0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+       0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+       0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+
+VOID xor_32(
+       IN  PUCHAR              a,
+       IN  PUCHAR              b,
+       OUT PUCHAR              out);
+
+VOID xor_128(
+       IN  PUCHAR              a,
+       IN  PUCHAR              b,
+       OUT PUCHAR              out);
+
+VOID next_key(
+       IN  PUCHAR              key,
+       IN  INT                 round);
+
+VOID byte_sub(
+       IN  PUCHAR              in,
+       OUT PUCHAR              out);
+
+VOID shift_row(
+       IN  PUCHAR              in,
+       OUT PUCHAR              out);
+
+VOID mix_column(
+       IN  PUCHAR              in,
+       OUT PUCHAR              out);
+
+UCHAR RTMPCkipSbox(
+       IN  UCHAR               a);
+//
+// Expanded IV for TKIP function.
+//
+typedef        struct  PACKED _IV_CONTROL_
+{
+       union PACKED
+       {
+               struct PACKED
+               {
+                       UCHAR           rc0;
+                       UCHAR           rc1;
+                       UCHAR           rc2;
+
+                       union PACKED
+                       {
+                               struct PACKED
+                               {
+#ifdef RT_BIG_ENDIAN
+                                       UCHAR   KeyID:2;
+                                       UCHAR   ExtIV:1;
+                                       UCHAR   Rsvd:5;
+#else
+                                       UCHAR   Rsvd:5;
+                                       UCHAR   ExtIV:1;
+                                       UCHAR   KeyID:2;
+#endif
+                               }       field;
+                               UCHAR           Byte;
+                       }       CONTROL;
+               }       field;
+
+               ULONG   word;
+       }       IV16;
+
+       ULONG   IV32;
+}      TKIP_IV, *PTKIP_IV;
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Convert from UCHAR[] to ULONG in a portable way
+
+       Arguments:
+      pMICKey          pointer to MIC Key
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+ULONG  RTMPTkipGetUInt32(
+       IN      PUCHAR  pMICKey)
+{
+       ULONG   res = 0;
+       INT             i;
+
+       for (i = 0; i < 4; i++)
+       {
+               res |= (*pMICKey++) << (8 * i);
+       }
+
+       return res;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Convert from ULONG to UCHAR[] in a portable way
+
+       Arguments:
+      pDst                     pointer to destination for convert ULONG to UCHAR[]
+      val                      the value for convert
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPTkipPutUInt32(
+       IN OUT  PUCHAR          pDst,
+       IN              ULONG           val)
+{
+       INT i;
+
+       for(i = 0; i < 4; i++)
+       {
+               *pDst++ = (UCHAR) (val & 0xff);
+               val >>= 8;
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Set the MIC Key.
+
+       Arguments:
+      pAd              Pointer to our adapter
+      pMICKey          pointer to MIC Key
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID RTMPTkipSetMICKey(
+       IN      PTKIP_KEY_INFO  pTkip,
+       IN      PUCHAR                  pMICKey)
+{
+       // Set the key
+       pTkip->K0 = RTMPTkipGetUInt32(pMICKey);
+       pTkip->K1 = RTMPTkipGetUInt32(pMICKey + 4);
+       // and reset the message
+       pTkip->L = pTkip->K0;
+       pTkip->R = pTkip->K1;
+       pTkip->nBytesInM = 0;
+       pTkip->M = 0;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Calculate the MIC Value.
+
+       Arguments:
+      pAd              Pointer to our adapter
+      uChar                    Append this uChar
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPTkipAppendByte(
+       IN      PTKIP_KEY_INFO  pTkip,
+       IN      UCHAR                   uChar)
+{
+       // Append the byte to our word-sized buffer
+       pTkip->M |= (uChar << (8* pTkip->nBytesInM));
+       pTkip->nBytesInM++;
+       // Process the word if it is full.
+       if( pTkip->nBytesInM >= 4 )
+       {
+               pTkip->L ^= pTkip->M;
+               pTkip->R ^= ROL32( pTkip->L, 17 );
+               pTkip->L += pTkip->R;
+               pTkip->R ^= ((pTkip->L & 0xff00ff00) >> 8) | ((pTkip->L & 0x00ff00ff) << 8);
+               pTkip->L += pTkip->R;
+               pTkip->R ^= ROL32( pTkip->L, 3 );
+               pTkip->L += pTkip->R;
+               pTkip->R ^= ROR32( pTkip->L, 2 );
+               pTkip->L += pTkip->R;
+               // Clear the buffer
+               pTkip->M = 0;
+               pTkip->nBytesInM = 0;
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Calculate the MIC Value.
+
+       Arguments:
+      pAd              Pointer to our adapter
+      pSrc                     Pointer to source data for Calculate MIC Value
+      Len                      Indicate the length of the source data
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPTkipAppend(
+       IN      PTKIP_KEY_INFO  pTkip,
+       IN      PUCHAR                  pSrc,
+       IN      UINT                    nBytes)
+{
+       // This is simple
+       while(nBytes > 0)
+       {
+               RTMPTkipAppendByte(pTkip, *pSrc++);
+               nBytes--;
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Get the MIC Value.
+
+       Arguments:
+      pAd              Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+               the MIC Value is store in pAd->PrivateInfo.MIC
+       ========================================================================
+*/
+VOID   RTMPTkipGetMIC(
+       IN      PTKIP_KEY_INFO  pTkip)
+{
+       // Append the minimum padding
+       RTMPTkipAppendByte(pTkip, 0x5a );
+       RTMPTkipAppendByte(pTkip, 0 );
+       RTMPTkipAppendByte(pTkip, 0 );
+       RTMPTkipAppendByte(pTkip, 0 );
+       RTMPTkipAppendByte(pTkip, 0 );
+       // and then zeroes until the length is a multiple of 4
+       while( pTkip->nBytesInM != 0 )
+       {
+               RTMPTkipAppendByte(pTkip, 0 );
+       }
+       // The appendByte function has already computed the result.
+       RTMPTkipPutUInt32(pTkip->MIC, pTkip->L);
+       RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Init Tkip function.
+
+       Arguments:
+      pAd              Pointer to our adapter
+               pTKey       Pointer to the Temporal Key (TK), TK shall be 128bits.
+               KeyId           TK Key ID
+               pTA                     Pointer to transmitter address
+               pMICKey         pointer to MIC Key
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPInitTkipEngine(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pKey,
+       IN      UCHAR                   KeyId,
+       IN      PUCHAR                  pTA,
+       IN      PUCHAR                  pMICKey,
+       IN      PUCHAR                  pTSC,
+       OUT     PULONG                  pIV16,
+       OUT     PULONG                  pIV32)
+{
+       TKIP_IV tkipIv;
+
+       // Prepare 8 bytes TKIP encapsulation for MPDU
+       NdisZeroMemory(&tkipIv, sizeof(TKIP_IV));
+       tkipIv.IV16.field.rc0 = *(pTSC + 1);
+       tkipIv.IV16.field.rc1 = (tkipIv.IV16.field.rc0 | 0x20) & 0x7f;
+       tkipIv.IV16.field.rc2 = *pTSC;
+       tkipIv.IV16.field.CONTROL.field.ExtIV = 1;  // 0: non-extended IV, 1: an extended IV
+       tkipIv.IV16.field.CONTROL.field.KeyID = KeyId;
+//     tkipIv.IV32 = *(PULONG)(pTSC + 2);
+       NdisMoveMemory(&tkipIv.IV32, (pTSC + 2), 4);   // Copy IV
+
+       *pIV16 = tkipIv.IV16.word;
+       *pIV32 = tkipIv.IV32;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Init MIC Value calculation function which include set MIC key &
+               calculate first 16 bytes (DA + SA + priority +  0)
+
+       Arguments:
+      pAd              Pointer to our adapter
+               pTKey       Pointer to the Temporal Key (TK), TK shall be 128bits.
+               pDA                     Pointer to DA address
+               pSA                     Pointer to SA address
+               pMICKey         pointer to MIC Key
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPInitMICEngine(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pKey,
+       IN      PUCHAR                  pDA,
+       IN      PUCHAR                  pSA,
+       IN  UCHAR           UserPriority,
+       IN      PUCHAR                  pMICKey)
+{
+       ULONG Priority = UserPriority;
+
+       // Init MIC value calculation
+       RTMPTkipSetMICKey(&pAd->PrivateInfo.Tx, pMICKey);
+       // DA
+       RTMPTkipAppend(&pAd->PrivateInfo.Tx, pDA, MAC_ADDR_LEN);
+       // SA
+       RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSA, MAC_ADDR_LEN);
+       // Priority + 3 bytes of 0
+       RTMPTkipAppend(&pAd->PrivateInfo.Tx, (PUCHAR)&Priority, 4);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Compare MIC value of received MSDU
+
+       Arguments:
+               pAd     Pointer to our adapter
+               pSrc        Pointer to the received Plain text data
+               pDA                     Pointer to DA address
+               pSA                     Pointer to SA address
+               pMICKey         pointer to MIC Key
+               Len         the length of the received plain text data exclude MIC value
+
+       Return Value:
+               TRUE        MIC value matched
+               FALSE       MIC value mismatched
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+BOOLEAN        RTMPTkipCompareMICValue(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pSrc,
+       IN      PUCHAR                  pDA,
+       IN      PUCHAR                  pSA,
+       IN      PUCHAR                  pMICKey,
+       IN      UCHAR                   UserPriority,
+       IN      UINT                    Len)
+{
+       UCHAR   OldMic[8];
+       ULONG   Priority = UserPriority;
+
+       // Init MIC value calculation
+       RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey);
+       // DA
+       RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN);
+       // SA
+       RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN);
+       // Priority + 3 bytes of 0
+       RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4);
+
+       // Calculate MIC value from plain text data
+       RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len);
+
+       // Get MIC valude from received frame
+       NdisMoveMemory(OldMic, pSrc + Len, 8);
+
+       // Get MIC value from decrypted plain data
+       RTMPTkipGetMIC(&pAd->PrivateInfo.Rx);
+
+       // Move MIC value from MSDU, this steps should move to data path.
+       // Since the MIC value might cross MPDUs.
+       if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8))
+       {
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValue(): TKIP MIC Error !\n"));  //MIC error.
+
+
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Compare MIC value of received MSDU
+
+       Arguments:
+               pAd     Pointer to our adapter
+               pLLC            LLC header
+               pSrc        Pointer to the received Plain text data
+               pDA                     Pointer to DA address
+               pSA                     Pointer to SA address
+               pMICKey         pointer to MIC Key
+               Len         the length of the received plain text data exclude MIC value
+
+       Return Value:
+               TRUE        MIC value matched
+               FALSE       MIC value mismatched
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+BOOLEAN        RTMPTkipCompareMICValueWithLLC(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pLLC,
+       IN      PUCHAR                  pSrc,
+       IN      PUCHAR                  pDA,
+       IN      PUCHAR                  pSA,
+       IN      PUCHAR                  pMICKey,
+       IN      UINT                    Len)
+{
+       UCHAR   OldMic[8];
+       ULONG   Priority = 0;
+
+       // Init MIC value calculation
+       RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey);
+       // DA
+       RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN);
+       // SA
+       RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN);
+       // Priority + 3 bytes of 0
+       RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4);
+
+       // Start with LLC header
+       RTMPTkipAppend(&pAd->PrivateInfo.Rx, pLLC, 8);
+
+       // Calculate MIC value from plain text data
+       RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len);
+
+       // Get MIC valude from received frame
+       NdisMoveMemory(OldMic, pSrc + Len, 8);
+
+       // Get MIC value from decrypted plain data
+       RTMPTkipGetMIC(&pAd->PrivateInfo.Rx);
+
+       // Move MIC value from MSDU, this steps should move to data path.
+       // Since the MIC value might cross MPDUs.
+       if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8))
+       {
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValueWithLLC(): TKIP MIC Error !\n"));  //MIC error.
+
+
+               return (FALSE);
+       }
+       return (TRUE);
+}
+/*
+       ========================================================================
+
+       Routine Description:
+               Copy frame from waiting queue into relative ring buffer and set
+       appropriate ASIC register to kick hardware transmit function
+
+       Arguments:
+               pAd             Pointer to our adapter
+               PNDIS_PACKET    Pointer to Ndis Packet for MIC calculation
+               pEncap                  Pointer to LLC encap data
+               LenEncap                Total encap length, might be 0 which indicates no encap
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPCalculateMICValue(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      PUCHAR                  pEncap,
+       IN      PCIPHER_KEY             pKey,
+       IN      UCHAR                   apidx)
+{
+       PACKET_INFO             PacketInfo;
+       PUCHAR                  pSrcBufVA;
+       UINT                    SrcBufLen;
+       PUCHAR                  pSrc;
+    UCHAR           UserPriority;
+       UCHAR                   vlan_offset = 0;
+
+       RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+
+       UserPriority = RTMP_GET_PACKET_UP(pPacket);
+       pSrc = pSrcBufVA;
+
+       // determine if this is a vlan packet
+       if (((*(pSrc + 12) << 8) + *(pSrc + 13)) == 0x8100)
+               vlan_offset = 4;
+
+#ifdef CONFIG_STA_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+       {
+               RTMPInitMICEngine(
+                       pAd,
+                       pKey->Key,
+                       pSrc,
+                       pSrc + 6,
+                       UserPriority,
+                       pKey->TxMic);
+       }
+
+
+       if (pEncap != NULL)
+       {
+               // LLC encapsulation
+               RTMPTkipAppend(&pAd->PrivateInfo.Tx, pEncap, 6);
+               // Protocol Type
+               RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc + 12 + vlan_offset, 2);
+       }
+       SrcBufLen -= (14 + vlan_offset);
+       pSrc += (14 + vlan_offset);
+       do
+       {
+               if (SrcBufLen > 0)
+               {
+                       RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc, SrcBufLen);
+               }
+
+               break;  // No need handle next packet
+
+       }       while (TRUE);           // End of copying payload
+
+       // Compute the final MIC Value
+       RTMPTkipGetMIC(&pAd->PrivateInfo.Tx);
+}
+
+
+/************************************************************/
+/* tkip_sbox()                                                                                                                         */
+/* Returns a 16 bit value from a 64K entry table. The Table */
+/* is synthesized from two 256 entry byte wide tables.         */
+/************************************************************/
+
+UINT tkip_sbox(UINT index)
+{
+       UINT index_low;
+       UINT index_high;
+       UINT left, right;
+
+       index_low = (index % 256);
+       index_high = ((index >> 8) % 256);
+
+       left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] * 256);
+       right = Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] * 256);
+
+       return (left ^ right);
+}
+
+UINT rotr1(UINT a)
+{
+       unsigned int b;
+
+       if ((a & 0x01) == 0x01)
+       {
+               b = (a >> 1) | 0x8000;
+       }
+       else
+       {
+               b = (a >> 1) & 0x7fff;
+       }
+       b = b % 65536;
+       return b;
+}
+
+VOID RTMPTkipMixKey(
+       UCHAR *key,
+       UCHAR *ta,
+       ULONG pnl, /* Least significant 16 bits of PN */
+       ULONG pnh, /* Most significant 32 bits of PN */
+       UCHAR *rc4key,
+       UINT *p1k)
+{
+
+       UINT tsc0;
+       UINT tsc1;
+       UINT tsc2;
+
+       UINT ppk0;
+       UINT ppk1;
+       UINT ppk2;
+       UINT ppk3;
+       UINT ppk4;
+       UINT ppk5;
+
+       INT i;
+       INT j;
+
+       tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */
+       tsc1 = (unsigned int)(pnh % 65536);
+       tsc2 = (unsigned int)(pnl % 65536); /* lsb */
+
+       /* Phase 1, step 1 */
+       p1k[0] = tsc1;
+       p1k[1] = tsc0;
+       p1k[2] = (UINT)(ta[0] + (ta[1]*256));
+       p1k[3] = (UINT)(ta[2] + (ta[3]*256));
+       p1k[4] = (UINT)(ta[4] + (ta[5]*256));
+
+       /* Phase 1, step 2 */
+       for (i=0; i<8; i++)
+       {
+               j = 2*(i & 1);
+               p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*key[1+j]) + key[j])) % 65536 )) % 65536;
+               p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*key[5+j]) + key[4+j])) % 65536 )) % 65536;
+               p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*key[9+j]) + key[8+j])) % 65536 )) % 65536;
+               p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*key[13+j]) + key[12+j])) % 65536 )) % 65536;
+               p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*key[1+j]) + key[j]))) % 65536 )) % 65536;
+               p1k[4] = (p1k[4] + i) % 65536;
+       }
+
+       /* Phase 2, Step 1 */
+       ppk0 = p1k[0];
+       ppk1 = p1k[1];
+       ppk2 = p1k[2];
+       ppk3 = p1k[3];
+       ppk4 = p1k[4];
+       ppk5 = (p1k[4] + tsc2) % 65536;
+
+       /* Phase2, Step 2 */
+       ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*key[1]) + key[0])) % 65536);
+       ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*key[3]) + key[2])) % 65536);
+       ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*key[5]) + key[4])) % 65536);
+       ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*key[7]) + key[6])) % 65536);
+       ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*key[9]) + key[8])) % 65536);
+       ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*key[11]) + key[10])) % 65536);
+
+       ppk0 = ppk0 + rotr1(ppk5 ^ ((256*key[13]) + key[12]));
+       ppk1 = ppk1 + rotr1(ppk0 ^ ((256*key[15]) + key[14]));
+       ppk2 = ppk2 + rotr1(ppk1);
+       ppk3 = ppk3 + rotr1(ppk2);
+       ppk4 = ppk4 + rotr1(ppk3);
+       ppk5 = ppk5 + rotr1(ppk4);
+
+       /* Phase 2, Step 3 */
+    /* Phase 2, Step 3 */
+
+       tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */
+       tsc1 = (unsigned int)(pnh % 65536);
+       tsc2 = (unsigned int)(pnl % 65536); /* lsb */
+
+       rc4key[0] = (tsc2 >> 8) % 256;
+       rc4key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f;
+       rc4key[2] = tsc2 % 256;
+       rc4key[3] = ((ppk5 ^ ((256*key[1]) + key[0])) >> 1) % 256;
+
+       rc4key[4] = ppk0 % 256;
+       rc4key[5] = (ppk0 >> 8) % 256;
+
+       rc4key[6] = ppk1 % 256;
+       rc4key[7] = (ppk1 >> 8) % 256;
+
+       rc4key[8] = ppk2 % 256;
+       rc4key[9] = (ppk2 >> 8) % 256;
+
+       rc4key[10] = ppk3 % 256;
+       rc4key[11] = (ppk3 >> 8) % 256;
+
+       rc4key[12] = ppk4 % 256;
+       rc4key[13] = (ppk4 >> 8) % 256;
+
+       rc4key[14] = ppk5 % 256;
+       rc4key[15] = (ppk5 >> 8) % 256;
+}
+
+
+/************************************************/
+/* construct_mic_header1()                      */
+/* Builds the first MIC header block from       */
+/* header fields.                               */
+/************************************************/
+
+void construct_mic_header1(
+       unsigned char *mic_header1,
+       int header_length,
+       unsigned char *mpdu)
+{
+       mic_header1[0] = (unsigned char)((header_length - 2) / 256);
+       mic_header1[1] = (unsigned char)((header_length - 2) % 256);
+       mic_header1[2] = mpdu[0] & 0xcf;    /* Mute CF poll & CF ack bits */
+       mic_header1[3] = mpdu[1] & 0xc7;    /* Mute retry, more data and pwr mgt bits */
+       mic_header1[4] = mpdu[4];       /* A1 */
+       mic_header1[5] = mpdu[5];
+       mic_header1[6] = mpdu[6];
+       mic_header1[7] = mpdu[7];
+       mic_header1[8] = mpdu[8];
+       mic_header1[9] = mpdu[9];
+       mic_header1[10] = mpdu[10];     /* A2 */
+       mic_header1[11] = mpdu[11];
+       mic_header1[12] = mpdu[12];
+       mic_header1[13] = mpdu[13];
+       mic_header1[14] = mpdu[14];
+       mic_header1[15] = mpdu[15];
+}
+
+/************************************************/
+/* construct_mic_header2()                      */
+/* Builds the last MIC header block from        */
+/* header fields.                               */
+/************************************************/
+
+void construct_mic_header2(
+       unsigned char *mic_header2,
+       unsigned char *mpdu,
+       int a4_exists,
+       int qc_exists)
+{
+       int i;
+
+       for (i = 0; i<16; i++) mic_header2[i]=0x00;
+
+       mic_header2[0] = mpdu[16];    /* A3 */
+       mic_header2[1] = mpdu[17];
+       mic_header2[2] = mpdu[18];
+       mic_header2[3] = mpdu[19];
+       mic_header2[4] = mpdu[20];
+       mic_header2[5] = mpdu[21];
+
+       // In Sequence Control field, mute sequence numer bits (12-bit)
+       mic_header2[6] = mpdu[22] & 0x0f;   /* SC */
+       mic_header2[7] = 0x00; /* mpdu[23]; */
+
+       if ((!qc_exists) & a4_exists)
+       {
+               for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i];   /* A4 */
+
+       }
+
+       if (qc_exists && (!a4_exists))
+       {
+               mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
+               mic_header2[9] = mpdu[25] & 0x00;
+       }
+
+       if (qc_exists && a4_exists)
+       {
+               for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i];   /* A4 */
+
+               mic_header2[14] = mpdu[30] & 0x0f;
+               mic_header2[15] = mpdu[31] & 0x00;
+       }
+}
+
+
+/************************************************/
+/* construct_mic_iv()                           */
+/* Builds the MIC IV from header fields and PN  */
+/************************************************/
+
+void construct_mic_iv(
+       unsigned char *mic_iv,
+       int qc_exists,
+       int a4_exists,
+       unsigned char *mpdu,
+       unsigned int payload_length,
+       unsigned char *pn_vector)
+{
+       int i;
+
+       mic_iv[0] = 0x59;
+       if (qc_exists && a4_exists)
+               mic_iv[1] = mpdu[30] & 0x0f;    /* QoS_TC           */
+       if (qc_exists && !a4_exists)
+               mic_iv[1] = mpdu[24] & 0x0f;   /* mute bits 7-4    */
+       if (!qc_exists)
+               mic_iv[1] = 0x00;
+       for (i = 2; i < 8; i++)
+               mic_iv[i] = mpdu[i + 8];                    /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
+#ifdef CONSISTENT_PN_ORDER
+               for (i = 8; i < 14; i++)
+                       mic_iv[i] = pn_vector[i - 8];           /* mic_iv[8:13] = PN[0:5] */
+#else
+               for (i = 8; i < 14; i++)
+                       mic_iv[i] = pn_vector[13 - i];          /* mic_iv[8:13] = PN[5:0] */
+#endif
+       i = (payload_length / 256);
+       i = (payload_length % 256);
+       mic_iv[14] = (unsigned char) (payload_length / 256);
+       mic_iv[15] = (unsigned char) (payload_length % 256);
+
+}
+
+
+
+/************************************/
+/* bitwise_xor()                    */
+/* A 128 bit, bitwise exclusive or  */
+/************************************/
+
+void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out)
+{
+       int i;
+       for (i=0; i<16; i++)
+       {
+               out[i] = ina[i] ^ inb[i];
+       }
+}
+
+
+void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphertext)
+{
+       int round;
+       int i;
+       unsigned char intermediatea[16];
+       unsigned char intermediateb[16];
+       unsigned char round_key[16];
+
+       for(i=0; i<16; i++) round_key[i] = key[i];
+
+       for (round = 0; round < 11; round++)
+       {
+               if (round == 0)
+               {
+                       xor_128(round_key, data, ciphertext);
+                       next_key(round_key, round);
+               }
+               else if (round == 10)
+               {
+                       byte_sub(ciphertext, intermediatea);
+                       shift_row(intermediatea, intermediateb);
+                       xor_128(intermediateb, round_key, ciphertext);
+               }
+               else    /* 1 - 9 */
+               {
+                       byte_sub(ciphertext, intermediatea);
+                       shift_row(intermediatea, intermediateb);
+                       mix_column(&intermediateb[0], &intermediatea[0]);
+                       mix_column(&intermediateb[4], &intermediatea[4]);
+                       mix_column(&intermediateb[8], &intermediatea[8]);
+                       mix_column(&intermediateb[12], &intermediatea[12]);
+                       xor_128(intermediatea, round_key, ciphertext);
+                       next_key(round_key, round);
+               }
+       }
+
+}
+
+void construct_ctr_preload(
+       unsigned char *ctr_preload,
+       int a4_exists,
+       int qc_exists,
+       unsigned char *mpdu,
+       unsigned char *pn_vector,
+       int c)
+{
+
+       int i = 0;
+       for (i=0; i<16; i++) ctr_preload[i] = 0x00;
+       i = 0;
+
+       ctr_preload[0] = 0x01;                                  /* flag */
+       if (qc_exists && a4_exists) ctr_preload[1] = mpdu[30] & 0x0f;   /* QoC_Control  */
+       if (qc_exists && !a4_exists) ctr_preload[1] = mpdu[24] & 0x0f;
+
+       for (i = 2; i < 8; i++)
+               ctr_preload[i] = mpdu[i + 8];                       /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
+#ifdef CONSISTENT_PN_ORDER
+         for (i = 8; i < 14; i++)
+                       ctr_preload[i] =    pn_vector[i - 8];           /* ctr_preload[8:13] = PN[0:5] */
+#else
+         for (i = 8; i < 14; i++)
+                       ctr_preload[i] =    pn_vector[13 - i];          /* ctr_preload[8:13] = PN[5:0] */
+#endif
+       ctr_preload[14] =  (unsigned char) (c / 256); // Ctr
+       ctr_preload[15] =  (unsigned char) (c % 256);
+
+}
+
+
+//
+// TRUE: Success!
+// FALSE: Decrypt Error!
+//
+BOOLEAN RTMPSoftDecryptTKIP(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR       pData,
+       IN ULONG        DataByteCnt,
+       IN UCHAR    UserPriority,
+       IN PCIPHER_KEY  pWpaKey)
+{
+       UCHAR                   KeyID;
+       UINT                    HeaderLen;
+    UCHAR                      fc0;
+       UCHAR                   fc1;
+       USHORT                  fc;
+       UINT                    frame_type;
+       UINT                    frame_subtype;
+    UINT                       from_ds;
+    UINT                       to_ds;
+       INT                             a4_exists;
+       INT                             qc_exists;
+       USHORT                  duration;
+       USHORT                  seq_control;
+       USHORT                  qos_control;
+       UCHAR                   TA[MAC_ADDR_LEN];
+       UCHAR                   DA[MAC_ADDR_LEN];
+       UCHAR                   SA[MAC_ADDR_LEN];
+       UCHAR                   RC4Key[16];
+       UINT                    p1k[5]; //for mix_key;
+       ULONG                   pnl;/* Least significant 16 bits of PN */
+       ULONG                   pnh;/* Most significant 32 bits of PN */
+       UINT                    num_blocks;
+       UINT                    payload_remainder;
+       ARCFOURCONTEXT  ArcFourContext;
+       UINT                    crc32 = 0;
+       UINT                    trailfcs = 0;
+       UCHAR                   MIC[8];
+       UCHAR                   TrailMIC[8];
+
+#ifdef RT_BIG_ENDIAN
+       RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE);
+#endif
+
+       fc0 = *pData;
+       fc1 = *(pData + 1);
+
+       fc = *((PUSHORT)pData);
+
+       frame_type = ((fc0 >> 2) & 0x03);
+       frame_subtype = ((fc0 >> 4) & 0x0f);
+
+    from_ds = (fc1 & 0x2) >> 1;
+    to_ds = (fc1 & 0x1);
+
+    a4_exists = (from_ds & to_ds);
+    qc_exists = ((frame_subtype == 0x08) ||    /* Assumed QoS subtypes */
+                  (frame_subtype == 0x09) ||   /* Likely to change.    */
+                  (frame_subtype == 0x0a) ||
+                  (frame_subtype == 0x0b)
+                 );
+
+       HeaderLen = 24;
+       if (a4_exists)
+               HeaderLen += 6;
+
+       KeyID = *((PUCHAR)(pData+ HeaderLen + 3));
+       KeyID = KeyID >> 6;
+
+       if (pWpaKey[KeyID].KeyLen == 0)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP failed!(KeyID[%d] Length can not be 0)\n", KeyID));
+               return FALSE;
+       }
+
+       duration = *((PUSHORT)(pData+2));
+
+       seq_control = *((PUSHORT)(pData+22));
+
+       if (qc_exists)
+       {
+               if (a4_exists)
+               {
+                       qos_control = *((PUSHORT)(pData+30));
+               }
+               else
+               {
+                       qos_control = *((PUSHORT)(pData+24));
+               }
+       }
+
+       if (to_ds == 0 && from_ds == 1)
+       {
+               NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN);
+               NdisMoveMemory(SA, pData+16, MAC_ADDR_LEN);
+               NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN);  //BSSID
+       }
+       else if (to_ds == 0 && from_ds == 0 )
+       {
+               NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN);
+               NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN);
+               NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN);
+       }
+       else if (to_ds == 1 && from_ds == 0)
+       {
+               NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN);
+               NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN);
+               NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN);
+       }
+       else if (to_ds == 1 && from_ds == 1)
+       {
+               NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN);
+               NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN);
+               NdisMoveMemory(SA, pData+22, MAC_ADDR_LEN);
+       }
+
+       num_blocks = (DataByteCnt - 16) / 16;
+       payload_remainder = (DataByteCnt - 16) % 16;
+
+       pnl = (*(pData + HeaderLen)) * 256 + *(pData + HeaderLen + 2);
+       pnh = *((PULONG)(pData + HeaderLen + 4));
+       pnh = cpu2le32(pnh);
+       RTMPTkipMixKey(pWpaKey[KeyID].Key, TA, pnl, pnh, RC4Key, p1k);
+
+       ARCFOUR_INIT(&ArcFourContext, RC4Key, 16);
+
+       ARCFOUR_DECRYPT(&ArcFourContext, pData + HeaderLen, pData + HeaderLen + 8, DataByteCnt - HeaderLen - 8);
+       NdisMoveMemory(&trailfcs, pData + DataByteCnt - 8 - 4, 4);
+       crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 4);  //Skip IV+EIV 8 bytes & Skip last 4 bytes(FCS).
+       crc32 ^= 0xffffffff;             /* complement */
+
+    if(crc32 != cpu2le32(trailfcs))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP, WEP Data ICV Error !\n"));       //ICV error.
+
+               return (FALSE);
+       }
+
+       NdisMoveMemory(TrailMIC, pData + DataByteCnt - 8 - 8 - 4, 8);
+       RTMPInitMICEngine(pAd, pWpaKey[KeyID].Key, DA, SA, UserPriority, pWpaKey[KeyID].RxMic);
+       RTMPTkipAppend(&pAd->PrivateInfo.Tx, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 12);
+       RTMPTkipGetMIC(&pAd->PrivateInfo.Tx);
+       NdisMoveMemory(MIC, pAd->PrivateInfo.Tx.MIC, 8);
+
+       if (!NdisEqualMemory(MIC, TrailMIC, 8))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptTKIP, WEP Data MIC Error !\n"));       //MIC error.
+               //RTMPReportMicError(pAd, &pWpaKey[KeyID]);     // marked by AlbertY @ 20060630
+               return (FALSE);
+       }
+
+#ifdef RT_BIG_ENDIAN
+       RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE);
+#endif
+       //DBGPRINT(RT_DEBUG_TRACE, "RTMPSoftDecryptTKIP Decript done!!\n");
+       return TRUE;
+}
+
+
+
+
+BOOLEAN RTMPSoftDecryptAES(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR       pData,
+       IN ULONG        DataByteCnt,
+       IN PCIPHER_KEY  pWpaKey)
+{
+       UCHAR                   KeyID;
+       UINT                    HeaderLen;
+       UCHAR                   PN[6];
+       UINT                    payload_len;
+       UINT                    num_blocks;
+       UINT                    payload_remainder;
+       USHORT                  fc;
+       UCHAR                   fc0;
+       UCHAR                   fc1;
+       UINT                    frame_type;
+       UINT                    frame_subtype;
+       UINT                    from_ds;
+       UINT                    to_ds;
+       INT                             a4_exists;
+       INT                             qc_exists;
+       UCHAR                   aes_out[16];
+       int                     payload_index;
+       UINT                    i;
+       UCHAR                   ctr_preload[16];
+       UCHAR                   chain_buffer[16];
+       UCHAR                   padded_buffer[16];
+       UCHAR                   mic_iv[16];
+       UCHAR                   mic_header1[16];
+       UCHAR                   mic_header2[16];
+       UCHAR                   MIC[8];
+       UCHAR                   TrailMIC[8];
+
+#ifdef RT_BIG_ENDIAN
+       RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE);
+#endif
+
+       fc0 = *pData;
+       fc1 = *(pData + 1);
+
+       fc = *((PUSHORT)pData);
+
+       frame_type = ((fc0 >> 2) & 0x03);
+       frame_subtype = ((fc0 >> 4) & 0x0f);
+
+       from_ds = (fc1 & 0x2) >> 1;
+       to_ds = (fc1 & 0x1);
+
+       a4_exists = (from_ds & to_ds);
+       qc_exists = ((frame_subtype == 0x08) ||    /* Assumed QoS subtypes */
+                                 (frame_subtype == 0x09) ||   /* Likely to change.    */
+                                 (frame_subtype == 0x0a) ||
+                                 (frame_subtype == 0x0b)
+                                );
+
+       HeaderLen = 24;
+       if (a4_exists)
+               HeaderLen += 6;
+
+       KeyID = *((PUCHAR)(pData+ HeaderLen + 3));
+       KeyID = KeyID >> 6;
+
+       if (pWpaKey[KeyID].KeyLen == 0)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptAES failed!(KeyID[%d] Length can not be 0)\n", KeyID));
+               return FALSE;
+       }
+
+       PN[0] = *(pData+ HeaderLen);
+       PN[1] = *(pData+ HeaderLen + 1);
+       PN[2] = *(pData+ HeaderLen + 4);
+       PN[3] = *(pData+ HeaderLen + 5);
+       PN[4] = *(pData+ HeaderLen + 6);
+       PN[5] = *(pData+ HeaderLen + 7);
+
+       payload_len = DataByteCnt - HeaderLen - 8 - 8;  // 8 bytes for CCMP header , 8 bytes for MIC
+       payload_remainder = (payload_len) % 16;
+       num_blocks = (payload_len) / 16;
+
+
+
+       // Find start of payload
+       payload_index = HeaderLen + 8; //IV+EIV
+
+       for (i=0; i< num_blocks; i++)
+       {
+               construct_ctr_preload(ctr_preload,
+                                                               a4_exists,
+                                                               qc_exists,
+                                                               pData,
+                                                               PN,
+                                                               i+1 );
+
+               aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out);
+
+               bitwise_xor(aes_out, pData + payload_index, chain_buffer);
+               NdisMoveMemory(pData + payload_index - 8, chain_buffer, 16);
+               payload_index += 16;
+       }
+
+       //
+       // If there is a short final block, then pad it
+       // encrypt it and copy the unpadded part back
+       //
+       if (payload_remainder > 0)
+       {
+               construct_ctr_preload(ctr_preload,
+                                                               a4_exists,
+                                                               qc_exists,
+                                                               pData,
+                                                               PN,
+                                                               num_blocks + 1);
+
+               NdisZeroMemory(padded_buffer, 16);
+               NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder);
+
+               aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out);
+
+               bitwise_xor(aes_out, padded_buffer, chain_buffer);
+               NdisMoveMemory(pData + payload_index - 8, chain_buffer, payload_remainder);
+               payload_index += payload_remainder;
+       }
+
+       //
+       // Descrypt the MIC
+       //
+       construct_ctr_preload(ctr_preload,
+                                                       a4_exists,
+                                                       qc_exists,
+                                                       pData,
+                                                       PN,
+                                                       0);
+       NdisZeroMemory(padded_buffer, 16);
+       NdisMoveMemory(padded_buffer, pData + payload_index, 8);
+
+       aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out);
+
+       bitwise_xor(aes_out, padded_buffer, chain_buffer);
+
+       NdisMoveMemory(TrailMIC, chain_buffer, 8);
+
+       //
+       // Calculate MIC
+       //
+
+       //Force the protected frame bit on
+       *(pData + 1) = *(pData + 1) | 0x40;
+
+       // Find start of payload
+       // Because the CCMP header has been removed
+       payload_index = HeaderLen;
+
+       construct_mic_iv(
+                                       mic_iv,
+                                       qc_exists,
+                                       a4_exists,
+                                       pData,
+                                       payload_len,
+                                       PN);
+
+       construct_mic_header1(
+                                               mic_header1,
+                                               HeaderLen,
+                                               pData);
+
+       construct_mic_header2(
+                                               mic_header2,
+                                               pData,
+                                               a4_exists,
+                                               qc_exists);
+
+       aes128k128d(pWpaKey[KeyID].Key, mic_iv, aes_out);
+       bitwise_xor(aes_out, mic_header1, chain_buffer);
+       aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out);
+       bitwise_xor(aes_out, mic_header2, chain_buffer);
+       aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out);
+
+       // iterate through each 16 byte payload block
+       for (i = 0; i < num_blocks; i++)
+       {
+               bitwise_xor(aes_out, pData + payload_index, chain_buffer);
+               payload_index += 16;
+               aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out);
+       }
+
+       // Add on the final payload block if it needs padding
+       if (payload_remainder > 0)
+       {
+               NdisZeroMemory(padded_buffer, 16);
+               NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder);
+
+               bitwise_xor(aes_out, padded_buffer, chain_buffer);
+               aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out);
+       }
+
+       // aes_out contains padded mic, discard most significant
+       // 8 bytes to generate 64 bit MIC
+       for (i = 0 ; i < 8; i++) MIC[i] = aes_out[i];
+
+       if (!NdisEqualMemory(MIC, TrailMIC, 8))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptAES, MIC Error !\n"));         //MIC error.
+               return FALSE;
+       }
+
+#ifdef RT_BIG_ENDIAN
+       RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE);
+#endif
+
+       return TRUE;
+}
+
+/****************************************/
+/* aes128k128d()                        */
+/* Performs a 128 bit AES encrypt with  */
+/* 128 bit data.                        */
+/****************************************/
+VOID xor_128(
+       IN  PUCHAR  a,
+       IN  PUCHAR  b,
+       OUT PUCHAR  out)
+{
+       INT i;
+
+       for (i=0;i<16; i++)
+       {
+               out[i] = a[i] ^ b[i];
+       }
+}
+
+VOID next_key(
+       IN  PUCHAR  key,
+       IN  INT     round)
+{
+       UCHAR       rcon;
+       UCHAR       sbox_key[4];
+       UCHAR       rcon_table[12] =
+       {
+               0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+               0x1b, 0x36, 0x36, 0x36
+       };
+
+       sbox_key[0] = RTMPCkipSbox(key[13]);
+       sbox_key[1] = RTMPCkipSbox(key[14]);
+       sbox_key[2] = RTMPCkipSbox(key[15]);
+       sbox_key[3] = RTMPCkipSbox(key[12]);
+
+       rcon = rcon_table[round];
+
+       xor_32(&key[0], sbox_key, &key[0]);
+       key[0] = key[0] ^ rcon;
+
+       xor_32(&key[4], &key[0], &key[4]);
+       xor_32(&key[8], &key[4], &key[8]);
+       xor_32(&key[12], &key[8], &key[12]);
+}
+
+VOID xor_32(
+       IN  PUCHAR  a,
+       IN  PUCHAR  b,
+       OUT PUCHAR  out)
+{
+       INT i;
+
+       for (i=0;i<4; i++)
+       {
+               out[i] = a[i] ^ b[i];
+       }
+}
+
+VOID byte_sub(
+       IN  PUCHAR  in,
+       OUT PUCHAR  out)
+{
+       INT i;
+
+       for (i=0; i< 16; i++)
+       {
+               out[i] = RTMPCkipSbox(in[i]);
+       }
+}
+
+UCHAR RTMPCkipSbox(
+       IN  UCHAR   a)
+{
+       return SboxTable[(int)a];
+}
+
+VOID shift_row(
+       IN  PUCHAR  in,
+       OUT PUCHAR  out)
+{
+       out[0] =  in[0];
+       out[1] =  in[5];
+       out[2] =  in[10];
+       out[3] =  in[15];
+       out[4] =  in[4];
+       out[5] =  in[9];
+       out[6] =  in[14];
+       out[7] =  in[3];
+       out[8] =  in[8];
+       out[9] =  in[13];
+       out[10] = in[2];
+       out[11] = in[7];
+       out[12] = in[12];
+       out[13] = in[1];
+       out[14] = in[6];
+       out[15] = in[11];
+}
+
+VOID mix_column(
+       IN  PUCHAR  in,
+       OUT PUCHAR  out)
+{
+       INT         i;
+       UCHAR       add1b[4];
+       UCHAR       add1bf7[4];
+       UCHAR       rotl[4];
+       UCHAR       swap_halfs[4];
+       UCHAR       andf7[4];
+       UCHAR       rotr[4];
+       UCHAR       temp[4];
+       UCHAR       tempb[4];
+
+       for (i=0 ; i<4; i++)
+       {
+               if ((in[i] & 0x80)== 0x80)
+                       add1b[i] = 0x1b;
+               else
+                       add1b[i] = 0x00;
+       }
+
+       swap_halfs[0] = in[2];    /* Swap halfs */
+       swap_halfs[1] = in[3];
+       swap_halfs[2] = in[0];
+       swap_halfs[3] = in[1];
+
+       rotl[0] = in[3];        /* Rotate left 8 bits */
+       rotl[1] = in[0];
+       rotl[2] = in[1];
+       rotl[3] = in[2];
+
+       andf7[0] = in[0] & 0x7f;
+       andf7[1] = in[1] & 0x7f;
+       andf7[2] = in[2] & 0x7f;
+       andf7[3] = in[3] & 0x7f;
+
+       for (i = 3; i>0; i--)    /* logical shift left 1 bit */
+       {
+               andf7[i] = andf7[i] << 1;
+               if ((andf7[i-1] & 0x80) == 0x80)
+               {
+                       andf7[i] = (andf7[i] | 0x01);
+               }
+       }
+       andf7[0] = andf7[0] << 1;
+       andf7[0] = andf7[0] & 0xfe;
+
+       xor_32(add1b, andf7, add1bf7);
+
+       xor_32(in, add1bf7, rotr);
+
+       temp[0] = rotr[0];         /* Rotate right 8 bits */
+       rotr[0] = rotr[1];
+       rotr[1] = rotr[2];
+       rotr[2] = rotr[3];
+       rotr[3] = temp[0];
+
+       xor_32(add1bf7, rotr, temp);
+       xor_32(swap_halfs, rotl,tempb);
+       xor_32(temp, tempb, out);
+}
+
diff --git a/drivers/staging/rt2870/common/rtmp_wep.c b/drivers/staging/rt2870/common/rtmp_wep.c
new file mode 100644 (file)
index 0000000..62f9e58
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       rtmp_wep.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Paul Wu         10-28-02                Initial
+*/
+
+#include "../rt_config.h"
+
+UINT FCSTAB_32[256] =
+{
+       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+       0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+       0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+       0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+       0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+       0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+       0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+       0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+       0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+       0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+       0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+       0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+       0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+       0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+       0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+       0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+       0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+       0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+       0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+       0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+       0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+       0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+       0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+       0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+       0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+       0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+       0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+       0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+       0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+       0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+       0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+       0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+       0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+       0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+       0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+       0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+       0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+       0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+       0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+       0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+       0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+       0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+       0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+       0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+       0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+       0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+       0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+       0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+       0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+       0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+       0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+       0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+       0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+       0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+       0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+       0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+       0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+       0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+       0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+       0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+/*
+UCHAR   WEPKEY[] = {
+               //IV
+               0x00, 0x11, 0x22,
+               //WEP KEY
+               0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC
+       };
+ */
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Init WEP function.
+
+       Arguments:
+      pAd              Pointer to our adapter
+               pKey        Pointer to the WEP KEY
+               KeyId              WEP Key ID
+               KeyLen      the length of WEP KEY
+               pDest       Pointer to the destination which Encryption data will store in.
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPInitWepEngine(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pKey,
+       IN      UCHAR                   KeyId,
+       IN      UCHAR                   KeyLen,
+       IN OUT  PUCHAR          pDest)
+{
+       UINT i;
+       UCHAR   WEPKEY[] = {
+               //IV
+               0x00, 0x11, 0x22,
+               //WEP KEY
+               0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC
+       };
+
+       pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32;   //Init crc32.
+
+#ifdef CONFIG_STA_SUPPORT
+    if (pAd->StaCfg.bCkipOn && (pAd->StaCfg.CkipFlag & 0x10) && (pAd->OpMode == OPMODE_STA))
+    {
+        ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, pKey, KeyLen);  //INIT SBOX, KEYLEN+3(IV)
+        NdisMoveMemory(pDest, pKey, 3);  //Append Init Vector
+    }
+    else
+#endif // CONFIG_STA_SUPPORT //
+    {
+               NdisMoveMemory(WEPKEY + 3, pKey, KeyLen);
+
+        for(i = 0; i < 3; i++)
+                       WEPKEY[i] = RandomByte(pAd);   //Call mlme RandomByte() function.
+               ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, KeyLen + 3);  //INIT SBOX, KEYLEN+3(IV)
+
+               NdisMoveMemory(pDest, WEPKEY, 3);  //Append Init Vector
+    }
+       *(pDest+3) = (KeyId << 6);       //Append KEYID
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Encrypt transimitted data
+
+       Arguments:
+      pAd              Pointer to our adapter
+      pSrc        Pointer to the transimitted source data that will be encrypt
+      pDest       Pointer to the destination where entryption data will be store in.
+      Len                      Indicate the length of the source data
+
+       Return Value:
+      None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPEncryptData(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pSrc,
+       IN      PUCHAR                  pDest,
+       IN      UINT                    Len)
+{
+       pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, pSrc, Len);
+       ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, pSrc, Len);
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Decrypt received WEP data
+
+       Arguments:
+               pAdapter                Pointer to our adapter
+               pSrc        Pointer to the received data
+               Len         the length of the received data
+
+       Return Value:
+               TRUE        Decrypt WEP data success
+               FALSE       Decrypt WEP data failed
+
+       Note:
+
+       ========================================================================
+*/
+BOOLEAN        RTMPSoftDecryptWEP(
+       IN PRTMP_ADAPTER        pAd,
+       IN PUCHAR                       pData,
+       IN ULONG                        DataByteCnt,
+       IN PCIPHER_KEY          pGroupKey)
+{
+       UINT    trailfcs;
+       UINT    crc32;
+       UCHAR   KeyIdx;
+       UCHAR   WEPKEY[] = {
+               //IV
+               0x00, 0x11, 0x22,
+               //WEP KEY
+               0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC
+       };
+       UCHAR   *pPayload = (UCHAR *)pData + LENGTH_802_11;
+       ULONG   payload_len = DataByteCnt - LENGTH_802_11;
+
+       NdisMoveMemory(WEPKEY, pPayload, 3);    //Get WEP IV
+
+       KeyIdx = (*(pPayload + 3) & 0xc0) >> 6;
+       if (pGroupKey[KeyIdx].KeyLen == 0)
+               return (FALSE);
+
+       NdisMoveMemory(WEPKEY + 3, pGroupKey[KeyIdx].Key, pGroupKey[KeyIdx].KeyLen);
+       ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, pGroupKey[KeyIdx].KeyLen + 3);
+       ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, pPayload, pPayload + 4, payload_len - 4);
+       NdisMoveMemory(&trailfcs, pPayload + payload_len - 8, 4);
+       crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pPayload, payload_len - 8);  //Skip last 4 bytes(FCS).
+       crc32 ^= 0xffffffff;             /* complement */
+
+    if(crc32 != cpu2le32(trailfcs))
+    {
+               DBGPRINT(RT_DEBUG_TRACE, ("! WEP Data CRC Error !\n"));  //CRC error.
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               The Stream Cipher Encryption Algorithm "ARCFOUR" initialize
+
+       Arguments:
+          Ctx         Pointer to ARCFOUR CONTEXT (SBOX)
+               pKey        Pointer to the WEP KEY
+               KeyLen      Indicate the length fo the WEP KEY
+
+       Return Value:
+          None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   ARCFOUR_INIT(
+       IN      PARCFOURCONTEXT Ctx,
+       IN      PUCHAR                  pKey,
+       IN      UINT                    KeyLen)
+{
+       UCHAR   t, u;
+       UINT    keyindex;
+       UINT    stateindex;
+       PUCHAR  state;
+       UINT    counter;
+
+       state = Ctx->STATE;
+       Ctx->X = 0;
+       Ctx->Y = 0;
+       for (counter = 0; counter < 256; counter++)
+               state[counter] = (UCHAR)counter;
+       keyindex = 0;
+       stateindex = 0;
+       for (counter = 0; counter < 256; counter++)
+       {
+               t = state[counter];
+               stateindex = (stateindex + pKey[keyindex] + t) & 0xff;
+               u = state[stateindex];
+               state[stateindex] = t;
+               state[counter] = u;
+               if (++keyindex >= KeyLen)
+                       keyindex = 0;
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Get bytes from ARCFOUR CONTEXT (S-BOX)
+
+       Arguments:
+          Ctx         Pointer to ARCFOUR CONTEXT (SBOX)
+
+       Return Value:
+          UCHAR  - the value of the ARCFOUR CONTEXT (S-BOX)
+
+       Note:
+
+       ========================================================================
+*/
+UCHAR  ARCFOUR_BYTE(
+       IN      PARCFOURCONTEXT         Ctx)
+{
+  UINT x;
+  UINT y;
+  UCHAR sx, sy;
+  PUCHAR state;
+
+  state = Ctx->STATE;
+  x = (Ctx->X + 1) & 0xff;
+  sx = state[x];
+  y = (sx + Ctx->Y) & 0xff;
+  sy = state[y];
+  Ctx->X = x;
+  Ctx->Y = y;
+  state[y] = sx;
+  state[x] = sy;
+
+  return(state[(sx + sy) & 0xff]);
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               The Stream Cipher Decryption Algorithm
+
+       Arguments:
+               Ctx         Pointer to ARCFOUR CONTEXT (SBOX)
+               pDest                   Pointer to the Destination
+               pSrc        Pointer to the Source data
+               Len         Indicate the length of the Source data
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   ARCFOUR_DECRYPT(
+       IN      PARCFOURCONTEXT Ctx,
+       IN      PUCHAR                  pDest,
+       IN      PUCHAR                  pSrc,
+       IN      UINT                    Len)
+{
+       UINT i;
+
+       for (i = 0; i < Len; i++)
+               pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               The Stream Cipher Encryption Algorithm
+
+       Arguments:
+               Ctx         Pointer to ARCFOUR CONTEXT (SBOX)
+               pDest                   Pointer to the Destination
+               pSrc        Pointer to the Source data
+               Len         Indicate the length of the Source dta
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   ARCFOUR_ENCRYPT(
+       IN      PARCFOURCONTEXT Ctx,
+       IN      PUCHAR                  pDest,
+       IN      PUCHAR                  pSrc,
+       IN      UINT                    Len)
+{
+       UINT i;
+
+       for (i = 0; i < Len; i++)
+               pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               The Stream Cipher Encryption Algorithm which conform to the special requirement to encrypt  GTK.
+
+       Arguments:
+               Ctx         Pointer to ARCFOUR CONTEXT (SBOX)
+               pDest                   Pointer to the Destination
+               pSrc        Pointer to the Source data
+               Len         Indicate the length of the Source dta
+
+
+       ========================================================================
+*/
+
+VOID   WPAARCFOUR_ENCRYPT(
+       IN      PARCFOURCONTEXT Ctx,
+       IN      PUCHAR                  pDest,
+       IN      PUCHAR                  pSrc,
+       IN      UINT                    Len)
+{
+       UINT i;
+        //discard first 256 bytes
+       for (i = 0; i < 256; i++)
+            ARCFOUR_BYTE(Ctx);
+
+       for (i = 0; i < Len; i++)
+               pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx);
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Calculate a new FCS given the current FCS and the new data.
+
+       Arguments:
+               Fcs           the original FCS value
+               Cp          pointer to the data which will be calculate the FCS
+               Len         the length of the data
+
+       Return Value:
+               UINT - FCS 32 bits
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+UINT   RTMP_CALC_FCS32(
+       IN      UINT    Fcs,
+       IN      PUCHAR  Cp,
+       IN      INT             Len)
+{
+       while (Len--)
+          Fcs = (((Fcs) >> 8) ^ FCSTAB_32[((Fcs) ^ (*Cp++)) & 0xff]);
+
+       return (Fcs);
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Get last FCS and encrypt it to the destination
+
+       Arguments:
+               pDest                   Pointer to the Destination
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPSetICV(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR  pDest)
+{
+       pAd->PrivateInfo.FCSCRC32 ^= 0xffffffff;             /* complement */
+       pAd->PrivateInfo.FCSCRC32 = cpu2le32(pAd->PrivateInfo.FCSCRC32);
+
+       ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, (PUCHAR) &pAd->PrivateInfo.FCSCRC32, 4);
+}
+
diff --git a/drivers/staging/rt2870/common/rtusb_bulk.c b/drivers/staging/rt2870/common/rtusb_bulk.c
new file mode 100644 (file)
index 0000000..3c6ba1b
--- /dev/null
@@ -0,0 +1,1981 @@
+ /*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       rtusb_bulk.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When            What
+       --------        ----------      ----------------------------------------------
+       Name            Date            Modification logs
+       Paul Lin        06-25-2004      created
+
+*/
+
+#include "../rt_config.h"
+// Match total 6 bulkout endpoint to corresponding queue.
+UCHAR  EpToQueue[6]={FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_MGMT};
+
+//static BOOLEAN SingleBulkOut = FALSE;
+
+void RTUSB_FILL_BULK_URB (struct urb *pUrb,
+       struct usb_device *pUsb_Dev,
+       unsigned int bulkpipe,
+       void *pTransferBuf,
+       int BufSize,
+       usb_complete_t Complete,
+       void *pContext)
+{
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+       usb_fill_bulk_urb(pUrb, pUsb_Dev, bulkpipe, pTransferBuf, BufSize, (usb_complete_t)Complete, pContext);
+#else
+       FILL_BULK_URB(pUrb, pUsb_Dev, bulkpipe, pTransferBuf, BufSize, Complete, pContext);
+#endif
+
+}
+
+VOID   RTUSBInitTxDesc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTX_CONTEXT             pTxContext,
+       IN      UCHAR                   BulkOutPipeId,
+       IN      usb_complete_t  Func)
+{
+       PURB                            pUrb;
+       PUCHAR                          pSrc = NULL;
+       POS_COOKIE                      pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+       pUrb = pTxContext->pUrb;
+       ASSERT(pUrb);
+
+       // Store BulkOut PipeId
+       pTxContext->BulkOutPipeId = BulkOutPipeId;
+
+       if (pTxContext->bAggregatible)
+       {
+               pSrc = &pTxContext->TransferBuffer->Aggregation[2];
+       }
+       else
+       {
+               pSrc = (PUCHAR) pTxContext->TransferBuffer->field.WirelessPacket;
+       }
+
+
+       //Initialize a tx bulk urb
+       RTUSB_FILL_BULK_URB(pUrb,
+                                               pObj->pUsb_Dev,
+                                               usb_sndbulkpipe(pObj->pUsb_Dev, pAd->BulkOutEpAddr[BulkOutPipeId]),
+                                               pSrc,
+                                               pTxContext->BulkOutSize,
+                                               Func,
+                                               pTxContext);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+       if (pTxContext->bAggregatible)
+               pUrb->transfer_dma      = (pTxContext->data_dma + TX_BUFFER_NORMSIZE + 2);
+       else
+               pUrb->transfer_dma      = pTxContext->data_dma;
+
+       pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+#endif
+
+}
+
+VOID   RTUSBInitHTTxDesc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PHT_TX_CONTEXT  pTxContext,
+       IN      UCHAR                   BulkOutPipeId,
+       IN      ULONG                   BulkOutSize,
+       IN      usb_complete_t  Func)
+{
+       PURB                            pUrb;
+       PUCHAR                          pSrc = NULL;
+       POS_COOKIE                      pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+       pUrb = pTxContext->pUrb;
+       ASSERT(pUrb);
+
+       // Store BulkOut PipeId
+       pTxContext->BulkOutPipeId = BulkOutPipeId;
+
+       pSrc = &pTxContext->TransferBuffer->field.WirelessPacket[pTxContext->NextBulkOutPosition];
+
+
+       //Initialize a tx bulk urb
+       RTUSB_FILL_BULK_URB(pUrb,
+                                               pObj->pUsb_Dev,
+                                               usb_sndbulkpipe(pObj->pUsb_Dev, pAd->BulkOutEpAddr[BulkOutPipeId]),
+                                               pSrc,
+                                               BulkOutSize,
+                                               Func,
+                                               pTxContext);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+       pUrb->transfer_dma      = (pTxContext->data_dma + pTxContext->NextBulkOutPosition);
+       pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+#endif
+
+}
+
+VOID   RTUSBInitRxDesc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PRX_CONTEXT             pRxContext)
+{
+       PURB                            pUrb;
+       POS_COOKIE                      pObj = (POS_COOKIE) pAd->OS_Cookie;
+       ULONG                           RX_bulk_size;
+
+
+       pUrb = pRxContext->pUrb;
+       ASSERT(pUrb);
+
+       if ( pAd->BulkInMaxPacketSize == 64)
+               RX_bulk_size = 4096;
+       else
+               RX_bulk_size = MAX_RXBULK_SIZE;
+
+       //Initialize a rx bulk urb
+       RTUSB_FILL_BULK_URB(pUrb,
+                                               pObj->pUsb_Dev,
+                                               usb_rcvbulkpipe(pObj->pUsb_Dev, pAd->BulkInEpAddr),
+                                               &(pRxContext->TransferBuffer[pAd->NextRxBulkInPosition]),
+                                               RX_bulk_size - (pAd->NextRxBulkInPosition),
+                                               (usb_complete_t)RTUSBBulkRxComplete,
+                                               (void *)pRxContext);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+       pUrb->transfer_dma      = pRxContext->data_dma + pAd->NextRxBulkInPosition;
+       pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+#endif
+
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+
+#define BULK_OUT_LOCK(pLock, IrqFlags) \
+               if(1 /*!(in_interrupt() & 0xffff0000)*/)        \
+                       RTMP_IRQ_LOCK((pLock), IrqFlags);
+
+#define BULK_OUT_UNLOCK(pLock, IrqFlags)       \
+               if(1 /*!(in_interrupt() & 0xffff0000)*/)        \
+                       RTMP_IRQ_UNLOCK((pLock), IrqFlags);
+
+
+VOID   RTUSBBulkOutDataPacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   BulkOutPipeId,
+       IN      UCHAR                   Index)
+{
+
+       PHT_TX_CONTEXT  pHTTXContext;
+       PURB                    pUrb;
+       int                             ret = 0;
+       PTXINFO_STRUC   pTxInfo, pLastTxInfo = NULL;
+       PTXWI_STRUC             pTxWI;
+       ULONG                   TmpBulkEndPos, ThisBulkSize;
+       unsigned long   IrqFlags = 0, IrqFlags2 = 0;
+       PUCHAR                  pWirelessPkt, pAppendant;
+       BOOLEAN                 bTxQLastRound = FALSE;
+       UCHAR                   allzero[4]= {0x0,0x0,0x0,0x0};
+
+       BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+       if ((pAd->BulkOutPending[BulkOutPipeId] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX))
+       {
+               BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+               return;
+       }
+       pAd->BulkOutPending[BulkOutPipeId] = TRUE;
+
+       if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
+               )
+       {
+               pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+               BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+               return;
+       }
+       BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+
+
+       pHTTXContext = &(pAd->TxContext[BulkOutPipeId]);
+
+       BULK_OUT_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2);
+       if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)
+               || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition))
+       {
+               BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2);
+
+               BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+               pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+
+               // Clear Data flag
+               RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId));
+               RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+
+               BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+               return;
+       }
+
+       // Clear Data flag
+       RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId));
+       RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+
+       //DBGPRINT(RT_DEBUG_TRACE,("BulkOut-B:I=0x%lx, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", in_interrupt(),
+       //                                                      pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition,
+       //                                                      pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad));
+       pHTTXContext->NextBulkOutPosition = pHTTXContext->ENextBulkOutPosition;
+       ThisBulkSize = 0;
+       TmpBulkEndPos = pHTTXContext->NextBulkOutPosition;
+       pWirelessPkt = &pHTTXContext->TransferBuffer->field.WirelessPacket[0];
+
+       if ((pHTTXContext->bCopySavePad == TRUE))
+       {
+               if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero,4))
+               {
+                       DBGPRINT_RAW(RT_DEBUG_ERROR,("e1, allzero : %x  %x  %x  %x  %x  %x  %x  %x \n",
+                               pHTTXContext->SavedPad[0], pHTTXContext->SavedPad[1], pHTTXContext->SavedPad[2],pHTTXContext->SavedPad[3]
+                               ,pHTTXContext->SavedPad[4], pHTTXContext->SavedPad[5], pHTTXContext->SavedPad[6],pHTTXContext->SavedPad[7]));
+               }
+               NdisMoveMemory(&pWirelessPkt[TmpBulkEndPos], pHTTXContext->SavedPad, 8);
+               pHTTXContext->bCopySavePad = FALSE;
+               if (pAd->bForcePrintTX == TRUE)
+                       DBGPRINT(RT_DEBUG_TRACE,("RTUSBBulkOutDataPacket --> COPY PAD. CurWrite = %ld, NextBulk = %ld.   ENextBulk = %ld.\n",   pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition));
+       }
+
+       do
+       {
+               pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[TmpBulkEndPos];
+               pTxWI = (PTXWI_STRUC)&pWirelessPkt[TmpBulkEndPos + TXINFO_SIZE];
+
+               if (pAd->bForcePrintTX == TRUE)
+                       DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkOutDataPacket AMPDU = %d.\n",   pTxWI->AMPDU));
+
+               // add by Iverson, limit BulkOut size to 4k to pass WMM b mode 2T1R test items
+               //if ((ThisBulkSize != 0)  && (pTxWI->AMPDU == 0))
+               if ((ThisBulkSize != 0) && (pTxWI->PHYMODE == MODE_CCK))
+               {
+                       if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x1000) == 0x1000))
+                       {
+                               // Limit BulkOut size to about 4k bytes.
+                               pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+                               break;
+                       }
+                       else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize&0xfffff800) != 0) ) /*|| ( (ThisBulkSize != 0)  && (pTxWI->AMPDU == 0))*/)
+                       {
+                               // For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size.
+                               // For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04.
+                               pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+                               break;
+                       }
+               }
+               // end Iverson
+               else
+               {
+                       if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x6000) == 0x6000))
+                       {       // Limit BulkOut size to about 24k bytes.
+                               pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+                               break;
+                       }
+                       else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize&0xfffff800) != 0) ) /*|| ( (ThisBulkSize != 0)  && (pTxWI->AMPDU == 0))*/)
+                       {       // For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size.
+                               // For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04.
+                               pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+                               break;
+                       }
+               }
+
+               if (TmpBulkEndPos == pHTTXContext->CurWritePosition)
+               {
+                       pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+                       break;
+               }
+
+               if (pTxInfo->QSEL != FIFO_EDCA)
+               {
+                       printk("%s(): ====> pTxInfo->QueueSel(%d)!= FIFO_EDCA!!!!\n", __FUNCTION__, pTxInfo->QSEL);
+                       printk("\tCWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad);
+                       hex_dump("Wrong QSel Pkt:", (PUCHAR)&pWirelessPkt[TmpBulkEndPos], (pHTTXContext->CurWritePosition - pHTTXContext->NextBulkOutPosition));
+               }
+
+               if (pTxInfo->USBDMATxPktLen <= 8)
+               {
+                       BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2);
+                       DBGPRINT(RT_DEBUG_ERROR /*RT_DEBUG_TRACE*/,("e2, USBDMATxPktLen==0, Size=%ld, bCSPad=%d, CWPos=%ld, NBPos=%ld, CWRPos=%ld!\n",
+                                       pHTTXContext->BulkOutSize, pHTTXContext->bCopySavePad, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->CurWriteRealPos));
+                       {
+                               DBGPRINT_RAW(RT_DEBUG_ERROR /*RT_DEBUG_TRACE*/,("%x  %x  %x  %x  %x  %x  %x  %x \n",
+                                       pHTTXContext->SavedPad[0], pHTTXContext->SavedPad[1], pHTTXContext->SavedPad[2],pHTTXContext->SavedPad[3]
+                                       ,pHTTXContext->SavedPad[4], pHTTXContext->SavedPad[5], pHTTXContext->SavedPad[6],pHTTXContext->SavedPad[7]));
+                       }
+                       pAd->bForcePrintTX = TRUE;
+                       BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+                       pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+                       BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+                       //DBGPRINT(RT_DEBUG_LOUD,("Out:pTxInfo->USBDMATxPktLen=%d!\n", pTxInfo->USBDMATxPktLen));
+                       return;
+               }
+
+                       // Increase Total transmit byte counter
+               pAd->RalinkCounters.OneSecTransmittedByteCount +=  pTxWI->MPDUtotalByteCount;
+               pAd->RalinkCounters.TransmittedByteCount +=  pTxWI->MPDUtotalByteCount;
+
+               pLastTxInfo = pTxInfo;
+
+               // Make sure we use EDCA QUEUE.
+               pTxInfo->QSEL = FIFO_EDCA;
+               ThisBulkSize += (pTxInfo->USBDMATxPktLen+4);
+               TmpBulkEndPos += (pTxInfo->USBDMATxPktLen+4);
+
+               if (TmpBulkEndPos != pHTTXContext->CurWritePosition)
+                       pTxInfo->USBDMANextVLD = 1;
+
+               if (pTxInfo->SwUseLastRound == 1)
+               {
+                       if (pHTTXContext->CurWritePosition == 8)
+                               pTxInfo->USBDMANextVLD = 0;
+                       pTxInfo->SwUseLastRound = 0;
+
+                       bTxQLastRound = TRUE;
+                       pHTTXContext->ENextBulkOutPosition = 8;
+
+       #ifdef RT_BIG_ENDIAN
+                       RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO);
+                       RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
+       #endif // RT_BIG_ENDIAN //
+
+                       break;
+               }
+
+#ifdef RT_BIG_ENDIAN
+               RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO);
+               RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
+#endif // RT_BIG_ENDIAN //
+
+       }while (TRUE);
+
+       // adjust the pTxInfo->USBDMANextVLD value of last pTxInfo.
+       if (pLastTxInfo)
+       {
+#ifdef RT_BIG_ENDIAN
+               RTMPDescriptorEndianChange((PUCHAR)pLastTxInfo, TYPE_TXINFO);
+#endif // RT_BIG_ENDIAN //
+               pLastTxInfo->USBDMANextVLD = 0;
+#ifdef RT_BIG_ENDIAN
+               RTMPDescriptorEndianChange((PUCHAR)pLastTxInfo, TYPE_TXINFO);
+#endif // RT_BIG_ENDIAN //
+       }
+
+       /*
+               We need to copy SavedPad when following condition matched!
+                       1. Not the last round of the TxQueue and
+                       2. any match of following cases:
+                               (1). The End Position of this bulk out is reach to the Currenct Write position and
+                                               the TxInfo and related header already write to the CurWritePosition.
+                                       =>(ENextBulkOutPosition == CurWritePosition) && (CurWriteRealPos > CurWritePosition)
+
+                               (2). The EndPosition of the bulk out is not reach to the Current Write Position.
+                                       =>(ENextBulkOutPosition != CurWritePosition)
+       */
+       if ((bTxQLastRound == FALSE) &&
+                (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) && (pHTTXContext->CurWriteRealPos > pHTTXContext->CurWritePosition)) ||
+                 (pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition))
+               )
+       {
+               NdisMoveMemory(pHTTXContext->SavedPad, &pWirelessPkt[pHTTXContext->ENextBulkOutPosition], 8);
+               pHTTXContext->bCopySavePad = TRUE;
+               if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero,4))
+               {
+                       PUCHAR  pBuf = &pHTTXContext->SavedPad[0];
+                       DBGPRINT_RAW(RT_DEBUG_ERROR,("WARNING-Zero-3:%02x%02x%02x%02x%02x%02x%02x%02x,CWPos=%ld, CWRPos=%ld, bCW=%d, NBPos=%ld, TBPos=%ld, TBSize=%ld\n",
+                               pBuf[0], pBuf[1], pBuf[2],pBuf[3],pBuf[4], pBuf[5], pBuf[6],pBuf[7], pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos,
+                               pHTTXContext->bCurWriting, pHTTXContext->NextBulkOutPosition, TmpBulkEndPos, ThisBulkSize));
+
+                       pBuf = &pWirelessPkt[pHTTXContext->CurWritePosition];
+                       DBGPRINT_RAW(RT_DEBUG_ERROR,("\tCWPos=%02x%02x%02x%02x%02x%02x%02x%02x\n", pBuf[0], pBuf[1], pBuf[2],pBuf[3],pBuf[4], pBuf[5], pBuf[6],pBuf[7]));
+               }
+               //DBGPRINT(RT_DEBUG_LOUD,("ENPos==CWPos=%ld, CWRPos=%ld, bCSPad=%d!\n", pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->bCopySavePad));
+       }
+
+       if (pAd->bForcePrintTX == TRUE)
+               DBGPRINT(RT_DEBUG_TRACE,("BulkOut-A:Size=%ld, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad));
+       //DBGPRINT(RT_DEBUG_LOUD,("BulkOut-A:Size=%ld, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, bLRound=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, bTxQLastRound));
+
+               // USB DMA engine requires to pad extra 4 bytes. This pad doesn't count into real bulkoutsize.
+       pAppendant = &pWirelessPkt[TmpBulkEndPos];
+       NdisZeroMemory(pAppendant, 8);
+               ThisBulkSize += 4;
+               pHTTXContext->LastOne = TRUE;
+               if ((ThisBulkSize % pAd->BulkOutMaxPacketSize) == 0)
+                       ThisBulkSize += 4;
+       pHTTXContext->BulkOutSize = ThisBulkSize;
+
+       pAd->watchDogTxPendingCnt[BulkOutPipeId] = 1;
+       BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2);
+
+       // Init Tx context descriptor
+       RTUSBInitHTTxDesc(pAd, pHTTXContext, BulkOutPipeId, ThisBulkSize, (usb_complete_t)RTUSBBulkOutDataPacketComplete);
+
+       pUrb = pHTTXContext->pUrb;
+       if((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", ret));
+
+               BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+               pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+               pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0;
+               BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+
+               return;
+       }
+
+       BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+       pHTTXContext->IRPPending = TRUE;
+       BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+       pAd->BulkOutReq++;
+
+}
+
+
+VOID RTUSBBulkOutDataPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs)
+{
+#if 0 // sample, IRQ LOCK
+       PRTMP_ADAPTER           pAd;
+       POS_COOKIE                      pObj;
+       PHT_TX_CONTEXT          pHTTXContext;
+       UCHAR                           BulkOutPipeId;
+       NTSTATUS                        Status;
+       unsigned long           IrqFlags;
+
+       DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutDataPacketComplete\n"));
+
+       pHTTXContext    = (PHT_TX_CONTEXT)pUrb->context;
+       pAd                     = pHTTXContext->pAd;
+       pObj            = (POS_COOKIE) pAd->OS_Cookie;
+       Status          = pUrb->status;
+
+       // Store BulkOut PipeId
+       BulkOutPipeId = pHTTXContext->BulkOutPipeId;
+       pAd->BulkOutDataOneSecCount++;
+
+       //DBGPRINT(RT_DEBUG_LOUD, ("Done-B(%d):I=0x%lx, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", BulkOutPipeId, in_interrupt(), pHTTXContext->CurWritePosition,
+       //              pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad));
+
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+       pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+       pHTTXContext->IRPPending = FALSE;
+       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+
+       if (Status == USB_ST_NOERROR)
+       {
+               pAd->BulkOutComplete++;
+
+               pAd->Counters8023.GoodTransmits++;
+               //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+               FREE_HTTX_RING(pAd, BulkOutPipeId, pHTTXContext);
+               //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+
+
+       }
+       else    // STATUS_OTHER
+       {
+               PUCHAR  pBuf;
+
+               pAd->BulkOutCompleteOther++;
+
+               pBuf = &pHTTXContext->TransferBuffer->WirelessPacket[pHTTXContext->NextBulkOutPosition];
+
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkOutDataPacket failed: ReasonCode=%d!\n", Status));
+               DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther));
+               DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOut Header:%x %x %x %x %x %x %x %x\n", pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5], pBuf[6], pBuf[7]));
+               //DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOutCompleteCancel=0x%x, BulkOutCompleteOther=0x%x\n", pAd->BulkOutCompleteCancel, pAd->BulkOutCompleteOther));
+
+               if (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                                       fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                                       fRTMP_ADAPTER_NIC_NOT_EXIST |
+                                                                       fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       pAd->bulkResetPipeid = BulkOutPipeId;
+               }
+       }
+
+       //
+       // bInUse = TRUE, means some process are filling TX data, after that must turn on bWaitingBulkOut
+       // bWaitingBulkOut = TRUE, means the TX data are waiting for bulk out.
+       //
+       //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+       if ((pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition) &&
+               (pHTTXContext->ENextBulkOutPosition != (pHTTXContext->CurWritePosition+8)) &&
+               !RTUSB_TEST_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId)))
+       {
+               // Indicate There is data avaliable
+               RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+       }
+       //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+
+       // Always call Bulk routine, even reset bulk.
+       // The protection of rest bulk should be in BulkOut routine
+       RTUSBKickBulkOut(pAd);
+
+
+       //DBGPRINT(RT_DEBUG_LOUD,("Done-A(%d):I=0x%lx, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d\n", BulkOutPipeId, in_interrupt(),
+       //              pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad));
+
+       switch (BulkOutPipeId)
+       {
+               case 0:
+                               pObj->ac0_dma_done_task.data = (unsigned long)pAd;
+                               tasklet_hi_schedule(&pObj->ac0_dma_done_task);
+                               break;
+               case 1:
+                               pObj->ac1_dma_done_task.data = (unsigned long)pAd;
+                               tasklet_hi_schedule(&pObj->ac1_dma_done_task);
+                               break;
+               case 2:
+                               pObj->ac2_dma_done_task.data = (unsigned long)pAd;
+                               tasklet_hi_schedule(&pObj->ac2_dma_done_task);
+                               break;
+               case 3:
+                               pObj->ac3_dma_done_task.data = (unsigned long)pAd;
+                               tasklet_hi_schedule(&pObj->ac3_dma_done_task);
+                               break;
+               case 4:
+                               pObj->hcca_dma_done_task.data = (unsigned long)pAd;
+                               tasklet_hi_schedule(&pObj->hcca_dma_done_task);
+                               break;
+       }
+#else
+
+{
+       PHT_TX_CONTEXT  pHTTXContext;
+       PRTMP_ADAPTER   pAd;
+       POS_COOKIE              pObj;
+       UCHAR                   BulkOutPipeId;
+
+
+       pHTTXContext    = (PHT_TX_CONTEXT)pUrb->context;
+       pAd                     = pHTTXContext->pAd;
+       pObj                    = (POS_COOKIE) pAd->OS_Cookie;
+
+       // Store BulkOut PipeId
+       BulkOutPipeId   = pHTTXContext->BulkOutPipeId;
+       pAd->BulkOutDataOneSecCount++;
+
+       switch (BulkOutPipeId)
+       {
+               case 0:
+                               pObj->ac0_dma_done_task.data = (unsigned long)pUrb;
+                               tasklet_hi_schedule(&pObj->ac0_dma_done_task);
+                               break;
+               case 1:
+                               pObj->ac1_dma_done_task.data = (unsigned long)pUrb;
+                               tasklet_hi_schedule(&pObj->ac1_dma_done_task);
+                               break;
+               case 2:
+                               pObj->ac2_dma_done_task.data = (unsigned long)pUrb;
+                               tasklet_hi_schedule(&pObj->ac2_dma_done_task);
+                               break;
+               case 3:
+                               pObj->ac3_dma_done_task.data = (unsigned long)pUrb;
+                               tasklet_hi_schedule(&pObj->ac3_dma_done_task);
+                               break;
+               case 4:
+                               pObj->hcca_dma_done_task.data = (unsigned long)pUrb;
+                               tasklet_hi_schedule(&pObj->hcca_dma_done_task);
+                               break;
+       }
+}
+#endif
+
+
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note: NULL frame use BulkOutPipeId = 0
+
+       ========================================================================
+*/
+VOID   RTUSBBulkOutNullFrame(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       PTX_CONTEXT             pNullContext = &(pAd->NullContext);
+       PURB                    pUrb;
+       int                             ret = 0;
+       unsigned long   IrqFlags;
+
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags);
+       if ((pAd->BulkOutPending[0] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX))
+       {
+               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+               return;
+       }
+       pAd->BulkOutPending[0] = TRUE;
+       pAd->watchDogTxPendingCnt[0] = 1;
+       pNullContext->IRPPending = TRUE;
+       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+
+       // Increase Total transmit byte counter
+       pAd->RalinkCounters.TransmittedByteCount +=  pNullContext->BulkOutSize;
+
+
+       // Clear Null frame bulk flag
+       RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL);
+
+#ifdef RT_BIG_ENDIAN
+       RTMPDescriptorEndianChange((PUCHAR)pNullContext->TransferBuffer, TYPE_TXINFO);
+#endif // RT_BIG_ENDIAN //
+
+       // Init Tx context descriptor
+       RTUSBInitTxDesc(pAd, pNullContext, 0, (usb_complete_t)RTUSBBulkOutNullFrameComplete);
+
+       pUrb = pNullContext->pUrb;
+       if((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+       {
+               RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags);
+               pAd->BulkOutPending[0] = FALSE;
+               pAd->watchDogTxPendingCnt[0] = 0;
+               pNullContext->IRPPending = FALSE;
+               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+
+               DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutNullFrame: Submit Tx URB failed %d\n", ret));
+               return;
+       }
+
+}
+
+// NULL frame use BulkOutPipeId = 0
+VOID RTUSBBulkOutNullFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs)
+{
+       PRTMP_ADAPTER           pAd;
+       PTX_CONTEXT                     pNullContext;
+       NTSTATUS                        Status;
+#if 0 // sample, IRQ LOCK
+       unsigned long           IrqFlags;
+#endif
+       POS_COOKIE                      pObj;
+
+
+       pNullContext    = (PTX_CONTEXT)pUrb->context;
+       pAd                     = pNullContext->pAd;
+       Status                  = pUrb->status;
+
+#if 0 // sample, IRQ LOCK
+       // Reset Null frame context flags
+       pNullContext->IRPPending        = FALSE;
+       pNullContext->InUse             = FALSE;
+
+       if (Status == USB_ST_NOERROR)
+       {
+               // Don't worry about the queue is empty or not, this function will check itself
+               //RTMPUSBDeQueuePacket(pAd, 0);
+               RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+       }
+       else    // STATUS_OTHER
+       {
+               if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out Null Frame Failed\n"));
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+       }
+
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags);
+       pAd->BulkOutPending[0] = FALSE;
+       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+
+       // Always call Bulk routine, even reset bulk.
+       // The protectioon of rest bulk should be in BulkOut routine
+       RTUSBKickBulkOut(pAd);
+#else
+
+       pObj = (POS_COOKIE) pAd->OS_Cookie;
+       pObj->null_frame_complete_task.data = (unsigned long)pUrb;
+       tasklet_hi_schedule(&pObj->null_frame_complete_task);
+#endif
+
+}
+
+#if 0  // For RT2870, RTS frame not used now, but maybe will use it latter.
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note: RTS frame use BulkOutPipeId = 0
+
+       ========================================================================
+*/
+VOID   RTUSBBulkOutRTSFrame(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       PTX_CONTEXT             pRTSContext = &(pAd->RTSContext);
+       PURB                    pUrb;
+       int                             ret = 0;
+       unsigned long   IrqFlags;
+       UCHAR                   PipeID=0;
+
+       if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_4))
+               PipeID= 3;
+       else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_3))
+               PipeID= 2;
+       else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_2))
+               PipeID= 1;
+       else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL))
+               PipeID= 0;
+
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[PipeID], IrqFlags);
+       if ((pAd->BulkOutPending[PipeID] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX))
+       {
+               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[PipeID], IrqFlags);
+               return;
+       }
+       pAd->BulkOutPending[PipeID] = TRUE;
+       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[PipeID], IrqFlags);
+
+       // Increase Total transmit byte counter
+       pAd->RalinkCounters.TransmittedByteCount +=  pRTSContext->BulkOutSize;
+
+       DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutRTSFrame \n"));
+
+       // Clear RTS frame bulk flag
+       RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_RTS);
+
+#ifdef RT_BIG_ENDIAN
+       RTMPDescriptorEndianChange((PUCHAR)pRTSContext->TransferBuffer, TYPE_TXINFO);
+#endif // RT_BIG_ENDIAN //
+
+       // Init Tx context descriptor
+       RTUSBInitTxDesc(pAd, pRTSContext, PipeID, (usb_complete_t)RTUSBBulkOutRTSFrameComplete);
+       pRTSContext->IRPPending = TRUE;
+
+       pUrb = pRTSContext->pUrb;
+       if((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutRTSFrame: Submit Tx URB failed %d\n", ret));
+               return;
+       }
+
+       DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutRTSFrame \n"));
+
+}
+
+// RTS frame use BulkOutPipeId = 0
+VOID RTUSBBulkOutRTSFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs)
+{
+       PRTMP_ADAPTER   pAd;
+       PTX_CONTEXT             pRTSContext;
+       NTSTATUS                Status;
+#if 0 // sample, IRQ LOCK
+       unsigned long   IrqFlags;
+#endif
+       POS_COOKIE              pObj;
+
+       DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutRTSFrameComplete\n"));
+
+       pRTSContext     = (PTX_CONTEXT)pUrb->context;
+       pAd                     = pRTSContext->pAd;
+       Status          = pUrb->status;
+
+#if 0 // sample, IRQ LOCK
+       // Reset RTS frame context flags
+       pRTSContext->IRPPending = FALSE;
+       pRTSContext->InUse              = FALSE;
+
+       if (Status == USB_ST_NOERROR)
+       {
+               // Don't worry about the queue is empty or not, this function will check itself
+               //RTMPUSBDeQueuePacket(pAd, pRTSContext->BulkOutPipeId);
+               RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+       }
+       else    // STATUS_OTHER
+       {
+               if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out RTS Frame Failed\n"));
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+       }
+
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId], IrqFlags);
+       pAd->BulkOutPending[pRTSContext->BulkOutPipeId] = FALSE;
+       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId], IrqFlags);
+
+       // Always call Bulk routine, even reset bulk.
+       // The protectioon of rest bulk should be in BulkOut routine
+       RTUSBKickBulkOut(pAd);
+#else
+
+       pObj = (POS_COOKIE) pAd->OS_Cookie;
+       pObj->rts_frame_complete_task.data = (unsigned long)pUrb;
+       tasklet_hi_schedule(&pObj->rts_frame_complete_task);
+#endif
+
+       DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutRTSFrameComplete\n"));
+
+}
+#endif
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note: MLME use BulkOutPipeId = 0
+
+       ========================================================================
+*/
+VOID   RTUSBBulkOutMLMEPacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Index)
+{
+       PTX_CONTEXT             pMLMEContext;
+       PURB                    pUrb;
+       int                             ret = 0;
+       unsigned long   IrqFlags;
+
+       pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa;
+       pUrb = pMLMEContext->pUrb;
+
+       if ((pAd->MgmtRing.TxSwFreeIdx >= MGMT_RING_SIZE) ||
+               (pMLMEContext->InUse == FALSE) ||
+               (pMLMEContext->bWaitingBulkOut == FALSE))
+       {
+
+
+               // Clear MLME bulk flag
+               RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
+
+               return;
+       }
+
+
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+       if ((pAd->BulkOutPending[MGMTPIPEIDX] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX))
+       {
+               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+               return;
+       }
+
+       pAd->BulkOutPending[MGMTPIPEIDX] = TRUE;
+       pAd->watchDogTxPendingCnt[MGMTPIPEIDX] = 1;
+       pMLMEContext->IRPPending = TRUE;
+       pMLMEContext->bWaitingBulkOut = FALSE;
+       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+
+       // Increase Total transmit byte counter
+       pAd->RalinkCounters.TransmittedByteCount +=  pMLMEContext->BulkOutSize;
+
+       // Clear MLME bulk flag
+       RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
+
+
+       //DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutMLMEPacket\n"));
+#if 0 // for debug
+{
+       printk("MLME-Out, C=%d!, D=%d, F=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx);
+
+       //TODO: Need to remove it when formal release
+       PTXINFO_STRUC pTxInfo;
+
+       pTxInfo = (PTXINFO_STRUC)pMLMEContext->TransferBuffer;
+       if (pTxInfo->QSEL != FIFO_EDCA)
+       {
+                       printk("%s(): ====> pTxInfo->QueueSel(%d)!= FIFO_EDCA!!!!\n", __FUNCTION__, pTxInfo->QSEL);
+                       printk("\tMLME_Index=%d!\n", Index);
+                       hex_dump("Wrong QSel Pkt:", (PUCHAR)pMLMEContext->TransferBuffer, pTxInfo->USBDMATxPktLen);
+       }
+}
+#endif
+
+#ifdef RT_BIG_ENDIAN
+       RTMPDescriptorEndianChange((PUCHAR)pMLMEContext->TransferBuffer, TYPE_TXINFO);
+#endif // RT_BIG_ENDIAN //
+
+       // Init Tx context descriptor
+       RTUSBInitTxDesc(pAd, pMLMEContext, MGMTPIPEIDX, (usb_complete_t)RTUSBBulkOutMLMEPacketComplete);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+       //For mgmt urb buffer, because we use sk_buff, so we need to notify the USB controller do dma mapping.
+       pUrb->transfer_dma      = 0;
+       pUrb->transfer_flags &= (~URB_NO_TRANSFER_DMA_MAP);
+#endif
+
+       pUrb = pMLMEContext->pUrb;
+       if((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutMLMEPacket: Submit MLME URB failed %d\n", ret));
+               RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+               pAd->BulkOutPending[MGMTPIPEIDX] = FALSE;
+               pAd->watchDogTxPendingCnt[MGMTPIPEIDX] = 0;
+               pMLMEContext->IRPPending = FALSE;
+               pMLMEContext->bWaitingBulkOut = TRUE;
+               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+
+               return;
+       }
+
+       //DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutMLMEPacket \n"));
+//     printk("<---RTUSBBulkOutMLMEPacket,Cpu=%d!, Dma=%d, SwIdx=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx);
+}
+
+
+VOID RTUSBBulkOutMLMEPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs)
+{
+       PTX_CONTEXT                     pMLMEContext;
+       PRTMP_ADAPTER           pAd;
+       NTSTATUS                        Status;
+       POS_COOKIE                      pObj;
+       int                                     index;
+#if 0 // sample, IRQ LOCK
+       unsigned long           IrqFlags;
+       PNDIS_PACKET            pPacket;
+#endif
+
+
+       //DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutMLMEPacketComplete\n"));
+       pMLMEContext    = (PTX_CONTEXT)pUrb->context;
+       pAd                     = pMLMEContext->pAd;
+       pObj                    = (POS_COOKIE)pAd->OS_Cookie;
+       Status                  = pUrb->status;
+       index                   = pMLMEContext->SelfIdx;
+
+
+#if 0 // sample, IRQ LOCK
+       ASSERT((pAd->MgmtRing.TxDmaIdx == index));
+       //printk("MLME-Done-B: C=%d, D=%d, F=%d, Self=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx, pMLMEContext->SelfIdx);
+
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+
+
+       if (Status != USB_ST_NOERROR)
+       {
+               //Bulk-Out fail status handle
+               if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out MLME Failed, Status=%d!\n", Status));
+                       // TODO: How to handle about the MLMEBulkOut failed issue. Need to resend the mgmt pkt?
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG);
+               }
+       }
+       pAd->BulkOutPending[MGMTPIPEIDX] = FALSE;
+       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+
+       RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags);
+       // Reset MLME context flags
+       pMLMEContext->IRPPending = FALSE;
+       pMLMEContext->InUse = FALSE;
+       pMLMEContext->bWaitingBulkOut = FALSE;
+       pMLMEContext->BulkOutSize = 0;
+
+       pPacket = pAd->MgmtRing.Cell[index].pNdisPacket;
+       pAd->MgmtRing.Cell[index].pNdisPacket = NULL;
+
+       // Increase MgmtRing Index
+       INC_RING_INDEX(pAd->MgmtRing.TxDmaIdx, MGMT_RING_SIZE);
+       pAd->MgmtRing.TxSwFreeIdx++;
+
+       RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags);
+
+       // No-matter success or fail, we free the mgmt packet.
+       if (pPacket)
+               RTMPFreeNdisPacket(pAd, pPacket);
+
+#if 0
+       //Bulk-Out fail status handle
+       if (Status != USB_ST_NOERROR)
+       {
+               if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out MLME Failed, Status=%d!\n", Status));
+                       // TODO: How to handle about the MLMEBulkOut failed issue. Need to reset the endpoint?
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG);
+               }
+       }
+#endif
+
+       //printk("MLME-Done-A: C=%d, D=%d, F=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx);
+
+       pObj->mgmt_dma_done_task.data = (unsigned long)pAd;
+       tasklet_hi_schedule(&pObj->mgmt_dma_done_task);
+
+       //DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutMLMEPacketComplete\n"));
+//     printk("<---RTUSBBulkOutMLMEPacketComplete, Cpu=%d, Dma=%d, SwIdx=%d!\n",
+//                             pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx);
+
+#else
+
+       pObj->mgmt_dma_done_task.data = (unsigned long)pUrb;
+       tasklet_hi_schedule(&pObj->mgmt_dma_done_task);
+#endif
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note: PsPoll use BulkOutPipeId = 0
+
+       ========================================================================
+*/
+VOID   RTUSBBulkOutPsPoll(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       PTX_CONTEXT             pPsPollContext = &(pAd->PsPollContext);
+       PURB                    pUrb;
+       int                             ret = 0;
+       unsigned long   IrqFlags;
+
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags);
+       if ((pAd->BulkOutPending[0] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX))
+       {
+               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+               return;
+       }
+       pAd->BulkOutPending[0] = TRUE;
+       pAd->watchDogTxPendingCnt[0] = 1;
+       pPsPollContext->IRPPending = TRUE;
+       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+
+
+       // Clear PS-Poll bulk flag
+       RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL);
+
+#ifdef RT_BIG_ENDIAN
+       RTMPDescriptorEndianChange((PUCHAR)pPsPollContext->TransferBuffer, TYPE_TXINFO);
+#endif // RT_BIG_ENDIAN //
+
+       // Init Tx context descriptor
+       RTUSBInitTxDesc(pAd, pPsPollContext, MGMTPIPEIDX, (usb_complete_t)RTUSBBulkOutPsPollComplete);
+
+       pUrb = pPsPollContext->pUrb;
+       if((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+       {
+               RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags);
+               pAd->BulkOutPending[0] = FALSE;
+               pAd->watchDogTxPendingCnt[0] = 0;
+               pPsPollContext->IRPPending = FALSE;
+               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+
+               DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutPsPoll: Submit Tx URB failed %d\n", ret));
+               return;
+       }
+
+}
+
+// PS-Poll frame use BulkOutPipeId = 0
+VOID RTUSBBulkOutPsPollComplete(purbb_t pUrb,struct pt_regs *pt_regs)
+{
+       PRTMP_ADAPTER           pAd;
+       PTX_CONTEXT                     pPsPollContext;
+       NTSTATUS                        Status;
+#if 0 // sample, IRQ LOCK
+       unsigned long           IrqFlags;
+#endif
+       POS_COOKIE                      pObj;
+
+
+       pPsPollContext= (PTX_CONTEXT)pUrb->context;
+       pAd = pPsPollContext->pAd;
+       Status = pUrb->status;
+
+#if 0 // sample, IRQ LOCK
+       // Reset PsPoll context flags
+       pPsPollContext->IRPPending      = FALSE;
+       pPsPollContext->InUse           = FALSE;
+
+       if (Status == USB_ST_NOERROR)
+       {
+               // Don't worry about the queue is empty or not, this function will check itself
+               RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+       }
+       else // STATUS_OTHER
+       {
+               if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out PSPoll Failed\n"));
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+               }
+       }
+
+       RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags);
+       pAd->BulkOutPending[0] = FALSE;
+       RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+
+       // Always call Bulk routine, even reset bulk.
+       // The protectioon of rest bulk should be in BulkOut routine
+       RTUSBKickBulkOut(pAd);
+#else
+
+       pObj = (POS_COOKIE) pAd->OS_Cookie;
+       pObj->pspoll_frame_complete_task.data = (unsigned long)pUrb;
+       tasklet_hi_schedule(&pObj->pspoll_frame_complete_task);
+#endif
+}
+
+
+#if 0
+/*
+       ========================================================================
+
+       Routine Description:
+       USB_RxPacket initializes a URB and uses the Rx IRP to submit it
+       to USB. It checks if an Rx Descriptor is available and passes the
+       the coresponding buffer to be filled. If no descriptor is available
+       fails the request. When setting the completion routine we pass our
+       Adapter Object as Context.
+
+       Arguments:
+
+       Return Value:
+               TRUE                    found matched tuple cache
+               FALSE                   no matched found
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTUSBBulkReceive(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       PRX_CONTEXT             pRxContext;
+       PURB                    pUrb;
+       int                             ret = 0;
+       unsigned long   IrqFlags;
+
+
+       /* device had been closed */
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS))
+               return;
+
+       RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+
+       // Last is time point between 2 separate URB.
+       if (pAd->NextRxBulkInPosition == 0)
+       {
+               //pAd->NextRxBulkInIndex = (pAd->NextRxBulkInIndex + 1) % (RX_RING_SIZE);
+               INC_RING_INDEX(pAd->NextRxBulkInIndex, RX_RING_SIZE);
+       }
+       else if ((pAd->NextRxBulkInPosition&0x1ff) != 0)
+       {
+               //pAd->NextRxBulkInIndex = (pAd->NextRxBulkInIndex + 1) % (RX_RING_SIZE);
+               INC_RING_INDEX(pAd->NextRxBulkInIndex, RX_RING_SIZE);
+               DBGPRINT_RAW(RT_DEBUG_TRACE, ("pAd->NextRxBulkInPosition = 0x%lx.  End of URB.\n", pAd->NextRxBulkInPosition ));
+               pAd->NextRxBulkInPosition = 0;
+       }
+
+       if (pAd->NextRxBulkInPosition == MAX_RXBULK_SIZE)
+               pAd->NextRxBulkInPosition = 0;
+
+       pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]);
+
+       // TODO: Why need to check if pRxContext->InUsed == TRUE?
+       //if ((pRxContext->InUse == TRUE) || (pRxContext->Readable == TRUE))
+       if ((pRxContext->InUse == FALSE) && (pRxContext->Readable == TRUE))
+       {
+               DBGPRINT_RAW(RT_DEBUG_TRACE, ("pRxContext[%d] InUse = %d.pRxContext->Readable = %d.  Return.\n", pAd->NextRxBulkInIndex,pRxContext->InUse, pRxContext->Readable ));
+               RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+               // read RxContext, Since not
+#ifdef CONFIG_STA_SUPPORT
+               STARxDoneInterruptHandle(pAd, TRUE);
+#endif // CONFIG_STA_SUPPORT //
+
+               //return;
+       }
+       pRxContext->InUse = TRUE;
+       pRxContext->IRPPending= TRUE;
+
+       RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+       // Init Rx context descriptor
+       NdisZeroMemory(pRxContext->TransferBuffer, BUFFER_SIZE);
+       RTUSBInitRxDesc(pAd, pRxContext);
+
+       pUrb = pRxContext->pUrb;
+       if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkReceive: Submit Rx URB failed %d\n", ret));
+               return;
+       }
+       else // success
+       {
+               NdisInterlockedIncrement(&pAd->PendingRx);
+               pAd->BulkInReq++;
+       }
+
+       // read RxContext, Since not
+#ifdef CONFIG_STA_SUPPORT
+       STARxDoneInterruptHandle(pAd, FALSE);
+#endif // CONFIG_STA_SUPPORT //
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               This routine process Rx Irp and call rx complete function.
+
+       Arguments:
+               DeviceObject    Pointer to the device object for next lower
+                                               device. DeviceObject passed in here belongs to
+                                               the next lower driver in the stack because we
+                                               were invoked via IoCallDriver in USB_RxPacket
+                                               AND it is not OUR device object
+         Irp                           Ptr to completed IRP
+         Context                       Ptr to our Adapter object (context specified
+                                               in IoSetCompletionRoutine
+
+       Return Value:
+               Always returns STATUS_MORE_PROCESSING_REQUIRED
+
+       Note:
+               Always returns STATUS_MORE_PROCESSING_REQUIRED
+       ========================================================================
+*/
+VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs)
+{
+#if 0
+       PRX_CONTEXT                     pRxContext;
+       PRTMP_ADAPTER           pAd;
+       NTSTATUS                        Status;
+//     POS_COOKIE                      pObj;
+
+       pRxContext      = (PRX_CONTEXT)pUrb->context;
+       pAd             = pRxContext->pAd;
+//     pObj            = (POS_COOKIE) pAd->OS_Cookie;
+
+
+       Status = pUrb->status;
+       //pRxContext->pIrp = NULL;
+
+       pRxContext->InUse = FALSE;
+       pRxContext->IRPPending = FALSE;
+
+       if (Status == USB_ST_NOERROR)
+       {
+               pAd->BulkInComplete++;
+               pRxContext->Readable = TRUE;
+               pAd->NextRxBulkInPosition = 0;
+
+       }
+       else     // STATUS_OTHER
+       {
+               pAd->BulkInCompleteFail++;
+               // Still read this packet although it may comtain wrong bytes.
+               pRxContext->Readable = FALSE;
+               // Parsing all packets. because after reset, the index will reset to all zero.
+
+               if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+               {
+
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk In Failed. Status = %d\n", Status));
+                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("==>NextRxBulkInIndex=0x%x, NextRxBulkInReadIndex=0x%x, TransferBufferLength= 0x%x\n",
+                               pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pRxContext->pUrb->actual_length));
+
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0);
+               }
+               //pUrb = NULL;
+       }
+
+       if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+               (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET)) &&
+//             (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) &&
+               (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) &&
+               (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+               (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+       {
+               RTUSBBulkReceive(pAd);
+#if 0
+#if 1
+               STARxDoneInterruptHandle(pAd, FALSE);
+#else
+               pObj->rx_bh.data = (unsigned long)pUrb;
+               tasklet_schedule(&pObj->rx_bh);
+#endif
+#endif
+       }
+
+       // Call RxPacket to process packet and return the status
+       NdisInterlockedDecrement(&pAd->PendingRx);
+#else
+
+
+       // use a receive tasklet to handle received packets;
+       // or sometimes hardware IRQ will be disabled here, so we can not
+       // use spin_lock_bh()/spin_unlock_bh() after IRQ is disabled. :<
+       PRX_CONTEXT             pRxContext;
+       PRTMP_ADAPTER   pAd;
+       POS_COOKIE              pObj;
+
+
+       pRxContext      = (PRX_CONTEXT)pUrb->context;
+       pAd             = pRxContext->pAd;
+       pObj            = (POS_COOKIE) pAd->OS_Cookie;
+
+       pObj->rx_done_task.data = (unsigned long)pUrb;
+       tasklet_hi_schedule(&pObj->rx_done_task);
+#endif
+}
+
+#else
+
+VOID DoBulkIn(IN RTMP_ADAPTER *pAd)
+{
+       PRX_CONTEXT             pRxContext;
+       PURB                    pUrb;
+       int                             ret = 0;
+       unsigned long   IrqFlags;
+
+       RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+       pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]);
+       if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE))
+       {
+               RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+               return;
+       }
+       pRxContext->InUse = TRUE;
+       pRxContext->IRPPending = TRUE;
+       pAd->PendingRx++;
+       pAd->BulkInReq++;
+       RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+       // Init Rx context descriptor
+       NdisZeroMemory(pRxContext->TransferBuffer, pRxContext->BulkInOffset);
+       RTUSBInitRxDesc(pAd, pRxContext);
+
+       pUrb = pRxContext->pUrb;
+       if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+       {       // fail
+
+               RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+               pRxContext->InUse = FALSE;
+               pRxContext->IRPPending = FALSE;
+               pAd->PendingRx--;
+               pAd->BulkInReq--;
+               RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+               DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkReceive: Submit Rx URB failed %d\n", ret));
+       }
+       else
+       {       // success
+#if 0
+               RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+               pRxContext->IRPPending = TRUE;
+               //NdisInterlockedIncrement(&pAd->PendingRx);
+               pAd->PendingRx++;
+               RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+               pAd->BulkInReq++;
+#endif
+               ASSERT((pRxContext->InUse == pRxContext->IRPPending));
+               //printk("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex);
+       }
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+       USB_RxPacket initializes a URB and uses the Rx IRP to submit it
+       to USB. It checks if an Rx Descriptor is available and passes the
+       the coresponding buffer to be filled. If no descriptor is available
+       fails the request. When setting the completion routine we pass our
+       Adapter Object as Context.
+
+       Arguments:
+
+       Return Value:
+               TRUE                    found matched tuple cache
+               FALSE                   no matched found
+
+       Note:
+
+       ========================================================================
+*/
+#define fRTMP_ADAPTER_NEED_STOP_RX             \
+               (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \
+                fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | \
+                fRTMP_ADAPTER_REMOVE_IN_PROGRESS | fRTMP_ADAPTER_BULKIN_RESET)
+
+#define fRTMP_ADAPTER_NEED_STOP_HANDLE_RX      \
+               (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \
+                fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | \
+                fRTMP_ADAPTER_REMOVE_IN_PROGRESS)
+
+VOID   RTUSBBulkReceive(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       PRX_CONTEXT             pRxContext;
+       unsigned long   IrqFlags;
+
+
+       /* sanity check */
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_HANDLE_RX))
+               return;
+
+       while(1)
+       {
+
+               RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+               pRxContext = &(pAd->RxContext[pAd->NextRxBulkInReadIndex]);
+               if (((pRxContext->InUse == FALSE) && (pRxContext->Readable == TRUE)) &&
+                       (pRxContext->bRxHandling == FALSE))
+               {
+                       pRxContext->bRxHandling = TRUE;
+                       RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+                       // read RxContext, Since not
+#ifdef CONFIG_STA_SUPPORT
+                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                               STARxDoneInterruptHandle(pAd, TRUE);
+#endif // CONFIG_STA_SUPPORT //
+
+                       // Finish to handle this bulkIn buffer.
+                       RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+                       pRxContext->BulkInOffset = 0;
+                       pRxContext->Readable = FALSE;
+                       pRxContext->bRxHandling = FALSE;
+                       pAd->ReadPosition = 0;
+                       pAd->TransferBufferLength = 0;
+                       INC_RING_INDEX(pAd->NextRxBulkInReadIndex, RX_RING_SIZE);
+                       RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+               }
+               else
+               {
+                       RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+                       break;
+               }
+       }
+
+       if (!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_RX)))
+               DoBulkIn(pAd);
+
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               This routine process Rx Irp and call rx complete function.
+
+       Arguments:
+               DeviceObject    Pointer to the device object for next lower
+                                               device. DeviceObject passed in here belongs to
+                                               the next lower driver in the stack because we
+                                               were invoked via IoCallDriver in USB_RxPacket
+                                               AND it is not OUR device object
+         Irp                           Ptr to completed IRP
+         Context                       Ptr to our Adapter object (context specified
+                                               in IoSetCompletionRoutine
+
+       Return Value:
+               Always returns STATUS_MORE_PROCESSING_REQUIRED
+
+       Note:
+               Always returns STATUS_MORE_PROCESSING_REQUIRED
+       ========================================================================
+*/
+VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs)
+{
+       // use a receive tasklet to handle received packets;
+       // or sometimes hardware IRQ will be disabled here, so we can not
+       // use spin_lock_bh()/spin_unlock_bh() after IRQ is disabled. :<
+       PRX_CONTEXT             pRxContext;
+       PRTMP_ADAPTER   pAd;
+       POS_COOKIE              pObj;
+
+
+       pRxContext      = (PRX_CONTEXT)pUrb->context;
+       pAd             = pRxContext->pAd;
+       pObj            = (POS_COOKIE) pAd->OS_Cookie;
+
+       pObj->rx_done_task.data = (unsigned long)pUrb;
+       tasklet_hi_schedule(&pObj->rx_done_task);
+
+}
+
+#endif
+
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTUSBKickBulkOut(
+       IN      PRTMP_ADAPTER pAd)
+{
+       // BulkIn Reset will reset whole USB PHY. So we need to make sure fRTMP_ADAPTER_BULKIN_RESET not flaged.
+       if (!RTMP_TEST_FLAG(pAd ,fRTMP_ADAPTER_NEED_STOP_TX)
+#ifdef RALINK_ATE
+               && !(ATE_ON(pAd))
+#endif // RALINK_ATE //
+               )
+       {
+#if 0  // not used now in RT28xx, but may used latter.
+               // 1. Data Fragment has highest priority
+               if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_FRAG))
+               {
+                       if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+                               (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+                               ))
+                       {
+                               RTUSBBulkOutDataPacket(pAd, 0, pAd->NextBulkOutIndex[0]);
+                       }
+               }
+               if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_FRAG_2))
+               {
+                       if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+                               (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+                               ))
+                       {
+                               RTUSBBulkOutDataPacket(pAd, 1, pAd->NextBulkOutIndex[1]);
+                       }
+               }
+               if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_FRAG_3))
+               {
+                       if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+                               (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+                               ))
+                       {
+                               RTUSBBulkOutDataPacket(pAd, 2, pAd->NextBulkOutIndex[2]);
+                       }
+               }
+               if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_FRAG_4))
+               {
+                       if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+                               (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+                               ))
+                       {
+                               RTUSBBulkOutDataPacket(pAd, 3, pAd->NextBulkOutIndex[3]);
+                       }
+               }
+#endif
+
+               // 2. PS-Poll frame is next
+               if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL))
+               {
+                       RTUSBBulkOutPsPoll(pAd);
+               }
+
+               // 5. Mlme frame is next
+               else if ((RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME)) &&
+                                (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE))
+               {
+                       RTUSBBulkOutMLMEPacket(pAd, pAd->MgmtRing.TxDmaIdx);
+               }
+
+               // 6. Data frame normal is next
+               if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL))
+               {
+                       if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+                               (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+                               ))
+                       {
+                               RTUSBBulkOutDataPacket(pAd, 0, pAd->NextBulkOutIndex[0]);
+                       }
+               }
+               if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_2))
+               {
+                       if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+                               (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+                               ))
+                       {
+                               RTUSBBulkOutDataPacket(pAd, 1, pAd->NextBulkOutIndex[1]);
+                       }
+               }
+               if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_3))
+               {
+                       if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+                               (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+                               ))
+                       {
+                               RTUSBBulkOutDataPacket(pAd, 2, pAd->NextBulkOutIndex[2]);
+                       }
+               }
+               if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_4))
+               {
+                       if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+                               (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+                               ))
+                       {
+                               RTUSBBulkOutDataPacket(pAd, 3, pAd->NextBulkOutIndex[3]);
+                       }
+               }
+
+               // 7. Null frame is the last
+               else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL))
+               {
+                       if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+                       {
+                               RTUSBBulkOutNullFrame(pAd);
+                       }
+               }
+
+               // 8. No data avaliable
+               else
+               {
+
+               }
+       }
+#ifdef RALINK_ATE
+       /* If the mode is in ATE mode. */
+       else if((ATE_ON(pAd)) &&
+               !RTMP_TEST_FLAG(pAd ,fRTMP_ADAPTER_NEED_STOP_TX))// PETER : watch out !
+       {
+               if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE))
+               {
+                       ATE_RTUSBBulkOutDataPacket(pAd, 0);
+               }
+       }
+#endif // RALINK_ATE //
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+       Call from Reset action after BulkOut failed.
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTUSBCleanUpDataBulkOutQueue(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       UCHAR                   Idx;
+       PHT_TX_CONTEXT  pTxContext;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpDataBulkOutQueue\n"));
+
+       for (Idx = 0; Idx < 4; Idx++)
+       {
+               pTxContext = &pAd->TxContext[Idx];
+
+               pTxContext->CurWritePosition = pTxContext->NextBulkOutPosition;
+               pTxContext->LastOne = FALSE;
+               NdisAcquireSpinLock(&pAd->BulkOutLock[Idx]);
+               pAd->BulkOutPending[Idx] = FALSE;
+               NdisReleaseSpinLock(&pAd->BulkOutLock[Idx]);
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<---CleanUpDataBulkOutQueue\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTUSBCleanUpMLMEBulkOutQueue(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpMLMEBulkOutQueue\n"));
+
+#if 0  // Do nothing!
+       NdisAcquireSpinLock(&pAd->MLMEBulkOutLock);
+       while (pAd->PrioRingTxCnt > 0)
+       {
+               pAd->MLMEContext[pAd->PrioRingFirstIndex].InUse = FALSE;
+
+               pAd->PrioRingFirstIndex++;
+               if (pAd->PrioRingFirstIndex >= MGMT_RING_SIZE)
+               {
+                       pAd->PrioRingFirstIndex = 0;
+               }
+
+               pAd->PrioRingTxCnt--;
+       }
+       NdisReleaseSpinLock(&pAd->MLMEBulkOutLock);
+#endif
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<---CleanUpMLMEBulkOutQueue\n"));
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTUSBCancelPendingIRPs(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       RTUSBCancelPendingBulkInIRP(pAd);
+       RTUSBCancelPendingBulkOutIRP(pAd);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTUSBCancelPendingBulkInIRP(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       PRX_CONTEXT             pRxContext;
+       UINT                    i;
+
+       DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->RTUSBCancelPendingBulkInIRP\n"));
+       for ( i = 0; i < (RX_RING_SIZE); i++)
+       {
+               pRxContext = &(pAd->RxContext[i]);
+               if(pRxContext->IRPPending == TRUE)
+               {
+                       RTUSB_UNLINK_URB(pRxContext->pUrb);
+                       pRxContext->IRPPending = FALSE;
+                       pRxContext->InUse = FALSE;
+                       //NdisInterlockedDecrement(&pAd->PendingRx);
+                       //pAd->PendingRx--;
+               }
+       }
+       DBGPRINT_RAW(RT_DEBUG_TRACE, ("<---RTUSBCancelPendingBulkInIRP\n"));
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTUSBCancelPendingBulkOutIRP(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       PHT_TX_CONTEXT          pHTTXContext;
+       PTX_CONTEXT                     pMLMEContext;
+       PTX_CONTEXT                     pBeaconContext;
+       PTX_CONTEXT                     pNullContext;
+       PTX_CONTEXT                     pPsPollContext;
+       PTX_CONTEXT                     pRTSContext;
+       UINT                            i, Idx;
+//     unsigned int            IrqFlags;
+//     NDIS_SPIN_LOCK          *pLock;
+//     BOOLEAN                         *pPending;
+
+
+//     pLock = &pAd->BulkOutLock[MGMTPIPEIDX];
+//     pPending = &pAd->BulkOutPending[MGMTPIPEIDX];
+
+       for (Idx = 0; Idx < 4; Idx++)
+       {
+               pHTTXContext = &(pAd->TxContext[Idx]);
+
+               if (pHTTXContext->IRPPending == TRUE)
+               {
+
+                       // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself
+                       // remove it from the HeadPendingSendList and NULL out HeadPendingSendList
+                       //      when the last IRP on the list has been  cancelled; that's how we exit this loop
+                       //
+
+                       RTUSB_UNLINK_URB(pHTTXContext->pUrb);
+
+                       // Sleep 200 microseconds to give cancellation time to work
+                       RTMPusecDelay(200);
+               }
+
+#ifdef RALINK_ATE
+               pHTTXContext->bCopySavePad = 0;
+               pHTTXContext->CurWritePosition = 0;
+               pHTTXContext->CurWriteRealPos = 0;
+               pHTTXContext->bCurWriting = FALSE;
+               pHTTXContext->NextBulkOutPosition = 0;
+               pHTTXContext->ENextBulkOutPosition = 0;
+#endif // RALINK_ATE //
+               pAd->BulkOutPending[Idx] = FALSE;
+       }
+
+       //RTMP_IRQ_LOCK(pLock, IrqFlags);
+       for (i = 0; i < MGMT_RING_SIZE; i++)
+       {
+               pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa;
+               if(pMLMEContext && (pMLMEContext->IRPPending == TRUE))
+               {
+
+                       // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself
+                       // remove it from the HeadPendingSendList and NULL out HeadPendingSendList
+                       //      when the last IRP on the list has been  cancelled; that's how we exit this loop
+                       //
+
+                       RTUSB_UNLINK_URB(pMLMEContext->pUrb);
+                       pMLMEContext->IRPPending = FALSE;
+
+                       // Sleep 200 microsecs to give cancellation time to work
+                       RTMPusecDelay(200);
+               }
+       }
+       pAd->BulkOutPending[MGMTPIPEIDX] = FALSE;
+       //RTMP_IRQ_UNLOCK(pLock, IrqFlags);
+
+
+       for (i = 0; i < BEACON_RING_SIZE; i++)
+       {
+               pBeaconContext = &(pAd->BeaconContext[i]);
+
+               if(pBeaconContext->IRPPending == TRUE)
+               {
+
+                       // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself
+                       // remove it from the HeadPendingSendList and NULL out HeadPendingSendList
+                       //      when the last IRP on the list has been  cancelled; that's how we exit this loop
+                       //
+
+                       RTUSB_UNLINK_URB(pBeaconContext->pUrb);
+
+                       // Sleep 200 microsecs to give cancellation time to work
+                       RTMPusecDelay(200);
+               }
+       }
+
+       pNullContext = &(pAd->NullContext);
+       if (pNullContext->IRPPending == TRUE)
+               RTUSB_UNLINK_URB(pNullContext->pUrb);
+
+       pRTSContext = &(pAd->RTSContext);
+       if (pRTSContext->IRPPending == TRUE)
+               RTUSB_UNLINK_URB(pRTSContext->pUrb);
+
+       pPsPollContext = &(pAd->PsPollContext);
+       if (pPsPollContext->IRPPending == TRUE)
+               RTUSB_UNLINK_URB(pPsPollContext->pUrb);
+
+       for (Idx = 0; Idx < 4; Idx++)
+       {
+               NdisAcquireSpinLock(&pAd->BulkOutLock[Idx]);
+               pAd->BulkOutPending[Idx] = FALSE;
+               NdisReleaseSpinLock(&pAd->BulkOutLock[Idx]);
+       }
+}
+
diff --git a/drivers/staging/rt2870/common/rtusb_data.c b/drivers/staging/rt2870/common/rtusb_data.c
new file mode 100644 (file)
index 0000000..5a0d783
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       rtusb_data.c
+
+       Abstract:
+       Ralink USB driver Tx/Rx functions.
+
+       Revision History:
+       Who         When          What
+       --------    ----------    ----------------------------------------------
+       Jan            03-25-2006    created
+
+*/
+#include "../rt_config.h"
+
+extern  UCHAR Phy11BGNextRateUpward[]; // defined in mlme.c
+extern UCHAR   EpToQueue[];
+
+VOID REPORT_AMSDU_FRAMES_TO_LLC(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize)
+{
+       PNDIS_PACKET    pPacket;
+       UINT                    nMSDU;
+       struct                  sk_buff *pSkb;
+
+       nMSDU = 0;
+       /* allocate a rx packet */
+       pSkb = dev_alloc_skb(RX_BUFFER_AGGRESIZE);
+       pPacket = (PNDIS_PACKET)OSPKT_TO_RTPKT(pSkb);
+       if (pSkb)
+       {
+
+               /* convert 802.11 to 802.3 packet */
+               pSkb->dev = get_netdev_from_bssid(pAd, BSS0);
+               RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
+               deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("Can't allocate skb\n"));
+       }
+}
+
+NDIS_STATUS    RTUSBFreeDescriptorRequest(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   BulkOutPipeId,
+       IN      UINT32                  NumberRequired)
+{
+//     UCHAR                   FreeNumber = 0;
+//     UINT                    Index;
+       NDIS_STATUS             Status = NDIS_STATUS_FAILURE;
+       unsigned long   IrqFlags;
+       HT_TX_CONTEXT   *pHTTXContext;
+
+
+       pHTTXContext = &pAd->TxContext[BulkOutPipeId];
+       RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+       if ((pHTTXContext->CurWritePosition < pHTTXContext->NextBulkOutPosition) && ((pHTTXContext->CurWritePosition + NumberRequired + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition))
+       {
+
+               RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+       }
+       else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < (NumberRequired + LOCAL_TXBUF_SIZE)))
+       {
+               RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+       }
+       else if (pHTTXContext->bCurWriting == TRUE)
+       {
+               DBGPRINT(RT_DEBUG_TRACE,("RTUSBFreeD c3 --> QueIdx=%d, CWPos=%ld, NBOutPos=%ld!\n", BulkOutPipeId, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition));
+               RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+       }
+       else
+       {
+               Status = NDIS_STATUS_SUCCESS;
+       }
+       RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+
+
+       return (Status);
+}
+
+NDIS_STATUS RTUSBFreeDescriptorRelease(
+       IN RTMP_ADAPTER *pAd,
+       IN UCHAR                BulkOutPipeId)
+{
+       unsigned long   IrqFlags;
+       HT_TX_CONTEXT   *pHTTXContext;
+
+       pHTTXContext = &pAd->TxContext[BulkOutPipeId];
+       RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+       pHTTXContext->bCurWriting = FALSE;
+       RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+
+       return (NDIS_STATUS_SUCCESS);
+}
+
+
+BOOLEAN        RTUSBNeedQueueBackForAgg(
+       IN RTMP_ADAPTER *pAd,
+       IN UCHAR                BulkOutPipeId)
+{
+       unsigned long   IrqFlags;
+       HT_TX_CONTEXT   *pHTTXContext;
+       BOOLEAN                 needQueBack = FALSE;
+
+       pHTTXContext = &pAd->TxContext[BulkOutPipeId];
+
+       RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+       if ((pHTTXContext->IRPPending == TRUE)  /*&& (pAd->TxSwQueue[BulkOutPipeId].Number == 0) */)
+       {
+#if 0
+               if ((pHTTXContext->CurWritePosition <= 8) &&
+                       (pHTTXContext->NextBulkOutPosition > 8 && (pHTTXContext->NextBulkOutPosition+MAX_AGGREGATION_SIZE) < MAX_TXBULK_LIMIT))
+               {
+                       needQueBack = TRUE;
+               }
+               else if ((pHTTXContext->CurWritePosition < pHTTXContext->NextBulkOutPosition) &&
+                                ((pHTTXContext->NextBulkOutPosition + MAX_AGGREGATION_SIZE) < MAX_TXBULK_LIMIT))
+               {
+                       needQueBack = TRUE;
+               }
+#else
+               if ((pHTTXContext->CurWritePosition < pHTTXContext->ENextBulkOutPosition) &&
+                       (((pHTTXContext->ENextBulkOutPosition+MAX_AGGREGATION_SIZE) < MAX_TXBULK_LIMIT) || (pHTTXContext->CurWritePosition > MAX_AGGREGATION_SIZE)))
+               {
+                       needQueBack = TRUE;
+               }
+#endif
+               else if ((pHTTXContext->CurWritePosition > pHTTXContext->ENextBulkOutPosition) &&
+                                ((pHTTXContext->ENextBulkOutPosition + MAX_AGGREGATION_SIZE) < pHTTXContext->CurWritePosition))
+               {
+                       needQueBack = TRUE;
+               }
+       }
+       RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+
+       return needQueBack;
+
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTUSBRejectPendingPackets(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       UCHAR                   Index;
+       PQUEUE_ENTRY    pEntry;
+       PNDIS_PACKET    pPacket;
+       PQUEUE_HEADER   pQueue;
+
+
+       for (Index = 0; Index < 4; Index++)
+       {
+               NdisAcquireSpinLock(&pAd->TxSwQueueLock[Index]);
+               while (pAd->TxSwQueue[Index].Head != NULL)
+               {
+                       pQueue = (PQUEUE_HEADER) &(pAd->TxSwQueue[Index]);
+                       pEntry = RemoveHeadQueue(pQueue);
+                       pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+                       RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+               }
+               NdisReleaseSpinLock(&pAd->TxSwQueueLock[Index]);
+
+       }
+
+}
+
+VOID RTMPWriteTxInfo(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTXINFO_STRUC   pTxInfo,
+       IN        USHORT                USBDMApktLen,
+       IN        BOOLEAN               bWiv,
+       IN        UCHAR                 QueueSel,
+       IN        UCHAR                 NextValid,
+       IN        UCHAR                 TxBurst)
+{
+       pTxInfo->USBDMATxPktLen = USBDMApktLen;
+       pTxInfo->QSEL = QueueSel;
+       if (QueueSel != FIFO_EDCA)
+               DBGPRINT(RT_DEBUG_TRACE, ("====> QueueSel != FIFO_EDCA<============\n"));
+       pTxInfo->USBDMANextVLD = FALSE; //NextValid;  // Need to check with Jan about this.
+       pTxInfo->USBDMATxburst = TxBurst;
+       pTxInfo->WIV = bWiv;
+       pTxInfo->SwUseLastRound = 0;
+       pTxInfo->rsv = 0;
+       pTxInfo->rsv2 = 0;
+}
+
diff --git a/drivers/staging/rt2870/common/rtusb_io.c b/drivers/staging/rt2870/common/rtusb_io.c
new file mode 100644 (file)
index 0000000..6db443e
--- /dev/null
@@ -0,0 +1,2006 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       rtusb_io.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When        What
+       --------        ----------  ----------------------------------------------
+       Name            Date        Modification logs
+       Paul Lin    06-25-2004  created
+*/
+
+#include "../rt_config.h"
+
+
+/*
+       ========================================================================
+
+       Routine Description: NIC initialization complete
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+
+NTSTATUS       RTUSBFirmwareRun(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       NTSTATUS        Status;
+
+       Status = RTUSB_VendorRequest(
+               pAd,
+               USBD_TRANSFER_DIRECTION_OUT,
+               DEVICE_VENDOR_REQUEST_OUT,
+               0x01,
+               0x8,
+               0,
+               NULL,
+               0);
+
+       return Status;
+}
+
+
+
+/*
+       ========================================================================
+
+       Routine Description: Write Firmware to NIC.
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS RTUSBFirmwareWrite(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR               pFwImage,
+       IN ULONG                FwLen)
+{
+       UINT32          MacReg;
+       NTSTATUS        Status;
+//     ULONG           i;
+       USHORT          writeLen;
+
+       Status = RTUSBReadMACRegister(pAd, MAC_CSR0, &MacReg);
+
+
+       writeLen = FwLen;
+       RTUSBMultiWrite(pAd, FIRMWARE_IMAGE_BASE, pFwImage, writeLen);
+
+       Status = RTUSBWriteMACRegister(pAd, 0x7014, 0xffffffff);
+       Status = RTUSBWriteMACRegister(pAd, 0x701c, 0xffffffff);
+       Status = RTUSBFirmwareRun(pAd);
+
+       return Status;
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description: Get current firmware operation mode (Return Value)
+
+       Arguments:
+
+       Return Value:
+               0 or 1 = Downloaded by host driver
+               others = Driver doesn't download firmware
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSBFirmwareOpmode(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUINT32                 pValue)
+{
+       NTSTATUS        Status;
+
+       Status = RTUSB_VendorRequest(
+               pAd,
+               (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK),
+               DEVICE_VENDOR_REQUEST_IN,
+               0x1,
+               0x11,
+               0,
+               pValue,
+               4);
+       return Status;
+}
+NTSTATUS       RTUSBVenderReset(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       NTSTATUS        Status;
+       DBGPRINT_RAW(RT_DEBUG_ERROR, ("-->RTUSBVenderReset\n"));
+       Status = RTUSB_VendorRequest(
+               pAd,
+               USBD_TRANSFER_DIRECTION_OUT,
+               DEVICE_VENDOR_REQUEST_OUT,
+               0x01,
+               0x1,
+               0,
+               NULL,
+               0);
+
+       DBGPRINT_RAW(RT_DEBUG_ERROR, ("<--RTUSBVenderReset\n"));
+       return Status;
+}
+/*
+       ========================================================================
+
+       Routine Description: Read various length data from RT2573
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSBMultiRead(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       OUT     PUCHAR                  pData,
+       IN      USHORT                  length)
+{
+       NTSTATUS        Status;
+
+       Status = RTUSB_VendorRequest(
+               pAd,
+               (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK),
+               DEVICE_VENDOR_REQUEST_IN,
+               0x7,
+               0,
+               Offset,
+               pData,
+               length);
+
+       return Status;
+}
+
+/*
+       ========================================================================
+
+       Routine Description: Write various length data to RT2573
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSBMultiWrite_OneByte(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       IN      PUCHAR                  pData)
+{
+       NTSTATUS        Status;
+
+       // TODO: In 2870, use this funciton carefully cause it's not stable.
+       Status = RTUSB_VendorRequest(
+               pAd,
+               USBD_TRANSFER_DIRECTION_OUT,
+               DEVICE_VENDOR_REQUEST_OUT,
+               0x6,
+               0,
+               Offset,
+               pData,
+               1);
+
+       return Status;
+}
+
+NTSTATUS       RTUSBMultiWrite(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       IN      PUCHAR                  pData,
+       IN      USHORT                  length)
+{
+       NTSTATUS        Status;
+
+
+        USHORT          index = 0,Value;
+        PUCHAR          pSrc = pData;
+        USHORT          resude = 0;
+
+        resude = length % 2;
+               length  += resude;
+               do
+               {
+                       Value =(USHORT)( *pSrc  | (*(pSrc + 1) << 8));
+               Status = RTUSBSingleWrite(pAd,Offset + index,Value);
+            index +=2;
+            length -= 2;
+            pSrc = pSrc + 2;
+        }while(length > 0);
+
+       return Status;
+}
+
+
+NTSTATUS RTUSBSingleWrite(
+       IN      RTMP_ADAPTER    *pAd,
+       IN      USHORT                  Offset,
+       IN      USHORT                  Value)
+{
+       NTSTATUS        Status;
+
+       Status = RTUSB_VendorRequest(
+               pAd,
+               USBD_TRANSFER_DIRECTION_OUT,
+               DEVICE_VENDOR_REQUEST_OUT,
+               0x2,
+               Value,
+               Offset,
+               NULL,
+               0);
+
+       return Status;
+
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description: Read 32-bit MAC register
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSBReadMACRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       OUT     PUINT32                 pValue)
+{
+       NTSTATUS        Status;
+       UINT32          localVal;
+
+       Status = RTUSB_VendorRequest(
+               pAd,
+               (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK),
+               DEVICE_VENDOR_REQUEST_IN,
+               0x7,
+               0,
+               Offset,
+               &localVal,
+               4);
+
+       *pValue = le2cpu32(localVal);
+
+
+       if (Status < 0)
+               *pValue = 0xffffffff;
+
+       return Status;
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description: Write 32-bit MAC register
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSBWriteMACRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       IN      UINT32                  Value)
+{
+       NTSTATUS        Status;
+       UINT32          localVal;
+
+       localVal = Value;
+
+       Status = RTUSBSingleWrite(pAd, Offset, (USHORT)(localVal & 0xffff));
+       Status = RTUSBSingleWrite(pAd, Offset + 2, (USHORT)((localVal & 0xffff0000) >> 16));
+
+       return Status;
+}
+
+
+
+#if 1
+/*
+       ========================================================================
+
+       Routine Description: Read 8-bit BBP register
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSBReadBBPRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Id,
+       IN      PUCHAR                  pValue)
+{
+       BBP_CSR_CFG_STRUC       BbpCsr;
+       UINT                    i = 0;
+       NTSTATUS                status;
+
+       // Verify the busy condition
+       do
+       {
+               status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word);
+               if(status >= 0)
+               {
+               if (!(BbpCsr.field.Busy == BUSY))
+                       break;
+               }
+               printk("RTUSBReadBBPRegister(BBP_CSR_CFG_1):retry count=%d!\n", i);
+               i++;
+       }
+       while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
+
+       if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+       {
+               //
+               // Read failed then Return Default value.
+               //
+               *pValue = pAd->BbpWriteLatch[Id];
+
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
+               return STATUS_UNSUCCESSFUL;
+       }
+
+       // Prepare for write material
+       BbpCsr.word                             = 0;
+       BbpCsr.field.fRead                      = 1;
+       BbpCsr.field.Busy                       = 1;
+       BbpCsr.field.RegNum             = Id;
+       RTUSBWriteMACRegister(pAd, BBP_CSR_CFG, BbpCsr.word);
+
+       i = 0;
+       // Verify the busy condition
+       do
+       {
+               status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word);
+               if (status >= 0)
+               {
+               if (!(BbpCsr.field.Busy == BUSY))
+               {
+                       *pValue = (UCHAR)BbpCsr.field.Value;
+                       break;
+               }
+               }
+               printk("RTUSBReadBBPRegister(BBP_CSR_CFG_2):retry count=%d!\n", i);
+               i++;
+       }
+       while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
+
+       if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+       {
+               //
+               // Read failed then Return Default value.
+               //
+               *pValue = pAd->BbpWriteLatch[Id];
+
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
+               return STATUS_UNSUCCESSFUL;
+       }
+
+       return STATUS_SUCCESS;
+}
+#else
+/*
+       ========================================================================
+
+       Routine Description: Read 8-bit BBP register via firmware
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSBReadBBPRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Id,
+       IN      PUCHAR                  pValue)
+{
+       BBP_CSR_CFG_STRUC       BbpCsr;
+       int                                     i, k;
+       for (i=0; i<MAX_BUSY_COUNT; i++)
+       {
+               RTUSBReadMACRegister(pAd, H2M_BBP_AGENT, &BbpCsr.word);
+               if (BbpCsr.field.Busy == BUSY)
+               {
+                       continue;
+               }
+               BbpCsr.word = 0;
+               BbpCsr.field.fRead = 1;
+               BbpCsr.field.BBP_RW_MODE = 1;
+               BbpCsr.field.Busy = 1;
+               BbpCsr.field.RegNum = Id;
+               RTUSBWriteMACRegister(pAd, H2M_BBP_AGENT, BbpCsr.word);
+               AsicSendCommandToMcu(pAd, 0x80, 0xff, 0x0, 0x0);
+               for (k=0; k<MAX_BUSY_COUNT; k++)
+               {
+                       RTUSBReadMACRegister(pAd, H2M_BBP_AGENT, &BbpCsr.word);
+                       if (BbpCsr.field.Busy == IDLE)
+                               break;
+               }
+               if ((BbpCsr.field.Busy == IDLE) &&
+                       (BbpCsr.field.RegNum == Id))
+               {
+                       *pValue = (UCHAR)BbpCsr.field.Value;
+                       break;
+               }
+       }
+       if (BbpCsr.field.Busy == BUSY)
+       {
+               DBGPRINT_ERR(("BBP read R%d=0x%x fail\n", Id, BbpCsr.word));
+               *pValue = pAd->BbpWriteLatch[Id];
+               return STATUS_UNSUCCESSFUL;
+       }
+       return STATUS_SUCCESS;
+}
+#endif
+
+#if 1
+/*
+       ========================================================================
+
+       Routine Description: Write 8-bit BBP register
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSBWriteBBPRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Id,
+       IN      UCHAR                   Value)
+{
+       BBP_CSR_CFG_STRUC       BbpCsr;
+       UINT                    i = 0;
+       NTSTATUS                status;
+       // Verify the busy condition
+       do
+       {
+               status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word);
+               if (status >= 0)
+               {
+               if (!(BbpCsr.field.Busy == BUSY))
+                       break;
+               }
+               printk("RTUSBWriteBBPRegister(BBP_CSR_CFG):retry count=%d!\n", i);
+               i++;
+       }
+       while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
+
+       if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+       {
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
+               return STATUS_UNSUCCESSFUL;
+       }
+
+       // Prepare for write material
+       BbpCsr.word                             = 0;
+       BbpCsr.field.fRead                      = 0;
+       BbpCsr.field.Value                      = Value;
+       BbpCsr.field.Busy                       = 1;
+       BbpCsr.field.RegNum             = Id;
+       RTUSBWriteMACRegister(pAd, BBP_CSR_CFG, BbpCsr.word);
+
+       pAd->BbpWriteLatch[Id] = Value;
+
+       return STATUS_SUCCESS;
+}
+#else
+/*
+       ========================================================================
+
+       Routine Description: Write 8-bit BBP register via firmware
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+
+NTSTATUS       RTUSBWriteBBPRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Id,
+       IN      UCHAR                   Value)
+
+{
+       BBP_CSR_CFG_STRUC       BbpCsr;
+       int                                     BusyCnt;
+       for (BusyCnt=0; BusyCnt<MAX_BUSY_COUNT; BusyCnt++)
+       {
+               RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word);
+               if (BbpCsr.field.Busy == BUSY)
+                       continue;
+               BbpCsr.word = 0;
+               BbpCsr.field.fRead = 0;
+               BbpCsr.field.BBP_RW_MODE = 1;
+               BbpCsr.field.Busy = 1;
+               BbpCsr.field.Value = Value;
+               BbpCsr.field.RegNum = Id;
+               RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word);
+               AsicSendCommandToMcu(pAd, 0x80, 0xff, 0x0, 0x0);
+               pAd->BbpWriteLatch[Id] = Value;
+               break;
+       }
+       if (BusyCnt == MAX_BUSY_COUNT)
+       {
+               DBGPRINT_ERR(("BBP write R%d=0x%x fail\n", Id, BbpCsr.word));
+               return STATUS_UNSUCCESSFUL;
+       }
+       return STATUS_SUCCESS;
+}
+#endif
+/*
+       ========================================================================
+
+       Routine Description: Write RF register through MAC
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSBWriteRFRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UINT32                  Value)
+{
+       PHY_CSR4_STRUC  PhyCsr4;
+       UINT                    i = 0;
+       NTSTATUS                status;
+
+       NdisZeroMemory(&PhyCsr4, sizeof(PHY_CSR4_STRUC));
+       do
+       {
+               status = RTUSBReadMACRegister(pAd, RF_CSR_CFG0, &PhyCsr4.word);
+               if (status >= 0)
+               {
+               if (!(PhyCsr4.field.Busy))
+                       break;
+               }
+               printk("RTUSBWriteRFRegister(RF_CSR_CFG0):retry count=%d!\n", i);
+               i++;
+       }
+       while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
+
+       if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+       {
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
+               return STATUS_UNSUCCESSFUL;
+       }
+
+       RTUSBWriteMACRegister(pAd, RF_CSR_CFG0, Value);
+
+       return STATUS_SUCCESS;
+}
+
+/*
+       ========================================================================
+
+       Routine Description: Write RT3070 RF register through MAC
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RT30xxWriteRFRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   RegID,
+       IN      UCHAR                   Value)
+{
+       RF_CSR_CFG_STRUC        rfcsr;
+       UINT                            i = 0;
+
+       do
+       {
+               RTUSBReadMACRegister(pAd, RF_CSR_CFG, &rfcsr.word);
+
+               if (!rfcsr.field.RF_CSR_KICK)
+                       break;
+               i++;
+       }
+       while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
+
+       if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+       {
+               DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
+               return STATUS_UNSUCCESSFUL;
+       }
+
+       rfcsr.field.RF_CSR_WR = 1;
+       rfcsr.field.RF_CSR_KICK = 1;
+       rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
+       rfcsr.field.RF_CSR_DATA = Value;
+
+       RTUSBWriteMACRegister(pAd, RF_CSR_CFG, rfcsr.word);
+
+       return STATUS_SUCCESS;
+}
+
+/*
+       ========================================================================
+
+       Routine Description: Read RT3070 RF register through MAC
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RT30xxReadRFRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   RegID,
+       IN      PUCHAR                  pValue)
+{
+       RF_CSR_CFG_STRUC        rfcsr;
+       UINT                            i=0, k;
+
+       for (i=0; i<MAX_BUSY_COUNT; i++)
+       {
+               RTUSBReadMACRegister(pAd, RF_CSR_CFG, &rfcsr.word);
+
+               if (rfcsr.field.RF_CSR_KICK == BUSY)
+               {
+                       continue;
+               }
+               rfcsr.word = 0;
+               rfcsr.field.RF_CSR_WR = 0;
+               rfcsr.field.RF_CSR_KICK = 1;
+               rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
+               RTUSBWriteMACRegister(pAd, RF_CSR_CFG, rfcsr.word);
+               for (k=0; k<MAX_BUSY_COUNT; k++)
+               {
+                       RTUSBReadMACRegister(pAd, RF_CSR_CFG, &rfcsr.word);
+
+                       if (rfcsr.field.RF_CSR_KICK == IDLE)
+                               break;
+               }
+               if ((rfcsr.field.RF_CSR_KICK == IDLE) &&
+                       (rfcsr.field.TESTCSR_RFACC_REGNUM == RegID))
+               {
+                       *pValue = (UCHAR)rfcsr.field.RF_CSR_DATA;
+                       break;
+               }
+       }
+       if (rfcsr.field.RF_CSR_KICK == BUSY)
+       {
+               DBGPRINT_ERR(("RF read R%d=0x%x fail\n", RegID, rfcsr.word));
+               return STATUS_UNSUCCESSFUL;
+       }
+
+       return STATUS_SUCCESS;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSBReadEEPROM(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       OUT     PUCHAR                  pData,
+       IN      USHORT                  length)
+{
+       NTSTATUS        Status = STATUS_SUCCESS;
+
+       Status = RTUSB_VendorRequest(
+               pAd,
+               (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK),
+               DEVICE_VENDOR_REQUEST_IN,
+               0x9,
+               0,
+               Offset,
+               pData,
+               length);
+
+       return Status;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSBWriteEEPROM(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       IN      PUCHAR                  pData,
+       IN      USHORT                  length)
+{
+       NTSTATUS        Status = STATUS_SUCCESS;
+
+       Status = RTUSB_VendorRequest(
+               pAd,
+               USBD_TRANSFER_DIRECTION_OUT,
+               DEVICE_VENDOR_REQUEST_OUT,
+               0x8,
+               0,
+               Offset,
+               pData,
+               length);
+
+       return Status;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+VOID RTUSBPutToSleep(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       UINT32          value;
+
+       // Timeout 0x40 x 50us
+       value = (SLEEPCID<<16)+(OWNERMCU<<24)+ (0x40<<8)+1;
+       RTUSBWriteMACRegister(pAd, 0x7010, value);
+       RTUSBWriteMACRegister(pAd, 0x404, 0x30);
+       //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+       DBGPRINT_RAW(RT_DEBUG_ERROR, ("Sleep Mailbox testvalue %x\n", value));
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS RTUSBWakeUp(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       NTSTATUS        Status;
+
+       Status = RTUSB_VendorRequest(
+               pAd,
+               USBD_TRANSFER_DIRECTION_OUT,
+               DEVICE_VENDOR_REQUEST_OUT,
+               0x01,
+               0x09,
+               0,
+               NULL,
+               0);
+
+       return Status;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTUSBInitializeCmdQ(
+       IN      PCmdQ   cmdq)
+{
+       cmdq->head = NULL;
+       cmdq->tail = NULL;
+       cmdq->size = 0;
+       cmdq->CmdQState = RT2870_THREAD_INITED;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NDIS_STATUS    RTUSBEnqueueCmdFromNdis(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      NDIS_OID                Oid,
+       IN      BOOLEAN                 SetInformation,
+       IN      PVOID                   pInformationBuffer,
+       IN      UINT32                  InformationBufferLength)
+{
+       NDIS_STATUS     status;
+       PCmdQElmt       cmdqelmt = NULL;
+       POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+
+       CHECK_PID_LEGALITY(pObj->RTUSBCmdThr_pid)
+               return (NDIS_STATUS_RESOURCES);
+
+       status = RTMPAllocateMemory((PVOID *)&cmdqelmt, sizeof(CmdQElmt));
+       if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL))
+               return (NDIS_STATUS_RESOURCES);
+
+               cmdqelmt->buffer = NULL;
+               if (pInformationBuffer != NULL)
+               {
+                       status = RTMPAllocateMemory((PVOID *)&cmdqelmt->buffer, InformationBufferLength);
+                       if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL))
+                       {
+                               kfree(cmdqelmt);
+                               return (NDIS_STATUS_RESOURCES);
+                       }
+                       else
+                       {
+                               NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength);
+                               cmdqelmt->bufferlength = InformationBufferLength;
+                       }
+               }
+               else
+                       cmdqelmt->bufferlength = 0;
+
+       cmdqelmt->command = Oid;
+       cmdqelmt->CmdFromNdis = TRUE;
+       if (SetInformation == TRUE)
+               cmdqelmt->SetOperation = TRUE;
+       else
+               cmdqelmt->SetOperation = FALSE;
+
+       NdisAcquireSpinLock(&pAd->CmdQLock);
+       if (pAd->CmdQ.CmdQState & RT2870_THREAD_CAN_DO_INSERT)
+       {
+               EnqueueCmd((&pAd->CmdQ), cmdqelmt);
+               status = NDIS_STATUS_SUCCESS;
+       }
+       else
+       {
+               status = NDIS_STATUS_FAILURE;
+       }
+       NdisReleaseSpinLock(&pAd->CmdQLock);
+
+       if (status == NDIS_STATUS_FAILURE)
+       {
+               if (cmdqelmt->buffer)
+                       NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0);
+               NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0);
+       }
+       else
+       RTUSBCMDUp(pAd);
+
+
+    return(NDIS_STATUS_SUCCESS);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+NDIS_STATUS RTUSBEnqueueInternalCmd(
+       IN PRTMP_ADAPTER        pAd,
+       IN NDIS_OID                     Oid,
+       IN PVOID                        pInformationBuffer,
+       IN UINT32                       InformationBufferLength)
+{
+       NDIS_STATUS     status;
+       PCmdQElmt       cmdqelmt = NULL;
+
+
+       status = RTMPAllocateMemory((PVOID *)&cmdqelmt, sizeof(CmdQElmt));
+       if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL))
+               return (NDIS_STATUS_RESOURCES);
+       NdisZeroMemory(cmdqelmt, sizeof(CmdQElmt));
+
+       if(InformationBufferLength > 0)
+       {
+               status = RTMPAllocateMemory((PVOID *)&cmdqelmt->buffer, InformationBufferLength);
+               if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL))
+               {
+                       NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0);
+                       return (NDIS_STATUS_RESOURCES);
+               }
+               else
+               {
+                       NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength);
+                       cmdqelmt->bufferlength = InformationBufferLength;
+               }
+       }
+       else
+       {
+               cmdqelmt->buffer = NULL;
+               cmdqelmt->bufferlength = 0;
+       }
+
+       cmdqelmt->command = Oid;
+       cmdqelmt->CmdFromNdis = FALSE;
+
+       if (cmdqelmt != NULL)
+       {
+               NdisAcquireSpinLock(&pAd->CmdQLock);
+               if (pAd->CmdQ.CmdQState & RT2870_THREAD_CAN_DO_INSERT)
+               {
+                       EnqueueCmd((&pAd->CmdQ), cmdqelmt);
+                       status = NDIS_STATUS_SUCCESS;
+               }
+               else
+               {
+                       status = NDIS_STATUS_FAILURE;
+               }
+               NdisReleaseSpinLock(&pAd->CmdQLock);
+
+               if (status == NDIS_STATUS_FAILURE)
+               {
+                       if (cmdqelmt->buffer)
+                               NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0);
+                       NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0);
+               }
+               else
+               RTUSBCMDUp(pAd);
+       }
+       return(NDIS_STATUS_SUCCESS);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       IRQL =
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTUSBDequeueCmd(
+       IN      PCmdQ           cmdq,
+       OUT     PCmdQElmt       *pcmdqelmt)
+{
+       *pcmdqelmt = cmdq->head;
+
+       if (*pcmdqelmt != NULL)
+       {
+               cmdq->head = cmdq->head->next;
+               cmdq->size--;
+               if (cmdq->size == 0)
+                       cmdq->tail = NULL;
+       }
+}
+
+/*
+    ========================================================================
+         usb_control_msg - Builds a control urb, sends it off and waits for completion
+         @dev: pointer to the usb device to send the message to
+         @pipe: endpoint "pipe" to send the message to
+         @request: USB message request value
+         @requesttype: USB message request type value
+         @value: USB message value
+         @index: USB message index value
+         @data: pointer to the data to send
+         @size: length in bytes of the data to send
+         @timeout: time in jiffies to wait for the message to complete before
+                         timing out (if 0 the wait is forever)
+         Context: !in_interrupt ()
+
+         This function sends a simple control message to a specified endpoint
+         and waits for the message to complete, or timeout.
+         If successful, it returns the number of bytes transferred, otherwise a negative error number.
+
+        Don't use this function from within an interrupt context, like a
+         bottom half handler.  If you need an asynchronous message, or need to send
+         a message from within interrupt context, use usb_submit_urb()
+         If a thread in your driver uses this call, make sure your disconnect()
+         method can wait for it to complete.  Since you don't have a handle on
+         the URB used, you can't cancel the request.
+
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS    RTUSB_VendorRequest(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UINT32                  TransferFlags,
+       IN      UCHAR                   RequestType,
+       IN      UCHAR                   Request,
+       IN      USHORT                  Value,
+       IN      USHORT                  Index,
+       IN      PVOID                   TransferBuffer,
+       IN      UINT32                  TransferBufferLength)
+{
+       int                             ret;
+       POS_COOKIE              pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("device disconnected\n"));
+               return -1;
+       }
+       else if (in_interrupt())
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("in_interrupt, RTUSB_VendorRequest Request%02x Value%04x Offset%04x\n",Request,Value,Index));
+
+               return -1;
+       }
+       else
+       {
+#define MAX_RETRY_COUNT  10
+
+               int retryCount = 0;
+               void    *tmpBuf = TransferBuffer;
+
+               // Acquire Control token
+#ifdef INF_AMAZON_SE
+               //Semaphore fix INF_AMAZON_SE hang
+               //pAd->UsbVendorReqBuf is the swap for DEVICE_VENDOR_REQUEST_IN to fix dma bug.
+               ret = down_interruptible(&(pAd->UsbVendorReq_semaphore));
+               if (pAd->UsbVendorReqBuf)
+               {
+                       ASSERT(TransferBufferLength <MAX_PARAM_BUFFER_SIZE);
+
+                       tmpBuf = (void *)pAd->UsbVendorReqBuf;
+                       NdisZeroMemory(pAd->UsbVendorReqBuf, TransferBufferLength);
+
+                       if (RequestType == DEVICE_VENDOR_REQUEST_OUT)
+                        NdisMoveMemory(tmpBuf, TransferBuffer, TransferBufferLength);
+               }
+#endif // INF_AMAZON_SE //
+               do {
+               if( RequestType == DEVICE_VENDOR_REQUEST_OUT)
+                       ret=usb_control_msg(pObj->pUsb_Dev, usb_sndctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES);
+               else if(RequestType == DEVICE_VENDOR_REQUEST_IN)
+                       ret=usb_control_msg(pObj->pUsb_Dev, usb_rcvctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES);
+               else
+               {
+                       DBGPRINT(RT_DEBUG_ERROR, ("vendor request direction is failed\n"));
+                       ret = -1;
+               }
+
+                       retryCount++;
+                       if (ret < 0) {
+                               printk("#\n");
+                               RTMPusecDelay(5000);
+                       }
+               } while((ret < 0) && (retryCount < MAX_RETRY_COUNT));
+
+#ifdef INF_AMAZON_SE
+               if ((pAd->UsbVendorReqBuf) && (RequestType == DEVICE_VENDOR_REQUEST_IN))
+                       NdisMoveMemory(TransferBuffer, tmpBuf, TransferBufferLength);
+               up(&(pAd->UsbVendorReq_semaphore));
+#endif // INF_AMAZON_SE //
+
+        if (ret < 0) {
+//                     DBGPRINT(RT_DEBUG_ERROR, ("USBVendorRequest failed ret=%d \n",ret));
+                       DBGPRINT(RT_DEBUG_ERROR, ("RTUSB_VendorRequest failed(%d),TxFlags=0x%x, ReqType=%s, Req=0x%x, Index=0x%x\n",
+                                               ret, TransferFlags, (RequestType == DEVICE_VENDOR_REQUEST_OUT ? "OUT" : "IN"), Request, Index));
+                       if (Request == 0x2)
+                               DBGPRINT(RT_DEBUG_ERROR, ("\tRequest Value=0x%04x!\n", Value));
+
+                       if ((TransferBuffer!= NULL) && (TransferBufferLength > 0))
+                               hex_dump("Failed TransferBuffer value", TransferBuffer, TransferBufferLength);
+        }
+
+#if 0
+        // retry
+               if (ret < 0) {
+                       int temp_i=0;
+                       DBGPRINT(RT_DEBUG_ERROR, ("USBVendorRequest failed ret=%d, \n",ret));
+                       ret = 0;
+                       do
+                       {
+                               if( RequestType == DEVICE_VENDOR_REQUEST_OUT)
+                                       ret=usb_control_msg(pObj->pUsb_Dev, usb_sndctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, TransferBuffer, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES);
+                               else if(RequestType == DEVICE_VENDOR_REQUEST_IN)
+                                       ret=usb_control_msg(pObj->pUsb_Dev, usb_rcvctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, TransferBuffer, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES);
+                               temp_i++;
+                       } while( (ret < 0) && (temp_i <= 1) );
+
+                       if( ret >= 0)
+                               return ret;
+
+               }
+#endif
+
+       }
+       return ret;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+         Creates an IRP to submite an IOCTL_INTERNAL_USB_RESET_PORT
+         synchronously. Callers of this function must be running at
+         PASSIVE LEVEL.
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+NTSTATUS       RTUSB_ResetDevice(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       NTSTATUS                Status = TRUE;
+
+       DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->USB_ResetDevice\n"));
+       //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS);
+       return Status;
+}
+
+VOID CMDHandler(
+    IN PRTMP_ADAPTER pAd)
+{
+       PCmdQElmt               cmdqelmt;
+       PUCHAR                  pData;
+       NDIS_STATUS             NdisStatus = NDIS_STATUS_SUCCESS;
+//     ULONG                   Now = 0;
+       NTSTATUS                ntStatus;
+//     unsigned long   IrqFlags;
+
+       while (pAd->CmdQ.size > 0)
+       {
+               NdisStatus = NDIS_STATUS_SUCCESS;
+
+               NdisAcquireSpinLock(&pAd->CmdQLock);
+               RTUSBDequeueCmd(&pAd->CmdQ, &cmdqelmt);
+               NdisReleaseSpinLock(&pAd->CmdQLock);
+
+               if (cmdqelmt == NULL)
+                       break;
+
+               pData = cmdqelmt->buffer;
+
+               if(!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
+               {
+                       switch (cmdqelmt->command)
+                       {
+                               case CMDTHREAD_CHECK_GPIO:
+                                       {
+#ifdef CONFIG_STA_SUPPORT
+                                               UINT32 data;
+#endif // CONFIG_STA_SUPPORT //
+#ifdef RALINK_ATE
+                                               if(ATE_ON(pAd))
+                                               {
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                                                       break;
+                                               }
+#endif // RALINK_ATE //
+
+#ifdef CONFIG_STA_SUPPORT
+
+
+                                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                               {
+                                                       // Read GPIO pin2 as Hardware controlled radio state
+
+                                                       RTUSBReadMACRegister( pAd, GPIO_CTRL_CFG, &data);
+
+                                                       if (data & 0x04)
+                                                       {
+                                                               pAd->StaCfg.bHwRadio = TRUE;
+                                                       }
+                                                       else
+                                                       {
+                                                               pAd->StaCfg.bHwRadio = FALSE;
+                                                       }
+
+                                                       if(pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
+                                                       {
+                                                               pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
+                                                               if(pAd->StaCfg.bRadio == TRUE)
+                                                               {
+                                                                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio On !!!\n"));
+
+                                                                       MlmeRadioOn(pAd);
+                                                                       // Update extra information
+                                                                       pAd->ExtraInfo = EXTRA_INFO_CLEAR;
+                                                               }
+                                                               else
+                                                               {
+                                                                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio Off !!!\n"));
+
+                                                                       MlmeRadioOff(pAd);
+                                                                       // Update extra information
+                                                                       pAd->ExtraInfo = HW_RADIO_OFF;
+                                                               }
+                                                       }
+                                               }
+#endif // CONFIG_STA_SUPPORT //
+                                       }
+                                       break;
+
+#ifdef CONFIG_STA_SUPPORT
+                               case CMDTHREAD_QKERIODIC_EXECUT:
+                                       {
+                                               StaQuickResponeForRateUpExec(NULL, pAd, NULL, NULL);
+                                       }
+                                       break;
+#endif // CONFIG_STA_SUPPORT //
+
+                               case CMDTHREAD_RESET_BULK_OUT:
+                                       {
+                                               UINT32          MACValue;
+                                               UCHAR           Index;
+                                               int                     ret=0;
+                                               PHT_TX_CONTEXT  pHTTXContext;
+//                                             RTMP_TX_RING *pTxRing;
+                                               unsigned long IrqFlags;
+#ifdef RALINK_ATE
+                                               PTX_CONTEXT             pNullContext = &(pAd->NullContext);
+#endif // RALINK_ATE //
+                                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT(ResetPipeid=0x%0x)===>\n", pAd->bulkResetPipeid));
+                                               // All transfers must be aborted or cancelled before attempting to reset the pipe.
+                                               //RTUSBCancelPendingBulkOutIRP(pAd);
+                                               // Wait 10ms to let previous packet that are already in HW FIFO to clear. by MAXLEE 12-25-2007
+                                               Index = 0;
+                                               do
+                                               {
+                                                       RTUSBReadMACRegister(pAd, TXRXQ_PCNT, &MACValue);
+                                                       if ((MACValue & 0xf00000/*0x800000*/) == 0)
+                                                               break;
+                                                       Index++;
+                                                       RTMPusecDelay(10000);
+                                               }while(Index < 100);
+                                               MACValue = 0;
+                                               RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue);
+                                               // To prevent Read Register error, we 2nd check the validity.
+                                               if ((MACValue & 0xc00000) == 0)
+                                                       RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue);
+                                               // To prevent Read Register error, we 3rd check the validity.
+                                               if ((MACValue & 0xc00000) == 0)
+                                                       RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue);
+                                               MACValue |= 0x80000;
+                                               RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue);
+
+                                               // Wait 1ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007
+                                               RTMPusecDelay(1000);
+
+                                               MACValue &= (~0x80000);
+                                               RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue);
+                                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tSet 0x2a0 bit19. Clear USB DMA TX path\n"));
+
+                                               // Wait 5ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007
+                                               //RTMPusecDelay(5000);
+
+                                               if ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG)
+                                               {
+                                                       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                                                       if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */)
+                                                       {
+                                                               RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
+                                                       }
+                                                       RTUSBKickBulkOut(pAd);
+
+                                                       DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tTX MGMT RECOVER Done!\n"));
+                                               }
+                                               else
+                                               {
+                                                       pHTTXContext = &(pAd->TxContext[pAd->bulkResetPipeid]);
+                                                       //NdisAcquireSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]);
+                                                       RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+                                                       if ( pAd->BulkOutPending[pAd->bulkResetPipeid] == FALSE)
+                                                       {
+                                                               pAd->BulkOutPending[pAd->bulkResetPipeid] = TRUE;
+                                                               pHTTXContext->IRPPending = TRUE;
+                                                               pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 1;
+
+                                                               // no matter what, clean the flag
+                                                               RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+
+                                                               //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]);
+                                                               RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+/*-----------------------------------------------------------------------------------------------*/
+#ifdef RALINK_ATE
+                                                               if(ATE_ON(pAd))
+                                                           {
+                                                                       pNullContext->IRPPending = TRUE;
+                                                                       //
+                                                                       // If driver is still in ATE TXFRAME mode,
+                                                                       // keep on transmitting ATE frames.
+                                                                       //
+                                                                       DBGPRINT_RAW(RT_DEBUG_TRACE, ("pAd->ate.Mode == %d\npAd->ContinBulkOut == %d\npAd->BulkOutRemained == %d\n", pAd->ate.Mode, pAd->ContinBulkOut, atomic_read(&pAd->BulkOutRemained)));
+                                                                       if((pAd->ate.Mode == ATE_TXFRAME) && ((pAd->ContinBulkOut == TRUE) || (atomic_read(&pAd->BulkOutRemained) > 0)))
+                                                                   {
+                                                                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("After CMDTHREAD_RESET_BULK_OUT, continue to bulk out frames !\n"));
+
+                                                                               // Init Tx context descriptor
+                                                                               RTUSBInitTxDesc(pAd, pNullContext, 0/* pAd->bulkResetPipeid */, (usb_complete_t)ATE_RTUSBBulkOutDataPacketComplete);
+
+                                                                               if((ret = RTUSB_SUBMIT_URB(pNullContext->pUrb))!=0)
+                                                                               {
+                                                                                       DBGPRINT(RT_DEBUG_ERROR, ("ATE_RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", ret));
+                                                                               }
+
+                                                                               pAd->BulkOutReq++;
+                                                                       }
+                                                               }
+                                                               else
+#endif // RALINK_ATE //
+/*-----------------------------------------------------------------------------------------------*/
+                                                               {
+                                                               RTUSBInitHTTxDesc(pAd, pHTTXContext, pAd->bulkResetPipeid, pHTTXContext->BulkOutSize, (usb_complete_t)RTUSBBulkOutDataPacketComplete);
+
+                                                               if((ret = RTUSB_SUBMIT_URB(pHTTXContext->pUrb))!=0)
+                                                               {
+                                                                               RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+                                                                       pAd->BulkOutPending[pAd->bulkResetPipeid] = FALSE;
+                                                                       pHTTXContext->IRPPending = FALSE;
+                                                                               pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 0;
+                                                                               RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+
+                                                                               DBGPRINT(RT_DEBUG_ERROR, ("CmdThread : CMDTHREAD_RESET_BULK_OUT: Submit Tx URB failed %d\n", ret));
+                                                               }
+                                                                       else
+                                                                       {
+                                                                               RTMP_IRQ_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+                                                                               DBGPRINT_RAW(RT_DEBUG_TRACE,("\tCMDTHREAD_RESET_BULK_OUT: TxContext[%d]:CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, pending=%d!\n",
+                                                                                               pAd->bulkResetPipeid, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition,
+                                                                                                                       pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, pAd->BulkOutPending[pAd->bulkResetPipeid]));
+                                                                               DBGPRINT_RAW(RT_DEBUG_TRACE,("\t\tBulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n",
+                                                                                                                       pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther));
+                                                                               RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+                                                                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tCMDTHREAD_RESET_BULK_OUT: Submit Tx DATA URB for failed BulkReq(0x%lx) Done, status=%d!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pHTTXContext->pUrb->status));
+
+                                                                       }
+                                                               }
+                                                       }
+                                                       else
+                                                       {
+                                                               //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]);
+                                                               //RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+
+                                                               DBGPRINT_RAW(RT_DEBUG_ERROR, ("CmdThread : TX DATA RECOVER FAIL for BulkReq(0x%lx) because BulkOutPending[%d] is TRUE!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pAd->bulkResetPipeid));
+                                                               if (pAd->bulkResetPipeid == 0)
+                                                               {
+                                                                       UCHAR   pendingContext = 0;
+                                                                       PHT_TX_CONTEXT pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[pAd->bulkResetPipeid ]);
+                                                                       PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa);
+                                                                       PTX_CONTEXT pNULLContext = (PTX_CONTEXT)(&pAd->PsPollContext);
+                                                                       PTX_CONTEXT pPsPollContext = (PTX_CONTEXT)(&pAd->NullContext);
+
+                                                                       if (pHTTXContext->IRPPending)
+                                                                               pendingContext |= 1;
+                                                                       else if (pMLMEContext->IRPPending)
+                                                                               pendingContext |= 2;
+                                                                       else if (pNULLContext->IRPPending)
+                                                                               pendingContext |= 4;
+                                                                       else if (pPsPollContext->IRPPending)
+                                                                               pendingContext |= 8;
+                                                                       else
+                                                                               pendingContext = 0;
+
+                                                                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("\tTX Occupied by %d!\n", pendingContext));
+                                                               }
+
+                                                       // no matter what, clean the flag
+                                                       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+
+                                                               RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+
+                                                               RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << pAd->bulkResetPipeid));
+                                                       }
+
+                                                       RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+                                                       //RTUSBKickBulkOut(pAd);
+                                               }
+
+                                       }
+                                       /*
+                                               // Don't cancel BULKIN.
+                                               while ((atomic_read(&pAd->PendingRx) > 0) &&
+                                                               (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+                                               {
+                                                       if (atomic_read(&pAd->PendingRx) > 0)
+                                                       {
+                                                               DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!cancel it!\n"));
+                                                               RTUSBCancelPendingBulkInIRP(pAd);
+                                                       }
+                                                       RTMPusecDelay(100000);
+                                               }
+
+                                               if ((atomic_read(&pAd->PendingRx) == 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
+                                               {
+                                                       UCHAR   i;
+                                                       RTUSBRxPacket(pAd);
+                                                       pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index
+                                                       pAd->NextRxBulkInIndex          = 0;    // Rx Bulk pointer
+                                                       for (i = 0; i < (RX_RING_SIZE); i++)
+                                                       {
+                                                               PRX_CONTEXT  pRxContext = &(pAd->RxContext[i]);
+
+                                                               pRxContext->pAd = pAd;
+                                                               pRxContext->InUse               = FALSE;
+                                                               pRxContext->IRPPending  = FALSE;
+                                                               pRxContext->Readable    = FALSE;
+                                                               pRxContext->ReorderInUse = FALSE;
+
+                                                       }
+                                                       RTUSBBulkReceive(pAd);
+                                                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTUSBBulkReceive\n"));
+                                               }*/
+                                       DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT<===\n"));
+                               break;
+
+                               case CMDTHREAD_RESET_BULK_IN:
+                                       DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN === >\n"));
+
+                                       // All transfers must be aborted or cancelled before attempting to reset the pipe.
+                                       {
+                                               UINT32          MACValue;
+/*-----------------------------------------------------------------------------------------------*/
+#ifdef RALINK_ATE
+                                               if (ATE_ON(pAd))
+                                               {
+                                                       if((pAd->PendingRx > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+                                                       {
+                                                               DBGPRINT_RAW(RT_DEBUG_ERROR, ("ATE : BulkIn IRP Pending!!!\n"));
+                                                               ATE_RTUSBCancelPendingBulkInIRP(pAd);
+                                                               RTMPusecDelay(100000);
+                                                               pAd->PendingRx = 0;
+                                                       }
+                                               }
+                                               else
+#endif // RALINK_ATE //
+/*-----------------------------------------------------------------------------------------------*/
+                                               {
+                                               //while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+                                               if((pAd->PendingRx > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+                                               {
+                                                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!!\n"));
+                                                       RTUSBCancelPendingBulkInIRP(pAd);
+                                                       RTMPusecDelay(100000);
+                                                       pAd->PendingRx = 0;
+                                               }
+                                               }
+
+                                               // Wait 10ms before reading register.
+                                               RTMPusecDelay(10000);
+                                               ntStatus = RTUSBReadMACRegister(pAd, MAC_CSR0, &MACValue);
+
+                                               if ((NT_SUCCESS(ntStatus) == TRUE) &&
+                                                       (!(RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF |
+                                                                                                       fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))))
+                                               {
+                                                       UCHAR   i;
+
+                                                       if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF |
+                                                                                                               fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))
+                                                               break;
+                                                       pAd->NextRxBulkInPosition = pAd->RxContext[pAd->NextRxBulkInIndex].BulkInOffset;
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("BULK_IN_RESET: NBIIdx=0x%x,NBIRIdx=0x%x, BIRPos=0x%lx. BIReq=x%lx, BIComplete=0x%lx, BICFail0x%lx\n",
+                                                                       pAd->NextRxBulkInIndex,  pAd->NextRxBulkInReadIndex, pAd->NextRxBulkInPosition, pAd->BulkInReq, pAd->BulkInComplete, pAd->BulkInCompleteFail));
+                                                       for (i = 0; i < RX_RING_SIZE; i++)
+                                                       {
+                                                               DBGPRINT(RT_DEBUG_TRACE, ("\tRxContext[%d]: IRPPending=%d, InUse=%d, Readable=%d!\n"
+                                                                       , i, pAd->RxContext[i].IRPPending, pAd->RxContext[i].InUse, pAd->RxContext[i].Readable));
+                                                       }
+                                                       /*
+
+                                                       DBGPRINT_RAW(RT_DEBUG_ERROR, ("==========================================\n"));
+
+                                                       pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index
+                                                       pAd->NextRxBulkInIndex          = 0;    // Rx Bulk pointer
+                                                       for (i = 0; i < (RX_RING_SIZE); i++)
+                                                       {
+                                                               PRX_CONTEXT  pRxContext = &(pAd->RxContext[i]);
+
+                                                               pRxContext->pAd = pAd;
+                                                               pRxContext->InUse               = FALSE;
+                                                               pRxContext->IRPPending  = FALSE;
+                                                               pRxContext->Readable    = FALSE;
+                                                               pRxContext->ReorderInUse = FALSE;
+
+                                                       }*/
+                                                       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
+                                                       for (i = 0; i < pAd->CommonCfg.NumOfBulkInIRP; i++)
+                                                       {
+                                                               //RTUSBBulkReceive(pAd);
+                                                               PRX_CONTEXT             pRxContext;
+                                                               PURB                    pUrb;
+                                                               int                             ret = 0;
+                                                               unsigned long   IrqFlags;
+
+
+                                                               RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+                                                               pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]);
+                                                               if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE))
+                                                               {
+                                                                       RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+                                                                       break;
+                                                               }
+                                                               pRxContext->InUse = TRUE;
+                                                               pRxContext->IRPPending = TRUE;
+                                                               pAd->PendingRx++;
+                                                               pAd->BulkInReq++;
+                                                               RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+                                                               // Init Rx context descriptor
+                                                               RTUSBInitRxDesc(pAd, pRxContext);
+                                                               pUrb = pRxContext->pUrb;
+                                                               if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+                                                               {       // fail
+
+                                                                       RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+                                                                       pRxContext->InUse = FALSE;
+                                                                       pRxContext->IRPPending = FALSE;
+                                                                       pAd->PendingRx--;
+                                                                       pAd->BulkInReq--;
+                                                                       RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+                                                                       DBGPRINT(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB failed(%d), status=%d\n", ret, pUrb->status));
+                                                               }
+                                                               else
+                                                               {       // success
+#if 0
+                                                                       RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+                                                                       pRxContext->IRPPending = TRUE;
+                                                                       //NdisInterlockedIncrement(&pAd->PendingRx);
+                                                                       pAd->PendingRx++;
+                                                                       RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+                                                                       pAd->BulkInReq++;
+#endif
+                                                                       //printk("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex);
+                                                                       DBGPRINT_RAW(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB Done, status=%d!\n", pUrb->status));
+                                                                       ASSERT((pRxContext->InUse == pRxContext->IRPPending));
+                                                               }
+                                                       }
+
+                                               }
+                                               else
+                                               {
+                                                       // Card must be removed
+                                                       if (NT_SUCCESS(ntStatus) != TRUE)
+                                                       {
+                                                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
+                                                               DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Read Register Failed!Card must be removed!!\n\n"));
+                                                       }
+                                                       else
+                                                       {
+                                                               DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Cannot do bulk in because flags(0x%lx) on !\n", pAd->Flags));
+                                               }
+                                       }
+                                       }
+                                       DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN <===\n"));
+                                       break;
+
+                               case CMDTHREAD_SET_ASIC_WCID:
+                                       {
+                                               RT_SET_ASIC_WCID        SetAsicWcid;
+                                               USHORT          offset;
+                                               UINT32          MACValue, MACRValue = 0;
+                                               SetAsicWcid = *((PRT_SET_ASIC_WCID)(pData));
+
+                                               if (SetAsicWcid.WCID >= MAX_LEN_OF_MAC_TABLE)
+                                                       return;
+
+                                               offset = MAC_WCID_BASE + ((UCHAR)SetAsicWcid.WCID)*HW_WCID_ENTRY_SIZE;
+
+                                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_SET_ASIC_WCID : WCID = %ld, SetTid  = %lx, DeleteTid = %lx.\n", SetAsicWcid.WCID, SetAsicWcid.SetTid, SetAsicWcid.DeleteTid));
+                                               MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[3]<<24)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[2]<<16)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[1]<<8)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[0]);
+                                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("1-MACValue= %x,\n", MACValue));
+                                               RTUSBWriteMACRegister(pAd, offset, MACValue);
+                                               // Read bitmask
+                                               RTUSBReadMACRegister(pAd, offset+4, &MACRValue);
+                                               if ( SetAsicWcid.DeleteTid != 0xffffffff)
+                                                       MACRValue &= (~SetAsicWcid.DeleteTid);
+                                               if (SetAsicWcid.SetTid != 0xffffffff)
+                                                       MACRValue |= (SetAsicWcid.SetTid);
+                                               MACRValue &= 0xffff0000;
+
+                                               MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[5]<<8)+pAd->MacTab.Content[SetAsicWcid.WCID].Addr[4];
+                                               MACValue |= MACRValue;
+                                               RTUSBWriteMACRegister(pAd, offset+4, MACValue);
+
+                                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-MACValue= %x,\n", MACValue));
+                                       }
+                                       break;
+
+                               case CMDTHREAD_SET_ASIC_WCID_CIPHER:
+                                       {
+#ifdef CONFIG_STA_SUPPORT
+                                               RT_SET_ASIC_WCID_ATTRI  SetAsicWcidAttri;
+                                               USHORT          offset;
+                                               UINT32          MACRValue = 0;
+                                               SHAREDKEY_MODE_STRUC csr1;
+                                               SetAsicWcidAttri = *((PRT_SET_ASIC_WCID_ATTRI)(pData));
+
+                                               if (SetAsicWcidAttri.WCID >= MAX_LEN_OF_MAC_TABLE)
+                                                       return;
+
+                                               offset = MAC_WCID_ATTRIBUTE_BASE + ((UCHAR)SetAsicWcidAttri.WCID)*HW_WCID_ATTRI_SIZE;
+
+                                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("Cmd : CMDTHREAD_SET_ASIC_WCID_CIPHER : WCID = %ld, Cipher = %lx.\n", SetAsicWcidAttri.WCID, SetAsicWcidAttri.Cipher));
+                                               // Read bitmask
+                                               RTUSBReadMACRegister(pAd, offset, &MACRValue);
+                                               MACRValue = 0;
+                                               MACRValue |= (((UCHAR)SetAsicWcidAttri.Cipher) << 1);
+
+                                               RTUSBWriteMACRegister(pAd, offset, MACRValue);
+                                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-offset = %x , MACValue= %x,\n", offset, MACRValue));
+
+                                               offset = PAIRWISE_IVEIV_TABLE_BASE + ((UCHAR)SetAsicWcidAttri.WCID)*HW_IVEIV_ENTRY_SIZE;
+                                               MACRValue = 0;
+                                               if ( (SetAsicWcidAttri.Cipher <= CIPHER_WEP128))
+                                                       MACRValue |= ( pAd->StaCfg.DefaultKeyId << 30);
+                                               else
+                                                       MACRValue |= (0x20000000);
+                                               RTUSBWriteMACRegister(pAd, offset, MACRValue);
+                                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-offset = %x , MACValue= %x,\n", offset, MACRValue));
+
+                                               //
+                                               // Update cipher algorithm. WSTA always use BSS0
+                                               //
+                                               // for adhoc mode only ,because wep status slow than add key, when use zero config
+                                               if (pAd->StaCfg.BssType == BSS_ADHOC )
+                                               {
+                                                       offset = MAC_WCID_ATTRIBUTE_BASE;
+
+                                                       RTUSBReadMACRegister(pAd, offset, &MACRValue);
+                                                       MACRValue &= (~0xe);
+                                                       MACRValue |= (((UCHAR)SetAsicWcidAttri.Cipher) << 1);
+
+                                                       RTUSBWriteMACRegister(pAd, offset, MACRValue);
+
+                                                       //Update group key cipher,,because wep status slow than add key, when use zero config
+                                                       RTUSBReadMACRegister(pAd, SHARED_KEY_MODE_BASE+4*(0/2), &csr1.word);
+
+                                                       csr1.field.Bss0Key0CipherAlg = SetAsicWcidAttri.Cipher;
+                                                       csr1.field.Bss0Key1CipherAlg = SetAsicWcidAttri.Cipher;
+
+                                                       RTUSBWriteMACRegister(pAd, SHARED_KEY_MODE_BASE+4*(0/2), csr1.word);
+                                               }
+#endif // CONFIG_STA_SUPPORT //
+                                       }
+                                       break;
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+                               // avoid in interrupt when write key
+                               case RT_CMD_SET_KEY_TABLE: //General call for AsicAddPairwiseKeyEntry()
+                                       {
+                                               RT_ADD_PAIRWISE_KEY_ENTRY KeyInfo;
+                                               KeyInfo  = *((PRT_ADD_PAIRWISE_KEY_ENTRY)(pData));
+                                               AsicAddPairwiseKeyEntry(pAd,
+                                                                                               KeyInfo.MacAddr,
+                                                                                               (UCHAR)KeyInfo.MacTabMatchWCID,
+                                                                                               &KeyInfo.CipherKey);
+                                       }
+                                       break;
+
+                               case RT_CMD_SET_RX_WCID_TABLE: //General call for RTMPAddWcidAttributeEntry()
+                                       {
+                                               PMAC_TABLE_ENTRY pEntry ;
+                                               pEntry = (PMAC_TABLE_ENTRY)(pData);
+                                               RTMPAddWcidAttributeEntry(pAd,
+                                                                                                       BSS0,
+                                                                                                       0,
+                                                                                                       pEntry->PairwiseKey.CipherAlg,
+                                                                                                       pEntry);
+                                       }
+                                       break;
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+                               case CMDTHREAD_SET_CLIENT_MAC_ENTRY:
+                                       {
+                                               MAC_TABLE_ENTRY *pEntry;
+                                               pEntry = (MAC_TABLE_ENTRY *)pData;
+
+
+#ifdef CONFIG_STA_SUPPORT
+                                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                               {
+                                                       AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)pEntry->Aid);
+                                                       if ((pEntry->AuthMode <= Ndis802_11AuthModeAutoSwitch) && (pEntry->WepStatus == Ndis802_11Encryption1Enabled))
+                                                       {
+                                                               UINT32 uIV = 0;
+                                                               PUCHAR  ptr;
+
+                                                               ptr = (PUCHAR) &uIV;
+                                                               *(ptr + 3) = (pAd->StaCfg.DefaultKeyId << 6);
+                                                               AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, uIV, 0);
+                                                               AsicUpdateWCIDAttribute(pAd, pEntry->Aid, BSS0, pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, FALSE);
+                                                       }
+                                                       else if (pEntry->AuthMode == Ndis802_11AuthModeWPANone)
+                                                       {
+                                                               UINT32 uIV = 0;
+                                                               PUCHAR  ptr;
+
+                                                               ptr = (PUCHAR) &uIV;
+                                                               *(ptr + 3) = (pAd->StaCfg.DefaultKeyId << 6);
+                                                               AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, uIV, 0);
+                                                               AsicUpdateWCIDAttribute(pAd, pEntry->Aid, BSS0, pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, FALSE);
+                                                       }
+                                                       else
+                                                       {
+                                                               //
+                                                               // Other case, disable engine.
+                                                               // Don't worry WPA key, we will add WPA Key after 4-Way handshaking.
+                                                               //
+                                                               USHORT   offset;
+                                                               offset = MAC_WCID_ATTRIBUTE_BASE + (pEntry->Aid * HW_WCID_ATTRI_SIZE);
+                                                               // RX_PKEY_MODE:0 for no security; RX_KEY_TAB:0 for shared key table; BSS_IDX:0
+                                                               RTUSBWriteMACRegister(pAd, offset, 0);
+                                                       }
+                                               }
+#endif // CONFIG_STA_SUPPORT //
+
+                                               AsicUpdateRxWCIDTable(pAd, pEntry->Aid, pEntry->Addr);
+                                               printk("UpdateRxWCIDTable(): Aid=%d, Addr=%02x:%02x:%02x:%02x:%02x:%02x!\n", pEntry->Aid,
+                                                               pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]);
+                                       }
+                                       break;
+
+                               case OID_802_11_ADD_WEP:
+                                       {
+#ifdef CONFIG_STA_SUPPORT
+                                               UINT    i;
+                                               UINT32  KeyIdx;
+                                               PNDIS_802_11_WEP        pWepKey;
+
+                                               DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::OID_802_11_ADD_WEP  \n"));
+
+                                               pWepKey = (PNDIS_802_11_WEP)pData;
+                                               KeyIdx = pWepKey->KeyIndex & 0x0fffffff;
+
+                                               // it is a shared key
+                                               if ((KeyIdx >= 4) || ((pWepKey->KeyLength != 5) && (pWepKey->KeyLength != 13)))
+                                               {
+                                                       NdisStatus = NDIS_STATUS_INVALID_DATA;
+                                                       DBGPRINT(RT_DEBUG_ERROR, ("CmdThread::OID_802_11_ADD_WEP, INVALID_DATA!!\n"));
+                                               }
+                                               else
+                                               {
+                                                       UCHAR CipherAlg;
+                                                       pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength;
+                                                       NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength);
+                                                       CipherAlg = (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 5)? CIPHER_WEP64 : CIPHER_WEP128;
+
+                                                       //
+                                                       // Change the WEP cipher to CKIP cipher if CKIP KP on.
+                                                       // Funk UI or Meetinghouse UI will add ckip key from this path.
+                                                       //
+
+                                                       if (pAd->OpMode == OPMODE_STA)
+                                                       {
+                                                               pAd->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
+                                                               pAd->MacTab.Content[BSSID_WCID].PairwiseKey.KeyLen = pAd->SharedKey[BSS0][KeyIdx].KeyLen;
+                                                       }
+                                                       pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CipherAlg;
+                                                       if (pWepKey->KeyIndex & 0x80000000)
+                                                       {
+                                                               // Default key for tx (shared key)
+                                                               UCHAR   IVEIV[8];
+                                                               UINT32  WCIDAttri, Value;
+                                                               USHORT  offset, offset2;
+                                                               NdisZeroMemory(IVEIV, 8);
+                                                               pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx;
+                                                               // Add BSSID to WCTable. because this is Tx wep key.
+                                                               // WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:1=PAIRWISE KEY, BSSIdx is 0
+                                                               WCIDAttri = (CipherAlg<<1)|SHAREDKEYTABLE;
+
+                                                               offset = MAC_WCID_ATTRIBUTE_BASE + (BSSID_WCID* HW_WCID_ATTRI_SIZE);
+                                                               RTUSBWriteMACRegister(pAd, offset, WCIDAttri);
+                                                               // 1. IV/EIV
+                                                               // Specify key index to find shared key.
+                                                               IVEIV[3] = (UCHAR)(KeyIdx<< 6); //WEP Eiv bit off. groupkey index is not 0
+                                                               offset = PAIRWISE_IVEIV_TABLE_BASE + (BSS0Mcast_WCID * HW_IVEIV_ENTRY_SIZE);
+                                                               offset2 = PAIRWISE_IVEIV_TABLE_BASE + (BSSID_WCID* HW_IVEIV_ENTRY_SIZE);
+                                                               for (i=0; i<8;)
+                                                               {
+                                                                       Value = IVEIV[i];
+                                                                       Value += (IVEIV[i+1]<<8);
+                                                                       Value += (IVEIV[i+2]<<16);
+                                                                       Value += (IVEIV[i+3]<<24);
+                                                                       RTUSBWriteMACRegister(pAd, offset+i, Value);
+                                                                       RTUSBWriteMACRegister(pAd, offset2+i, Value);
+                                                                       i+=4;
+                                                               }
+
+                                                               // 2. WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:use share key, BSSIdx is 0
+                                                               WCIDAttri = (pAd->SharedKey[BSS0][KeyIdx].CipherAlg<<1)|SHAREDKEYTABLE;
+                                                               offset = MAC_WCID_ATTRIBUTE_BASE + (BSS0Mcast_WCID* HW_WCID_ATTRI_SIZE);
+                                                               DBGPRINT(RT_DEBUG_TRACE, ("BSS0Mcast_WCID : offset = %x, WCIDAttri = %x\n", offset, WCIDAttri));
+                                                               RTUSBWriteMACRegister(pAd, offset, WCIDAttri);
+
+                                                       }
+                                                       AsicAddSharedKeyEntry(pAd, BSS0, (UCHAR)KeyIdx, CipherAlg, pWepKey->KeyMaterial, NULL, NULL);
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::OID_802_11_ADD_WEP (KeyIdx=%d, Len=%d-byte)\n", KeyIdx, pWepKey->KeyLength));
+                                               }
+#endif // CONFIG_STA_SUPPORT //
+                                       }
+                                       break;
+
+                               case CMDTHREAD_802_11_COUNTER_MEASURE:
+                                       break;
+                               default:
+                                       DBGPRINT(RT_DEBUG_ERROR, ("--> Control Thread !! ERROR !! Unknown(cmdqelmt->command=0x%x) !! \n", cmdqelmt->command));
+                                       break;
+                       }
+               }
+
+               if (cmdqelmt->CmdFromNdis == TRUE)
+               {
+                               if (cmdqelmt->buffer != NULL)
+                                       NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0);
+
+                       NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0);
+               }
+               else
+               {
+                       if ((cmdqelmt->buffer != NULL) && (cmdqelmt->bufferlength != 0))
+                               NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0);
+            {
+                               NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0);
+                       }
+               }
+       }       /* end of while */
+}
+
diff --git a/drivers/staging/rt2870/common/spectrum.c b/drivers/staging/rt2870/common/spectrum.c
new file mode 100644 (file)
index 0000000..abba840
--- /dev/null
@@ -0,0 +1,1876 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+       action.c
+
+    Abstract:
+    Handle association related requests either from WSTA or from local MLME
+
+    Revision History:
+    Who          When          What
+    ---------    ----------    ----------------------------------------------
+       Fonchi Wu    2008                  created for 802.11h
+ */
+
+#include "../rt_config.h"
+#include "action.h"
+
+VOID MeasureReqTabInit(
+       IN PRTMP_ADAPTER pAd)
+{
+       NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
+
+       pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC);
+       if (pAd->CommonCfg.pMeasureReqTab)
+               NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB));
+       else
+               DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __FUNCTION__));
+
+       return;
+}
+
+VOID MeasureReqTabExit(
+       IN PRTMP_ADAPTER pAd)
+{
+       NdisFreeSpinLock(pAd->CommonCfg.MeasureReqTabLock);
+
+       if (pAd->CommonCfg.pMeasureReqTab)
+               kfree(pAd->CommonCfg.pMeasureReqTab);
+       pAd->CommonCfg.pMeasureReqTab = NULL;
+
+       return;
+}
+
+static PMEASURE_REQ_ENTRY MeasureReqLookUp(
+       IN PRTMP_ADAPTER        pAd,
+       IN UINT8                        DialogToken)
+{
+       UINT HashIdx;
+       PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
+       PMEASURE_REQ_ENTRY pEntry = NULL;
+       PMEASURE_REQ_ENTRY pPrevEntry = NULL;
+
+       if (pTab == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__));
+               return NULL;
+       }
+
+       RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
+
+       HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
+       pEntry = pTab->Hash[HashIdx];
+
+       while (pEntry)
+       {
+               if (pEntry->DialogToken == DialogToken)
+                       break;
+               else
+               {
+                       pPrevEntry = pEntry;
+                       pEntry = pEntry->pNext;
+               }
+       }
+
+       RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
+
+       return pEntry;
+}
+
+static PMEASURE_REQ_ENTRY MeasureReqInsert(
+       IN PRTMP_ADAPTER        pAd,
+       IN UINT8                        DialogToken)
+{
+       INT i;
+       ULONG HashIdx;
+       PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
+       PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry;
+       ULONG Now;
+
+       if(pTab == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__));
+               return NULL;
+       }
+
+       pEntry = MeasureReqLookUp(pAd, DialogToken);
+       if (pEntry == NULL)
+       {
+               RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
+               for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++)
+               {
+                       NdisGetSystemUpTime(&Now);
+                       pEntry = &pTab->Content[i];
+
+                       if ((pEntry->Valid == TRUE)
+                               && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT)))
+                       {
+                               PMEASURE_REQ_ENTRY pPrevEntry = NULL;
+                               ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
+                               PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
+
+                               // update Hash list
+                               do
+                               {
+                                       if (pProbeEntry == pEntry)
+                                       {
+                                               if (pPrevEntry == NULL)
+                                               {
+                                                       pTab->Hash[HashIdx] = pEntry->pNext;
+                                               }
+                                               else
+                                               {
+                                                       pPrevEntry->pNext = pEntry->pNext;
+                                               }
+                                               break;
+                                       }
+
+                                       pPrevEntry = pProbeEntry;
+                                       pProbeEntry = pProbeEntry->pNext;
+                               } while (pProbeEntry);
+
+                               NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
+                               pTab->Size--;
+
+                               break;
+                       }
+
+                       if (pEntry->Valid == FALSE)
+                               break;
+               }
+
+               if (i < MAX_MEASURE_REQ_TAB_SIZE)
+               {
+                       NdisGetSystemUpTime(&Now);
+                       pEntry->lastTime = Now;
+                       pEntry->Valid = TRUE;
+                       pEntry->DialogToken = DialogToken;
+                       pTab->Size++;
+               }
+               else
+               {
+                       pEntry = NULL;
+                       DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __FUNCTION__));
+               }
+
+               // add this Neighbor entry into HASH table
+               if (pEntry)
+               {
+                       HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
+                       if (pTab->Hash[HashIdx] == NULL)
+                       {
+                               pTab->Hash[HashIdx] = pEntry;
+                       }
+                       else
+                       {
+                               pCurrEntry = pTab->Hash[HashIdx];
+                               while (pCurrEntry->pNext != NULL)
+                                       pCurrEntry = pCurrEntry->pNext;
+                               pCurrEntry->pNext = pEntry;
+                       }
+               }
+
+               RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
+       }
+
+       return pEntry;
+}
+
+static VOID MeasureReqDelete(
+       IN PRTMP_ADAPTER        pAd,
+       IN UINT8                        DialogToken)
+{
+       PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
+       PMEASURE_REQ_ENTRY pEntry = NULL;
+
+       if(pTab == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__));
+               return;
+       }
+
+       // if empty, return
+       if (pTab->Size == 0)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
+               return;
+       }
+
+       pEntry = MeasureReqLookUp(pAd, DialogToken);
+       if (pEntry != NULL)
+       {
+               PMEASURE_REQ_ENTRY pPrevEntry = NULL;
+               ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
+               PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
+
+               RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
+               // update Hash list
+               do
+               {
+                       if (pProbeEntry == pEntry)
+                       {
+                               if (pPrevEntry == NULL)
+                               {
+                                       pTab->Hash[HashIdx] = pEntry->pNext;
+                               }
+                               else
+                               {
+                                       pPrevEntry->pNext = pEntry->pNext;
+                               }
+                               break;
+                       }
+
+                       pPrevEntry = pProbeEntry;
+                       pProbeEntry = pProbeEntry->pNext;
+               } while (pProbeEntry);
+
+               NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
+               pTab->Size--;
+
+               RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
+       }
+
+       return;
+}
+
+VOID TpcReqTabInit(
+       IN PRTMP_ADAPTER pAd)
+{
+       NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
+
+       pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC);
+       if (pAd->CommonCfg.pTpcReqTab)
+               NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB));
+       else
+               DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __FUNCTION__));
+
+       return;
+}
+
+VOID TpcReqTabExit(
+       IN PRTMP_ADAPTER pAd)
+{
+       NdisFreeSpinLock(pAd->CommonCfg.TpcReqTabLock);
+
+       if (pAd->CommonCfg.pTpcReqTab)
+               kfree(pAd->CommonCfg.pTpcReqTab);
+       pAd->CommonCfg.pTpcReqTab = NULL;
+
+       return;
+}
+
+static PTPC_REQ_ENTRY TpcReqLookUp(
+       IN PRTMP_ADAPTER        pAd,
+       IN UINT8                        DialogToken)
+{
+       UINT HashIdx;
+       PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
+       PTPC_REQ_ENTRY pEntry = NULL;
+       PTPC_REQ_ENTRY pPrevEntry = NULL;
+
+       if (pTab == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__));
+               return NULL;
+       }
+
+       RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
+
+       HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
+       pEntry = pTab->Hash[HashIdx];
+
+       while (pEntry)
+       {
+               if (pEntry->DialogToken == DialogToken)
+                       break;
+               else
+               {
+                       pPrevEntry = pEntry;
+                       pEntry = pEntry->pNext;
+               }
+       }
+
+       RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
+
+       return pEntry;
+}
+
+
+static PTPC_REQ_ENTRY TpcReqInsert(
+       IN PRTMP_ADAPTER        pAd,
+       IN UINT8                        DialogToken)
+{
+       INT i;
+       ULONG HashIdx;
+       PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
+       PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry;
+       ULONG Now;
+
+       if(pTab == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__));
+               return NULL;
+       }
+
+       pEntry = TpcReqLookUp(pAd, DialogToken);
+       if (pEntry == NULL)
+       {
+               RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
+               for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++)
+               {
+                       NdisGetSystemUpTime(&Now);
+                       pEntry = &pTab->Content[i];
+
+                       if ((pEntry->Valid == TRUE)
+                               && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT)))
+                       {
+                               PTPC_REQ_ENTRY pPrevEntry = NULL;
+                               ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
+                               PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
+
+                               // update Hash list
+                               do
+                               {
+                                       if (pProbeEntry == pEntry)
+                                       {
+                                               if (pPrevEntry == NULL)
+                                               {
+                                                       pTab->Hash[HashIdx] = pEntry->pNext;
+                                               }
+                                               else
+                                               {
+                                                       pPrevEntry->pNext = pEntry->pNext;
+                                               }
+                                               break;
+                                       }
+
+                                       pPrevEntry = pProbeEntry;
+                                       pProbeEntry = pProbeEntry->pNext;
+                               } while (pProbeEntry);
+
+                               NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
+                               pTab->Size--;
+
+                               break;
+                       }
+
+                       if (pEntry->Valid == FALSE)
+                               break;
+               }
+
+               if (i < MAX_TPC_REQ_TAB_SIZE)
+               {
+                       NdisGetSystemUpTime(&Now);
+                       pEntry->lastTime = Now;
+                       pEntry->Valid = TRUE;
+                       pEntry->DialogToken = DialogToken;
+                       pTab->Size++;
+               }
+               else
+               {
+                       pEntry = NULL;
+                       DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __FUNCTION__));
+               }
+
+               // add this Neighbor entry into HASH table
+               if (pEntry)
+               {
+                       HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
+                       if (pTab->Hash[HashIdx] == NULL)
+                       {
+                               pTab->Hash[HashIdx] = pEntry;
+                       }
+                       else
+                       {
+                               pCurrEntry = pTab->Hash[HashIdx];
+                               while (pCurrEntry->pNext != NULL)
+                                       pCurrEntry = pCurrEntry->pNext;
+                               pCurrEntry->pNext = pEntry;
+                       }
+               }
+
+               RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
+       }
+
+       return pEntry;
+}
+
+static VOID TpcReqDelete(
+       IN PRTMP_ADAPTER        pAd,
+       IN UINT8                        DialogToken)
+{
+       PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
+       PTPC_REQ_ENTRY pEntry = NULL;
+
+       if(pTab == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__));
+               return;
+       }
+
+       // if empty, return
+       if (pTab->Size == 0)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
+               return;
+       }
+
+       pEntry = TpcReqLookUp(pAd, DialogToken);
+       if (pEntry != NULL)
+       {
+               PTPC_REQ_ENTRY pPrevEntry = NULL;
+               ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
+               PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
+
+               RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
+               // update Hash list
+               do
+               {
+                       if (pProbeEntry == pEntry)
+                       {
+                               if (pPrevEntry == NULL)
+                               {
+                                       pTab->Hash[HashIdx] = pEntry->pNext;
+                               }
+                               else
+                               {
+                                       pPrevEntry->pNext = pEntry->pNext;
+                               }
+                               break;
+                       }
+
+                       pPrevEntry = pProbeEntry;
+                       pProbeEntry = pProbeEntry->pNext;
+               } while (pProbeEntry);
+
+               NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
+               pTab->Size--;
+
+               RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
+       }
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Get Current TimeS tamp.
+
+       Parametrs:
+
+       Return  : Current Time Stamp.
+       ==========================================================================
+ */
+static UINT64 GetCurrentTimeStamp(
+       IN PRTMP_ADAPTER pAd)
+{
+       // get current time stamp.
+       return 0;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Get Current Transmit Power.
+
+       Parametrs:
+
+       Return  : Current Time Stamp.
+       ==========================================================================
+ */
+static UINT8 GetCurTxPwr(
+       IN PRTMP_ADAPTER pAd,
+       IN UINT8 Wcid)
+{
+       return 16; /* 16 dBm */
+}
+
+/*
+       ==========================================================================
+       Description:
+               Insert Dialog Token into frame.
+
+       Parametrs:
+               1. frame buffer pointer.
+               2. frame length.
+               3. Dialog token.
+
+       Return  : None.
+       ==========================================================================
+ */
+static VOID InsertDialogToken(
+       IN PRTMP_ADAPTER pAd,
+       OUT PUCHAR pFrameBuf,
+       OUT PULONG pFrameLen,
+       IN UINT8 DialogToken)
+{
+       ULONG TempLen;
+       MakeOutgoingFrame(pFrameBuf,    &TempLen,
+                                       1,                              &DialogToken,
+                                       END_OF_ARGS);
+
+       *pFrameLen = *pFrameLen + TempLen;
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Insert TPC Request IE into frame.
+
+       Parametrs:
+               1. frame buffer pointer.
+               2. frame length.
+
+       Return  : None.
+       ==========================================================================
+ */
+ static VOID InsertTpcReqIE(
+       IN PRTMP_ADAPTER pAd,
+       OUT PUCHAR pFrameBuf,
+       OUT PULONG pFrameLen)
+{
+       ULONG TempLen;
+       ULONG Len = 0;
+       UINT8 ElementID = IE_TPC_REQUEST;
+
+       MakeOutgoingFrame(pFrameBuf,                                    &TempLen,
+                                               1,                                                      &ElementID,
+                                               1,                                                      &Len,
+                                               END_OF_ARGS);
+
+       *pFrameLen = *pFrameLen + TempLen;
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Insert TPC Report IE into frame.
+
+       Parametrs:
+               1. frame buffer pointer.
+               2. frame length.
+               3. Transmit Power.
+               4. Link Margin.
+
+       Return  : None.
+       ==========================================================================
+ */
+ static VOID InsertTpcReportIE(
+       IN PRTMP_ADAPTER pAd,
+       OUT PUCHAR pFrameBuf,
+       OUT PULONG pFrameLen,
+       IN UINT8 TxPwr,
+       IN UINT8 LinkMargin)
+{
+       ULONG TempLen;
+       ULONG Len = sizeof(TPC_REPORT_INFO);
+       UINT8 ElementID = IE_TPC_REPORT;
+       TPC_REPORT_INFO TpcReportIE;
+
+       TpcReportIE.TxPwr = TxPwr;
+       TpcReportIE.LinkMargin = LinkMargin;
+
+       MakeOutgoingFrame(pFrameBuf,                                    &TempLen,
+                                               1,                                                      &ElementID,
+                                               1,                                                      &Len,
+                                               Len,                                            &TpcReportIE,
+                                               END_OF_ARGS);
+
+       *pFrameLen = *pFrameLen + TempLen;
+
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Insert Channel Switch Announcement IE into frame.
+
+       Parametrs:
+               1. frame buffer pointer.
+               2. frame length.
+               3. channel switch announcement mode.
+               4. new selected channel.
+               5. channel switch announcement count.
+
+       Return  : None.
+       ==========================================================================
+ */
+static VOID InsertChSwAnnIE(
+       IN PRTMP_ADAPTER pAd,
+       OUT PUCHAR pFrameBuf,
+       OUT PULONG pFrameLen,
+       IN UINT8 ChSwMode,
+       IN UINT8 NewChannel,
+       IN UINT8 ChSwCnt)
+{
+       ULONG TempLen;
+       ULONG Len = sizeof(CH_SW_ANN_INFO);
+       UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
+       CH_SW_ANN_INFO ChSwAnnIE;
+
+       ChSwAnnIE.ChSwMode = ChSwMode;
+       ChSwAnnIE.Channel = NewChannel;
+       ChSwAnnIE.ChSwCnt = ChSwCnt;
+
+       MakeOutgoingFrame(pFrameBuf,                            &TempLen,
+                                               1,                                              &ElementID,
+                                               1,                                              &Len,
+                                               Len,                                    &ChSwAnnIE,
+                                               END_OF_ARGS);
+
+       *pFrameLen = *pFrameLen + TempLen;
+
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Insert Measure Request IE into frame.
+
+       Parametrs:
+               1. frame buffer pointer.
+               2. frame length.
+               3. Measure Token.
+               4. Measure Request Mode.
+               5. Measure Request Type.
+               6. Measure Channel.
+               7. Measure Start time.
+               8. Measure Duration.
+
+
+       Return  : None.
+       ==========================================================================
+ */
+static VOID InsertMeasureReqIE(
+       IN PRTMP_ADAPTER pAd,
+       OUT PUCHAR pFrameBuf,
+       OUT PULONG pFrameLen,
+       IN PMEASURE_REQ_INFO pMeasureReqIE)
+{
+       ULONG TempLen;
+       UINT8 Len = sizeof(MEASURE_REQ_INFO);
+       UINT8 ElementID = IE_MEASUREMENT_REQUEST;
+
+       MakeOutgoingFrame(pFrameBuf,                                    &TempLen,
+                                               1,                                                      &ElementID,
+                                               1,                                                      &Len,
+                                               Len,                                            pMeasureReqIE,
+                                               END_OF_ARGS);
+
+       *pFrameLen = *pFrameLen + TempLen;
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Insert Measure Report IE into frame.
+
+       Parametrs:
+               1. frame buffer pointer.
+               2. frame length.
+               3. Measure Token.
+               4. Measure Request Mode.
+               5. Measure Request Type.
+               6. Length of Report Infomation
+               7. Pointer of Report Infomation Buffer.
+
+       Return  : None.
+       ==========================================================================
+ */
+static VOID InsertMeasureReportIE(
+       IN PRTMP_ADAPTER pAd,
+       OUT PUCHAR pFrameBuf,
+       OUT PULONG pFrameLen,
+       IN PMEASURE_REPORT_INFO pMeasureReportIE,
+       IN UINT8 ReportLnfoLen,
+       IN PUINT8 pReportInfo)
+{
+       ULONG TempLen;
+       ULONG Len;
+       UINT8 ElementID = IE_MEASUREMENT_REPORT;
+
+       Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen;
+
+       MakeOutgoingFrame(pFrameBuf,                                    &TempLen,
+                                               1,                                                      &ElementID,
+                                               1,                                                      &Len,
+                                               Len,                                            pMeasureReportIE,
+                                               END_OF_ARGS);
+
+       *pFrameLen = *pFrameLen + TempLen;
+
+       if ((ReportLnfoLen > 0) && (pReportInfo != NULL))
+       {
+               MakeOutgoingFrame(pFrameBuf + *pFrameLen,               &TempLen,
+                                                       ReportLnfoLen,                          pReportInfo,
+                                                       END_OF_ARGS);
+
+               *pFrameLen = *pFrameLen + TempLen;
+       }
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Prepare Measurement request action frame and enqueue it into
+               management queue waiting for transmition.
+
+       Parametrs:
+               1. the destination mac address of the frame.
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID EnqueueMeasurementReq(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pDA,
+       IN UINT8 MeasureToken,
+       IN UINT8 MeasureReqMode,
+       IN UINT8 MeasureReqType,
+       IN UINT8 MeasureCh,
+       IN UINT16 MeasureDuration)
+{
+       PUCHAR pOutBuffer = NULL;
+       NDIS_STATUS NStatus;
+       ULONG FrameLen;
+       HEADER_802_11 ActHdr;
+       MEASURE_REQ_INFO MeasureReqIE;
+       UINT8 RmReqDailogToken = RandomByte(pAd);
+       UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd);
+
+       // build action frame header.
+       MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
+                                               pAd->CurrentAddress);
+
+       NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
+       if(NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
+               return;
+       }
+       NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
+       FrameLen = sizeof(HEADER_802_11);
+
+       InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRQ);
+
+       // fill Dialog Token
+       InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, MeasureToken);
+
+       // prepare Measurement IE.
+       NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO));
+       MeasureReqIE.Token = RmReqDailogToken;
+       MeasureReqIE.ReqMode.word = MeasureReqMode;
+       MeasureReqIE.ReqType = MeasureReqType;
+       MeasureReqIE.MeasureReq.ChNum = MeasureCh;
+       MeasureReqIE.MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
+       MeasureReqIE.MeasureReq.MeasureDuration = cpu2le16(MeasureDuration);
+       InsertMeasureReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureReqIE);
+
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Prepare Measurement report action frame and enqueue it into
+               management queue waiting for transmition.
+
+       Parametrs:
+               1. the destination mac address of the frame.
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID EnqueueMeasurementRep(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pDA,
+       IN UINT8 DialogToken,
+       IN UINT8 MeasureToken,
+       IN UINT8 MeasureReqMode,
+       IN UINT8 MeasureReqType,
+       IN UINT8 ReportInfoLen,
+       IN PUINT8 pReportInfo)
+{
+       PUCHAR pOutBuffer = NULL;
+       NDIS_STATUS NStatus;
+       ULONG FrameLen;
+       HEADER_802_11 ActHdr;
+       MEASURE_REPORT_INFO MeasureRepIE;
+
+       // build action frame header.
+       MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
+                                               pAd->CurrentAddress);
+
+       NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
+       if(NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
+               return;
+       }
+       NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
+       FrameLen = sizeof(HEADER_802_11);
+
+       InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP);
+
+       // fill Dialog Token
+       InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
+
+       // prepare Measurement IE.
+       NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO));
+       MeasureRepIE.Token = MeasureToken;
+       MeasureRepIE.ReportMode.word = MeasureReqMode;
+       MeasureRepIE.ReportType = MeasureReqType;
+       InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo);
+
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Prepare TPC Request action frame and enqueue it into
+               management queue waiting for transmition.
+
+       Parametrs:
+               1. the destination mac address of the frame.
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID EnqueueTPCReq(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pDA,
+       IN UCHAR DialogToken)
+{
+       PUCHAR pOutBuffer = NULL;
+       NDIS_STATUS NStatus;
+       ULONG FrameLen;
+
+       HEADER_802_11 ActHdr;
+
+       // build action frame header.
+       MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
+                                               pAd->CurrentAddress);
+
+       NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
+       if(NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
+               return;
+       }
+       NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
+       FrameLen = sizeof(HEADER_802_11);
+
+       InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ);
+
+       // fill Dialog Token
+       InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
+
+       // Insert TPC Request IE.
+       InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
+
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Prepare TPC Report action frame and enqueue it into
+               management queue waiting for transmition.
+
+       Parametrs:
+               1. the destination mac address of the frame.
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID EnqueueTPCRep(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pDA,
+       IN UINT8 DialogToken,
+       IN UINT8 TxPwr,
+       IN UINT8 LinkMargin)
+{
+       PUCHAR pOutBuffer = NULL;
+       NDIS_STATUS NStatus;
+       ULONG FrameLen;
+
+       HEADER_802_11 ActHdr;
+
+       // build action frame header.
+       MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
+                                               pAd->CurrentAddress);
+
+       NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
+       if(NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
+               return;
+       }
+       NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
+       FrameLen = sizeof(HEADER_802_11);
+
+       InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP);
+
+       // fill Dialog Token
+       InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
+
+       // Insert TPC Request IE.
+       InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin);
+
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Prepare Channel Switch Announcement action frame and enqueue it into
+               management queue waiting for transmition.
+
+       Parametrs:
+               1. the destination mac address of the frame.
+               2. Channel switch announcement mode.
+               2. a New selected channel.
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID EnqueueChSwAnn(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pDA,
+       IN UINT8 ChSwMode,
+       IN UINT8 NewCh)
+{
+       PUCHAR pOutBuffer = NULL;
+       NDIS_STATUS NStatus;
+       ULONG FrameLen;
+
+       HEADER_802_11 ActHdr;
+
+       // build action frame header.
+       MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
+                                               pAd->CurrentAddress);
+
+       NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
+       if(NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
+               return;
+       }
+       NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
+       FrameLen = sizeof(HEADER_802_11);
+
+       InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
+
+       InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0);
+
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       return;
+}
+
+static BOOLEAN DfsRequirementCheck(
+       IN PRTMP_ADAPTER pAd,
+       IN UINT8 Channel)
+{
+       BOOLEAN Result = FALSE;
+       INT i;
+
+       do
+       {
+               // check DFS procedure is running.
+               // make sure DFS procedure won't start twice.
+               if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
+               {
+                       Result = FALSE;
+                       break;
+               }
+
+               // check the new channel carried from Channel Switch Announcemnet is valid.
+               for (i=0; i<pAd->ChannelListNum; i++)
+               {
+                       if ((Channel == pAd->ChannelList[i].Channel)
+                               &&(pAd->ChannelList[i].RemainingTimeForUse == 0))
+                       {
+                               // found radar signal in the channel. the channel can't use at least for 30 minutes.
+                               pAd->ChannelList[i].RemainingTimeForUse = 1800;//30 min = 1800 sec
+                               Result = TRUE;
+                               break;
+                       }
+               }
+       } while(FALSE);
+
+       return Result;
+}
+
+VOID NotifyChSwAnnToPeerAPs(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pRA,
+       IN PUCHAR pTA,
+       IN UINT8 ChSwMode,
+       IN UINT8 Channel)
+{
+#ifdef WDS_SUPPORT
+       if (!((pRA[0] & 0xff) == 0xff)) // is pRA a broadcase address.
+       {
+               INT i;
+               // info neighbor APs that Radar signal found throgh WDS link.
+               for (i = 0; i < MAX_WDS_ENTRY; i++)
+               {
+                       if (ValidWdsEntry(pAd, i))
+                       {
+                               PUCHAR pDA = pAd->WdsTab.WdsEntry[i].PeerWdsAddr;
+
+                               // DA equal to SA. have no necessary orignal AP which found Radar signal.
+                               if (MAC_ADDR_EQUAL(pTA, pDA))
+                                       continue;
+
+                               // send Channel Switch Action frame to info Neighbro APs.
+                               EnqueueChSwAnn(pAd, pDA, ChSwMode, Channel);
+                       }
+               }
+       }
+#endif // WDS_SUPPORT //
+}
+
+static VOID StartDFSProcedure(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR Channel,
+       IN UINT8 ChSwMode)
+{
+       // start DFS procedure
+       pAd->CommonCfg.Channel = Channel;
+#ifdef DOT11_N_SUPPORT
+       N_ChannelCheck(pAd);
+#endif // DOT11_N_SUPPORT //
+       pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
+       pAd->CommonCfg.RadarDetect.CSCount = 0;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Channel Switch Announcement action frame sanity check.
+
+       Parametrs:
+               1. MLME message containing the received frame
+               2. message length.
+               3. Channel switch announcement infomation buffer.
+
+
+       Return  : None.
+       ==========================================================================
+ */
+
+/*
+  Channel Switch Announcement IE.
+  +----+-----+-----------+------------+-----------+
+  | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
+  +----+-----+-----------+------------+-----------+
+    1    1        1           1            1
+*/
+static BOOLEAN PeerChSwAnnSanity(
+       IN PRTMP_ADAPTER pAd,
+       IN VOID *pMsg,
+       IN ULONG MsgLen,
+       OUT PCH_SW_ANN_INFO pChSwAnnInfo)
+{
+       PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
+       PUCHAR pFramePtr = Fr->Octet;
+       BOOLEAN result = FALSE;
+       PEID_STRUCT eid_ptr;
+
+       // skip 802.11 header.
+       MsgLen -= sizeof(HEADER_802_11);
+
+       // skip category and action code.
+       pFramePtr += 2;
+       MsgLen -= 2;
+
+       if (pChSwAnnInfo == NULL)
+               return result;
+
+       eid_ptr = (PEID_STRUCT)pFramePtr;
+       while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
+       {
+               switch(eid_ptr->Eid)
+               {
+                       case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
+                               NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1);
+                               NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1);
+                               NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1);
+
+                               result = TRUE;
+                break;
+
+                       default:
+                               break;
+               }
+               eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+       }
+
+       return result;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Measurement request action frame sanity check.
+
+       Parametrs:
+               1. MLME message containing the received frame
+               2. message length.
+               3. Measurement request infomation buffer.
+
+       Return  : None.
+       ==========================================================================
+ */
+static BOOLEAN PeerMeasureReqSanity(
+       IN PRTMP_ADAPTER pAd,
+       IN VOID *pMsg,
+       IN ULONG MsgLen,
+       OUT PUINT8 pDialogToken,
+       OUT PMEASURE_REQ_INFO pMeasureReqInfo)
+{
+       PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
+       PUCHAR pFramePtr = Fr->Octet;
+       BOOLEAN result = FALSE;
+       PEID_STRUCT eid_ptr;
+       PUCHAR ptr;
+       UINT64 MeasureStartTime;
+       UINT16 MeasureDuration;
+
+       // skip 802.11 header.
+       MsgLen -= sizeof(HEADER_802_11);
+
+       // skip category and action code.
+       pFramePtr += 2;
+       MsgLen -= 2;
+
+       if (pMeasureReqInfo == NULL)
+               return result;
+
+       NdisMoveMemory(pDialogToken, pFramePtr, 1);
+       pFramePtr += 1;
+       MsgLen -= 1;
+
+       eid_ptr = (PEID_STRUCT)pFramePtr;
+       while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
+       {
+               switch(eid_ptr->Eid)
+               {
+                       case IE_MEASUREMENT_REQUEST:
+                               NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1);
+                               NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1);
+                               NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1);
+                               ptr = eid_ptr->Octet + 3;
+                               NdisMoveMemory(&pMeasureReqInfo->MeasureReq.ChNum, ptr, 1);
+                               NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
+                               pMeasureReqInfo->MeasureReq.MeasureStartTime = SWAP64(MeasureStartTime);
+                               NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
+                               pMeasureReqInfo->MeasureReq.MeasureDuration = SWAP16(MeasureDuration);
+
+                               result = TRUE;
+                               break;
+
+                       default:
+                               break;
+               }
+               eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+       }
+
+       return result;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Measurement report action frame sanity check.
+
+       Parametrs:
+               1. MLME message containing the received frame
+               2. message length.
+               3. Measurement report infomation buffer.
+               4. basic report infomation buffer.
+
+       Return  : None.
+       ==========================================================================
+ */
+
+/*
+  Measurement Report IE.
+  +----+-----+-------+-------------+--------------+----------------+
+  | ID | Len | Token | Report Mode | Measure Type | Measure Report |
+  +----+-----+-------+-------------+--------------+----------------+
+    1     1      1          1             1            variable
+
+  Basic Report.
+  +--------+------------+----------+-----+
+  | Ch Num | Start Time | Duration | Map |
+  +--------+------------+----------+-----+
+      1          8           2        1
+
+  Map Field Bit Format.
+  +-----+---------------+---------------------+-------+------------+----------+
+  | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
+  +-----+---------------+---------------------+-------+------------+----------+
+     0          1                  2              3         4          5-7
+*/
+static BOOLEAN PeerMeasureReportSanity(
+       IN PRTMP_ADAPTER pAd,
+       IN VOID *pMsg,
+       IN ULONG MsgLen,
+       OUT PUINT8 pDialogToken,
+       OUT PMEASURE_REPORT_INFO pMeasureReportInfo,
+       OUT PUINT8 pReportBuf)
+{
+       PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
+       PUCHAR pFramePtr = Fr->Octet;
+       BOOLEAN result = FALSE;
+       PEID_STRUCT eid_ptr;
+       PUCHAR ptr;
+
+       // skip 802.11 header.
+       MsgLen -= sizeof(HEADER_802_11);
+
+       // skip category and action code.
+       pFramePtr += 2;
+       MsgLen -= 2;
+
+       if (pMeasureReportInfo == NULL)
+               return result;
+
+       NdisMoveMemory(pDialogToken, pFramePtr, 1);
+       pFramePtr += 1;
+       MsgLen -= 1;
+
+       eid_ptr = (PEID_STRUCT)pFramePtr;
+       while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
+       {
+               switch(eid_ptr->Eid)
+               {
+                       case IE_MEASUREMENT_REPORT:
+                               NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1);
+                               NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1);
+                               NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1);
+                               if (pMeasureReportInfo->ReportType == RM_BASIC)
+                               {
+                                       PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf;
+                                       ptr = eid_ptr->Octet + 3;
+                                       NdisMoveMemory(&pReport->ChNum, ptr, 1);
+                                       NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
+                                       NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
+                                       NdisMoveMemory(&pReport->Map, ptr + 11, 1);
+
+                               }
+                               else if (pMeasureReportInfo->ReportType == RM_CCA)
+                               {
+                                       PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf;
+                                       ptr = eid_ptr->Octet + 3;
+                                       NdisMoveMemory(&pReport->ChNum, ptr, 1);
+                                       NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
+                                       NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
+                                       NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1);
+
+                               }
+                               else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM)
+                               {
+                                       PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf;
+                                       ptr = eid_ptr->Octet + 3;
+                                       NdisMoveMemory(&pReport->ChNum, ptr, 1);
+                                       NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
+                                       NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
+                                       NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8);
+                               }
+                               result = TRUE;
+                break;
+
+                       default:
+                               break;
+               }
+               eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+       }
+
+       return result;
+}
+
+/*
+       ==========================================================================
+       Description:
+               TPC Request action frame sanity check.
+
+       Parametrs:
+               1. MLME message containing the received frame
+               2. message length.
+               3. Dialog Token.
+
+       Return  : None.
+       ==========================================================================
+ */
+static BOOLEAN PeerTpcReqSanity(
+       IN PRTMP_ADAPTER pAd,
+       IN VOID *pMsg,
+       IN ULONG MsgLen,
+       OUT PUINT8 pDialogToken)
+{
+       PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
+       PUCHAR pFramePtr = Fr->Octet;
+       BOOLEAN result = FALSE;
+       PEID_STRUCT eid_ptr;
+
+       MsgLen -= sizeof(HEADER_802_11);
+
+       // skip category and action code.
+       pFramePtr += 2;
+       MsgLen -= 2;
+
+       if (pDialogToken == NULL)
+               return result;
+
+       NdisMoveMemory(pDialogToken, pFramePtr, 1);
+       pFramePtr += 1;
+       MsgLen -= 1;
+
+       eid_ptr = (PEID_STRUCT)pFramePtr;
+       while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
+       {
+               switch(eid_ptr->Eid)
+               {
+                       case IE_TPC_REQUEST:
+                               result = TRUE;
+                break;
+
+                       default:
+                               break;
+               }
+               eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+       }
+
+       return result;
+}
+
+/*
+       ==========================================================================
+       Description:
+               TPC Report action frame sanity check.
+
+       Parametrs:
+               1. MLME message containing the received frame
+               2. message length.
+               3. Dialog Token.
+               4. TPC Report IE.
+
+       Return  : None.
+       ==========================================================================
+ */
+static BOOLEAN PeerTpcRepSanity(
+       IN PRTMP_ADAPTER pAd,
+       IN VOID *pMsg,
+       IN ULONG MsgLen,
+       OUT PUINT8 pDialogToken,
+       OUT PTPC_REPORT_INFO pTpcRepInfo)
+{
+       PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
+       PUCHAR pFramePtr = Fr->Octet;
+       BOOLEAN result = FALSE;
+       PEID_STRUCT eid_ptr;
+
+       MsgLen -= sizeof(HEADER_802_11);
+
+       // skip category and action code.
+       pFramePtr += 2;
+       MsgLen -= 2;
+
+       if (pDialogToken == NULL)
+               return result;
+
+       NdisMoveMemory(pDialogToken, pFramePtr, 1);
+       pFramePtr += 1;
+       MsgLen -= 1;
+
+       eid_ptr = (PEID_STRUCT)pFramePtr;
+       while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
+       {
+               switch(eid_ptr->Eid)
+               {
+                       case IE_TPC_REPORT:
+                               NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
+                               NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1);
+                               result = TRUE;
+                break;
+
+                       default:
+                               break;
+               }
+               eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+       }
+
+       return result;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Channel Switch Announcement action frame handler.
+
+       Parametrs:
+               Elme - MLME message containing the received frame
+
+       Return  : None.
+       ==========================================================================
+ */
+static VOID PeerChSwAnnAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       CH_SW_ANN_INFO ChSwAnnInfo;
+       PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
+#ifdef CONFIG_STA_SUPPORT
+       UCHAR index = 0, Channel = 0, NewChannel = 0;
+       ULONG Bssidx = 0;
+#endif // CONFIG_STA_SUPPORT //
+
+       NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
+       if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n"));
+               return;
+       }
+
+
+#ifdef CONFIG_STA_SUPPORT
+       if (pAd->OpMode == OPMODE_STA)
+       {
+               Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel);
+               if (Bssidx == BSS_NOT_FOUND)
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n"));
+                       return;
+               }
+
+               DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel));
+               hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6);
+
+               Channel = pAd->CommonCfg.Channel;
+               NewChannel = ChSwAnnInfo.Channel;
+
+               if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
+               {
+                       // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
+                       // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
+                       AsicSwitchChannel(pAd, 1, FALSE);
+                       AsicLockChannel(pAd, 1);
+                   LinkDown(pAd, FALSE);
+                       MlmeQueueInit(&pAd->Mlme.Queue);
+                       BssTableInit(&pAd->ScanTab);
+                   RTMPusecDelay(1000000);             // use delay to prevent STA do reassoc
+
+                       // channel sanity check
+                       for (index = 0 ; index < pAd->ChannelListNum; index++)
+                       {
+                               if (pAd->ChannelList[index].Channel == NewChannel)
+                               {
+                                       pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
+                                       pAd->CommonCfg.Channel = NewChannel;
+                                       AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+                                       AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
+                                       break;
+                               }
+                       }
+
+                       if (index >= pAd->ChannelListNum)
+                       {
+                               DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
+                       }
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       return;
+}
+
+
+/*
+       ==========================================================================
+       Description:
+               Measurement Request action frame handler.
+
+       Parametrs:
+               Elme - MLME message containing the received frame
+
+       Return  : None.
+       ==========================================================================
+ */
+static VOID PeerMeasureReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
+       UINT8 DialogToken;
+       MEASURE_REQ_INFO MeasureReqInfo;
+       MEASURE_REPORT_MODE ReportMode;
+
+       if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo))
+       {
+               ReportMode.word = 0;
+               ReportMode.field.Incapable = 1;
+               EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL);
+       }
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Measurement Report action frame handler.
+
+       Parametrs:
+               Elme - MLME message containing the received frame
+
+       Return  : None.
+       ==========================================================================
+ */
+static VOID PeerMeasureReportAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       MEASURE_REPORT_INFO MeasureReportInfo;
+       PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
+       UINT8 DialogToken;
+       PUINT8 pMeasureReportInfo;
+
+//     if (pAd->CommonCfg.bIEEE80211H != TRUE)
+//             return;
+
+       if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __FUNCTION__, sizeof(MEASURE_RPI_REPORT)));
+               return;
+       }
+
+       NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO));
+       NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT));
+       if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo))
+       {
+               do {
+                       PMEASURE_REQ_ENTRY pEntry = NULL;
+
+                       // Not a autonomous measure report.
+                       // check the dialog token field. drop it if the dialog token doesn't match.
+                       if ((DialogToken != 0)
+                               && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL))
+                               break;
+
+                       if (pEntry != NULL)
+                               MeasureReqDelete(pAd, pEntry->DialogToken);
+
+                       if (MeasureReportInfo.ReportType == RM_BASIC)
+                       {
+                               PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo;
+                               if ((pBasicReport->Map.field.Radar)
+                                       && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE))
+                               {
+                                       NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum);
+                                       StartDFSProcedure(pAd, pBasicReport->ChNum, 1);
+                               }
+                       }
+               } while (FALSE);
+       }
+       else
+               DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n"));
+
+       kfree(pMeasureReportInfo);
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               TPC Request action frame handler.
+
+       Parametrs:
+               Elme - MLME message containing the received frame
+
+       Return  : None.
+       ==========================================================================
+ */
+static VOID PeerTpcReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
+       PUCHAR pFramePtr = pFr->Octet;
+       UINT8 DialogToken;
+       UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
+       UINT8 LinkMargin = 0;
+       CHAR RealRssi;
+
+       // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The
+       //                              STA may incorporate rate information and channel conditions, including interference, into its computation
+       //                              of link margin.
+
+       RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
+                                                               ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
+                                                               ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
+
+       // skip Category and action code.
+       pFramePtr += 2;
+
+       // Dialog token.
+       NdisMoveMemory(&DialogToken, pFramePtr, 1);
+
+       LinkMargin = (RealRssi / MIN_RCV_PWR);
+       if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
+               EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin);
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               TPC Report action frame handler.
+
+       Parametrs:
+               Elme - MLME message containing the received frame
+
+       Return  : None.
+       ==========================================================================
+ */
+static VOID PeerTpcRepAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UINT8 DialogToken;
+       TPC_REPORT_INFO TpcRepInfo;
+       PTPC_REQ_ENTRY pEntry = NULL;
+
+       NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
+       if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo))
+       {
+               if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL)
+               {
+                       TpcReqDelete(pAd, pEntry->DialogToken);
+                       DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
+                               __FUNCTION__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin));
+               }
+       }
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Spectrun action frames Handler such as channel switch annoucement,
+               measurement report, measurement request actions frames.
+
+       Parametrs:
+               Elme - MLME message containing the received frame
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID PeerSpectrumAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+
+       UCHAR   Action = Elem->Msg[LENGTH_802_11+1];
+
+       if (pAd->CommonCfg.bIEEE80211H != TRUE)
+               return;
+
+       switch(Action)
+       {
+               case SPEC_MRQ:
+                       // current rt2860 unable do such measure specified in Measurement Request.
+                       // reject all measurement request.
+                       PeerMeasureReqAction(pAd, Elem);
+                       break;
+
+               case SPEC_MRP:
+                       PeerMeasureReportAction(pAd, Elem);
+                       break;
+
+               case SPEC_TPCRQ:
+                       PeerTpcReqAction(pAd, Elem);
+                       break;
+
+               case SPEC_TPCRP:
+                       PeerTpcRepAction(pAd, Elem);
+                       break;
+
+               case SPEC_CHANNEL_SWITCH:
+{
+#ifdef DOT11N_DRAFT3
+                               SEC_CHA_OFFSET_IE       Secondary;
+                               CHA_SWITCH_ANNOUNCE_IE  ChannelSwitch;
+
+                               // 802.11h only has Channel Switch Announcement IE.
+                               RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE));
+
+                               // 802.11n D3.03 adds secondary channel offset element in the end.
+                               if (Elem->MsgLen ==  (LENGTH_802_11 + 2 + sizeof (CHA_SWITCH_ANNOUNCE_IE) + sizeof (SEC_CHA_OFFSET_IE)))
+                               {
+                                       RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE));
+                               }
+                               else
+                               {
+                                       Secondary.SecondaryChannelOffset = 0;
+                               }
+
+                               if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3))
+                               {
+                                       ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset);
+                               }
+#endif // DOT11N_DRAFT3 //
+}
+                       PeerChSwAnnAction(pAd, Elem);
+                       break;
+       }
+
+       return;
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       Parametrs:
+
+       Return  : None.
+       ==========================================================================
+ */
+INT Set_MeasureReq_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UINT Aid = 1;
+       UINT ArgIdx;
+       PUCHAR thisChar;
+
+       MEASURE_REQ_MODE MeasureReqMode;
+       UINT8 MeasureReqToken = RandomByte(pAd);
+       UINT8 MeasureReqType = RM_BASIC;
+       UINT8 MeasureCh = 1;
+
+       ArgIdx = 1;
+       while ((thisChar = strsep((char **)&arg, "-")) != NULL)
+       {
+               switch(ArgIdx)
+               {
+                       case 1: // Aid.
+                               Aid = simple_strtol(thisChar, 0, 16);
+                               break;
+
+                       case 2: // Measurement Request Type.
+                               MeasureReqType = simple_strtol(thisChar, 0, 16);
+                               if (MeasureReqType > 3)
+                               {
+                                       DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __FUNCTION__, MeasureReqType));
+                                       return TRUE;
+                               }
+                               break;
+
+                       case 3: // Measurement channel.
+                               MeasureCh = simple_strtol(thisChar, 0, 16);
+                               break;
+               }
+               ArgIdx++;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __FUNCTION__, Aid, MeasureReqType, MeasureCh));
+       if (!VALID_WCID(Aid))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid));
+               return TRUE;
+       }
+
+       MeasureReqMode.word = 0;
+       MeasureReqMode.field.Enable = 1;
+
+       MeasureReqInsert(pAd, MeasureReqToken);
+
+       EnqueueMeasurementReq(pAd, pAd->MacTab.Content[Aid].Addr,
+               MeasureReqToken, MeasureReqMode.word, MeasureReqType, MeasureCh, 2000);
+
+       return TRUE;
+}
+
+INT Set_TpcReq_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UINT Aid;
+
+       UINT8 TpcReqToken = RandomByte(pAd);
+
+       Aid = simple_strtol(arg, 0, 16);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __FUNCTION__, Aid));
+       if (!VALID_WCID(Aid))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid));
+               return TRUE;
+       }
+
+       TpcReqInsert(pAd, TpcReqToken);
+
+       EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
+
+       return TRUE;
+}
+
diff --git a/drivers/staging/rt2870/dfs.h b/drivers/staging/rt2870/dfs.h
new file mode 100644 (file)
index 0000000..752a635
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    dfs.h
+
+    Abstract:
+    Support DFS function.
+
+    Revision History:
+    Who       When            What
+    --------  ----------      ----------------------------------------------
+    Fonchi    03-12-2007      created
+*/
+
+#define RADAR_PULSE 1
+#define RADAR_WIDTH 2
+
+#define WIDTH_RD_IDLE 0
+#define WIDTH_RD_CHECK 1
+
+
+VOID BbpRadarDetectionStart(
+       IN PRTMP_ADAPTER pAd);
+
+VOID BbpRadarDetectionStop(
+       IN PRTMP_ADAPTER pAd);
+
+VOID RadarDetectionStart(
+       IN PRTMP_ADAPTER pAd,
+       IN BOOLEAN CTS_Protect,
+       IN UINT8 CTSPeriod);
+
+VOID RadarDetectionStop(
+       IN PRTMP_ADAPTER        pAd);
+
+VOID RadarDetectPeriodic(
+       IN PRTMP_ADAPTER        pAd);
+
+
+BOOLEAN RadarChannelCheck(
+       IN PRTMP_ADAPTER        pAd,
+       IN UCHAR                        Ch);
+
+ULONG JapRadarType(
+       IN PRTMP_ADAPTER pAd);
+
+ULONG RTMPBbpReadRadarDuration(
+       IN PRTMP_ADAPTER        pAd);
+
+ULONG RTMPReadRadarDuration(
+       IN PRTMP_ADAPTER        pAd);
+
+VOID RTMPCleanRadarDuration(
+       IN PRTMP_ADAPTER        pAd);
+
+VOID RTMPPrepareRDCTSFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pDA,
+       IN      ULONG                   Duration,
+       IN  UCHAR           RTSRate,
+       IN  ULONG           CTSBaseAddr,
+       IN  UCHAR                       FrameGap);
+
+VOID RTMPPrepareRadarDetectParams(
+       IN PRTMP_ADAPTER        pAd);
+
+
+INT Set_ChMovingTime_Proc(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR arg);
+
+INT Set_LongPulseRadarTh_Proc(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR arg);
+
+
diff --git a/drivers/staging/rt2870/leap.h b/drivers/staging/rt2870/leap.h
new file mode 100644 (file)
index 0000000..6818c1f
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       leap.h
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Name            Date                    Modification logs
+*/
+#ifndef __LEAP_H__
+#define __LEAP_H__
+
+// Messages for Associate state machine
+#define LEAP_MACHINE_BASE                   30
+
+#define LEAP_MSG_REQUEST_IDENTITY           31
+#define LEAP_MSG_REQUEST_LEAP               32
+#define LEAP_MSG_SUCCESS                    33
+#define LEAP_MSG_FAILED                     34
+#define LEAP_MSG_RESPONSE_LEAP              35
+#define LEAP_MSG_EAPOLKEY                   36
+#define LEAP_MSG_UNKNOWN                    37
+#define LEAP_MSG                            38
+//! assoc state-machine states
+#define LEAP_IDLE                           0
+#define LEAP_WAIT_IDENTITY_REQUEST          1
+#define LEAP_WAIT_CHANLLENGE_REQUEST        2
+#define LEAP_WAIT_SUCCESS                   3
+#define LEAP_WAIT_CHANLLENGE_RESPONSE       4
+#define LEAP_WAIT_EAPOLKEY                  5
+
+#define LEAP_REASON_INVALID_AUTH                    0x01
+#define LEAP_REASON_AUTH_TIMEOUT                    0x02
+#define LEAP_REASON_CHALLENGE_FROM_AP_FAILED        0x03
+#define LEAP_REASON_CHALLENGE_TO_AP_FAILED          0x04
+
+#define CISCO_AuthModeLEAP                          0x80
+#define CISCO_AuthModeLEAPNone                      0x00
+#define LEAP_AUTH_TIMEOUT                           30000
+#define LEAP_CHALLENGE_RESPONSE_LENGTH              24
+#define LEAP_CHALLENGE_REQUEST_LENGTH               8
+
+typedef struct _LEAP_EAPOL_HEADER_ {
+    UCHAR       Version;
+    UCHAR       Type;
+    UCHAR       Length[2];
+} LEAP_EAPOL_HEADER, *PLEAP_EAPOL_HEADER;
+
+typedef struct _LEAP_EAPOL_PACKET_ {
+    UCHAR       Code;
+    UCHAR       Identifier;
+    UCHAR       Length[2];
+    UCHAR       Type;
+} LEAP_EAPOL_PACKET, *PLEAP_EAPOL_PACKET;
+
+typedef struct _LEAP_EAP_CONTENTS_ {
+    UCHAR       Version;
+    UCHAR       Reserved;
+    UCHAR       Length;
+} LEAP_EAP_CONTENTS, *PLEAP_EAP_CONTENTS;
+
+/*** EAPOL key ***/
+typedef struct _EAPOL_KEY_HEADER_ {
+    UCHAR       Type;
+    UCHAR       Length[2];
+    UCHAR       Counter[8];
+    UCHAR       IV[16];
+    UCHAR       Index;
+    UCHAR       Signature[16];
+} EAPOL_KEY_HEADER, *PEAPOL_KEY_HEADER;
+
+BOOLEAN LeapMsgTypeSubst(
+    IN  UCHAR   EAPType,
+    OUT ULONG   *MsgType);
+
+VOID LeapMachinePerformAction(
+    IN PRTMP_ADAPTER    pAd,
+    IN STATE_MACHINE    *S,
+    IN MLME_QUEUE_ELEM  *Elem);
+
+VOID LeapMacHeaderInit(
+    IN  PRTMP_ADAPTER       pAd,
+    IN  OUT PHEADER_802_11  pHdr80211,
+    IN  UCHAR               wep,
+    IN  PUCHAR              pAddr3);
+
+VOID LeapStartAction(
+    IN PRTMP_ADAPTER    pAd,
+    IN MLME_QUEUE_ELEM  *Elem);
+
+VOID LeapIdentityAction(
+    IN PRTMP_ADAPTER    pAd,
+    IN MLME_QUEUE_ELEM  *Elem);
+
+VOID LeapPeerChallengeAction(
+    IN PRTMP_ADAPTER    pAd,
+    IN MLME_QUEUE_ELEM  *Elem);
+
+VOID HashPwd(
+    IN  PUCHAR  pwd,
+    IN  INT     pwdlen,
+    OUT PUCHAR  hash);
+
+VOID PeerChallengeResponse(
+    IN  PUCHAR  szChallenge,
+    IN  PUCHAR  smbPasswd,
+    OUT PUCHAR  szResponse);
+
+VOID ParityKey(
+    OUT PUCHAR  szOut,
+    IN  PUCHAR  szIn);
+
+VOID DesKey(
+    OUT ULONG   k[16][2],
+    IN  PUCHAR  key,
+    IN  INT     decrypt);
+
+VOID Des(
+    IN  ULONG   ks[16][2],
+    OUT UCHAR   block[8]);
+
+VOID DesEncrypt(
+    IN  PUCHAR  szClear,
+    IN  PUCHAR  szKey,
+    OUT PUCHAR  szOut);
+
+VOID LeapNetworkChallengeAction(
+    IN PRTMP_ADAPTER    pAd,
+    IN MLME_QUEUE_ELEM  *Elem);
+
+VOID LeapNetworkChallengeResponse(
+    IN PRTMP_ADAPTER    pAd,
+    IN MLME_QUEUE_ELEM  *Elem);
+
+VOID HashpwdHash(
+    IN  PUCHAR  hash,
+    IN  PUCHAR  hashhash);
+
+VOID ProcessSessionKey(
+    OUT PUCHAR  SessionKey,
+    IN  PUCHAR  hash2,
+    IN  PUCHAR  ChallengeToRadius,
+    IN  PUCHAR  ChallengeResponseFromRadius,
+    IN  PUCHAR  ChallengeFromRadius,
+    IN  PUCHAR  ChallengeResponseToRadius);
+
+VOID LeapEapolKeyAction(
+    IN PRTMP_ADAPTER    pAd,
+    IN MLME_QUEUE_ELEM  *Elem);
+
+VOID RogueApTableInit(
+    IN ROGUEAP_TABLE    *Tab);
+
+ULONG RogueApTableSearch(
+    IN ROGUEAP_TABLE    *Tab,
+    IN PUCHAR           pAddr);
+
+VOID RogueApEntrySet(
+    IN  PRTMP_ADAPTER   pAd,
+    OUT ROGUEAP_ENTRY   *pRogueAp,
+    IN PUCHAR           pAddr,
+    IN UCHAR            FaileCode);
+
+ULONG RogueApTableSetEntry(
+    IN  PRTMP_ADAPTER   pAd,
+    OUT ROGUEAP_TABLE  *Tab,
+    IN PUCHAR           pAddr,
+    IN UCHAR            FaileCode);
+
+VOID RogueApTableDeleteEntry(
+    IN OUT ROGUEAP_TABLE *Tab,
+    IN PUCHAR          pAddr);
+
+VOID LeapAuthTimeout(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3);
+
+VOID LeapSendRogueAPReport(
+    IN  PRTMP_ADAPTER   pAd);
+
+BOOLEAN CCKMAssocRspSanity(
+    IN PRTMP_ADAPTER    pAd,
+    IN VOID             *Msg,
+    IN ULONG            MsgLen);
+
+#endif  // __LEAP_H__
diff --git a/drivers/staging/rt2870/link_list.h b/drivers/staging/rt2870/link_list.h
new file mode 100644 (file)
index 0000000..f652113
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#ifndef __LINK_LIST_H__
+#define __LINK_LIST_H__
+
+typedef struct _LIST_ENTRY
+{
+       struct _LIST_ENTRY *pNext;
+} LIST_ENTRY, *PLIST_ENTRY;
+
+typedef struct _LIST_HEADR
+{
+       PLIST_ENTRY pHead;
+       PLIST_ENTRY pTail;
+       UCHAR size;
+} LIST_HEADER, *PLIST_HEADER;
+
+static inline VOID initList(
+       IN PLIST_HEADER pList)
+{
+       pList->pHead = pList->pTail = NULL;
+       pList->size = 0;
+       return;
+}
+
+static inline VOID insertTailList(
+       IN PLIST_HEADER pList,
+       IN PLIST_ENTRY pEntry)
+{
+       pEntry->pNext = NULL;
+       if (pList->pTail)
+               pList->pTail->pNext = pEntry;
+       else
+               pList->pHead = pEntry;
+       pList->pTail = pEntry;
+       pList->size++;
+
+       return;
+}
+
+static inline PLIST_ENTRY removeHeadList(
+       IN PLIST_HEADER pList)
+{
+       PLIST_ENTRY pNext;
+       PLIST_ENTRY pEntry;
+
+       pEntry = pList->pHead;
+       if (pList->pHead != NULL)
+       {
+               pNext = pList->pHead->pNext;
+               pList->pHead = pNext;
+               if (pNext == NULL)
+                       pList->pTail = NULL;
+               pList->size--;
+       }
+       return pEntry;
+}
+
+static inline int getListSize(
+       IN PLIST_HEADER pList)
+{
+       return pList->size;
+}
+
+static inline PLIST_ENTRY delEntryList(
+       IN PLIST_HEADER pList,
+       IN PLIST_ENTRY pEntry)
+{
+       PLIST_ENTRY pCurEntry;
+       PLIST_ENTRY pPrvEntry;
+
+       if(pList->pHead == NULL)
+               return NULL;
+
+       if(pEntry == pList->pHead)
+       {
+               pCurEntry = pList->pHead;
+               pList->pHead = pCurEntry->pNext;
+
+               if(pList->pHead == NULL)
+                       pList->pTail = NULL;
+
+               pList->size--;
+               return pCurEntry;
+       }
+
+       pPrvEntry = pList->pHead;
+       pCurEntry = pPrvEntry->pNext;
+       while(pCurEntry != NULL)
+       {
+               if (pEntry == pCurEntry)
+               {
+                       pPrvEntry->pNext = pCurEntry->pNext;
+
+                       if(pEntry == pList->pTail)
+                               pList->pTail = pPrvEntry;
+
+                       pList->size--;
+                       break;
+               }
+               pPrvEntry = pCurEntry;
+               pCurEntry = pPrvEntry->pNext;
+       }
+
+       return pCurEntry;
+}
+
+#endif // ___LINK_LIST_H__ //
+
diff --git a/drivers/staging/rt2870/md4.h b/drivers/staging/rt2870/md4.h
new file mode 100644 (file)
index 0000000..f1e5b52
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#ifndef __MD4_H__
+#define __MD4_H__
+
+/* MD4 context. */
+typedef        struct  _MD4_CTX_       {
+       ULONG   state[4];        /* state (ABCD) */
+       ULONG   count[2];        /* number of bits, modulo 2^64 (lsb first) */
+       UCHAR   buffer[64];      /* input buffer */
+}      MD4_CTX;
+
+VOID MD4Init (MD4_CTX *);
+VOID MD4Update (MD4_CTX *, PUCHAR, UINT);
+VOID MD4Final (UCHAR [16], MD4_CTX *);
+
+#endif //__MD4_H__
\ No newline at end of file
diff --git a/drivers/staging/rt2870/md5.h b/drivers/staging/rt2870/md5.h
new file mode 100644 (file)
index 0000000..d85db12
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       md5.h
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Name            Date                    Modification logs
+       jan                     10-28-03                Initial
+       Rita            11-23-04                Modify MD5 and SHA-1
+*/
+
+#ifndef        uint8
+#define        uint8  unsigned char
+#endif
+
+#ifndef        uint32
+#define        uint32 unsigned long int
+#endif
+
+
+#ifndef        __MD5_H__
+#define        __MD5_H__
+
+#define MD5_MAC_LEN 16
+
+typedef struct _MD5_CTX {
+    UINT32   Buf[4];             // buffers of four states
+       UCHAR   Input[64];          // input message
+       UINT32   LenInBitCount[2];   // length counter for input message, 0 up to 64 bits
+}   MD5_CTX;
+
+VOID MD5Init(MD5_CTX *pCtx);
+VOID MD5Update(MD5_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes);
+VOID MD5Final(UCHAR Digest[16], MD5_CTX *pCtx);
+VOID MD5Transform(UINT32 Buf[4], UINT32 Mes[16]);
+
+void md5_mac(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac);
+void hmac_md5(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac);
+
+//
+// SHA context
+//
+typedef        struct _SHA_CTX
+{
+       UINT32   Buf[5];             // buffers of five states
+       UCHAR   Input[80];          // input message
+       UINT32   LenInBitCount[2];   // length counter for input message, 0 up to 64 bits
+
+}      SHA_CTX;
+
+VOID SHAInit(SHA_CTX *pCtx);
+UCHAR SHAUpdate(SHA_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes);
+VOID SHAFinal(SHA_CTX *pCtx, UCHAR Digest[20]);
+VOID SHATransform(UINT32 Buf[5], UINT32 Mes[20]);
+
+#define SHA_DIGEST_LEN 20
+#endif // __MD5_H__
+
+/******************************************************************************/
+#ifndef        _AES_H
+#define        _AES_H
+
+typedef        struct
+{
+       uint32 erk[64];         /* encryption round     keys */
+       uint32 drk[64];         /* decryption round     keys */
+       int     nr;                             /* number of rounds     */
+}
+aes_context;
+
+int     rtmp_aes_set_key( aes_context *ctx,    uint8 *key,     int     nbits );
+void rtmp_aes_encrypt( aes_context *ctx,       uint8 input[16], uint8 output[16] );
+void rtmp_aes_decrypt( aes_context *ctx,       uint8 input[16], uint8 output[16] );
+
+void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output);
+int PasswordHash(char *password, unsigned char *ssid, int ssidlength, unsigned char *output);
+
+#endif /* aes.h        */
+
diff --git a/drivers/staging/rt2870/mlme.h b/drivers/staging/rt2870/mlme.h
new file mode 100644 (file)
index 0000000..52fb8e1
--- /dev/null
@@ -0,0 +1,1471 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       mlme.h
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       John Chang      2003-08-28              Created
+       John Chang  2004-09-06      modified for RT2600
+
+*/
+#ifndef __MLME_H__
+#define __MLME_H__
+
+//extern UCHAR BROADCAST_ADDR[];
+
+// maximum supported capability information -
+// ESS, IBSS, Privacy, Short Preamble, Spectrum mgmt, Short Slot
+#define SUPPORTED_CAPABILITY_INFO   0x0533
+
+#define END_OF_ARGS                 -1
+#define LFSR_MASK                   0x80000057
+#define MLME_TASK_EXEC_INTV         100/*200*/       //
+#define LEAD_TIME                   5
+#define MLME_TASK_EXEC_MULTIPLE       10  /*5*/       // MLME_TASK_EXEC_MULTIPLE * MLME_TASK_EXEC_INTV = 1 sec
+#define REORDER_EXEC_INTV              100       // 0.1 sec
+//#define TBTT_PRELOAD_TIME         384        // usec. LomgPreamble + 24-byte at 1Mbps
+
+// The definition of Radar detection duration region
+#define CE             0
+#define FCC            1
+#define JAP            2
+#define JAP_W53        3
+#define JAP_W56        4
+#define MAX_RD_REGION 5
+
+#ifdef NDIS51_MINIPORT
+#define BEACON_LOST_TIME            4000       // 2048 msec = 2 sec
+#else
+#define BEACON_LOST_TIME            4 * OS_HZ    // 2048 msec = 2 sec
+#endif
+
+#define DLS_TIMEOUT                 1200      // unit: msec
+#define AUTH_TIMEOUT                300       // unit: msec
+#define ASSOC_TIMEOUT               300       // unit: msec
+#define JOIN_TIMEOUT                2 * OS_HZ      // unit: msec
+#define SHORT_CHANNEL_TIME          90        // unit: msec
+#define MIN_CHANNEL_TIME            110        // unit: msec, for dual band scan
+#define MAX_CHANNEL_TIME            140       // unit: msec, for single band scan
+#define        FAST_ACTIVE_SCAN_TIME       30            // Active scan waiting for probe response time
+#define CW_MIN_IN_BITS              4         // actual CwMin = 2^CW_MIN_IN_BITS - 1
+
+
+#ifdef CONFIG_STA_SUPPORT
+#ifndef CONFIG_AP_SUPPORT
+#define CW_MAX_IN_BITS              10        // actual CwMax = 2^CW_MAX_IN_BITS - 1
+#endif
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+extern UINT32 CW_MAX_IN_BITS;
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+// Note: RSSI_TO_DBM_OFFSET has been changed to variable for new RF (2004-0720).
+// SHould not refer to this constant anymore
+//#define RSSI_TO_DBM_OFFSET          120 // for RT2530 RSSI-115 = dBm
+#define RSSI_FOR_MID_TX_POWER       -55  // -55 db is considered mid-distance
+#define RSSI_FOR_LOW_TX_POWER       -45  // -45 db is considered very short distance and
+                                        // eligible to use a lower TX power
+#define RSSI_FOR_LOWEST_TX_POWER    -30
+//#define MID_TX_POWER_DELTA          0   // 0 db from full TX power upon mid-distance to AP
+#define LOW_TX_POWER_DELTA          6    // -3 db from full TX power upon very short distance. 1 grade is 0.5 db
+#define LOWEST_TX_POWER_DELTA       16   // -8 db from full TX power upon shortest distance. 1 grade is 0.5 db
+
+#define RSSI_TRIGGERED_UPON_BELOW_THRESHOLD     0
+#define RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD   1
+#define RSSI_THRESHOLD_FOR_ROAMING              25
+#define RSSI_DELTA                              5
+
+// Channel Quality Indication
+#define CQI_IS_GOOD(cqi)            ((cqi) >= 50)
+//#define CQI_IS_FAIR(cqi)          (((cqi) >= 20) && ((cqi) < 50))
+#define CQI_IS_POOR(cqi)            (cqi < 50)  //(((cqi) >= 5) && ((cqi) < 20))
+#define CQI_IS_BAD(cqi)             (cqi < 5)
+#define CQI_IS_DEAD(cqi)            (cqi == 0)
+
+// weighting factor to calculate Channel quality, total should be 100%
+#define RSSI_WEIGHTING                   50
+#define TX_WEIGHTING                     30
+#define RX_WEIGHTING                     20
+
+//#define PEER_KEY_NOT_USED                0
+//#define PEER_KEY_64_BIT                  64
+//#define PEER_KEY_128_BIT                 128
+
+//#define PEER_KEY_64BIT_LEN               8
+//#define PEER_KEY_128BIT_LEN              16
+
+#define BSS_NOT_FOUND                    0xFFFFFFFF
+
+
+#ifdef CONFIG_STA_SUPPORT
+#define MAX_LEN_OF_MLME_QUEUE            40 //10
+#endif // CONFIG_STA_SUPPORT //
+
+#define SCAN_PASSIVE                     18            // scan with no probe request, only wait beacon and probe response
+#define SCAN_ACTIVE                      19            // scan with probe request, and wait beacon and probe response
+#define        SCAN_CISCO_PASSIVE                               20             // Single channel passive scan
+#define        SCAN_CISCO_ACTIVE                                21             // Single channel active scan
+#define        SCAN_CISCO_NOISE                                 22             // Single channel passive scan for noise histogram collection
+#define        SCAN_CISCO_CHANNEL_LOAD                  23             // Single channel passive scan for channel load collection
+#define FAST_SCAN_ACTIVE                 24            // scan with probe request, and wait beacon and probe response
+
+#ifdef DOT11N_DRAFT3
+#define SCAN_2040_BSS_COEXIST                  26
+#endif // DOT11N_DRAFT3 //
+
+//#define BSS_TABLE_EMPTY(x)             ((x).BssNr == 0)
+#define MAC_ADDR_IS_GROUP(Addr)       (((Addr[0]) & 0x01))
+#define MAC_ADDR_HASH(Addr)            (Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5])
+#define MAC_ADDR_HASH_INDEX(Addr)      (MAC_ADDR_HASH(Addr) % HASH_TABLE_SIZE)
+#define TID_MAC_HASH(Addr,TID)            (TID^Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5])
+#define TID_MAC_HASH_INDEX(Addr,TID)      (TID_MAC_HASH(Addr,TID) % HASH_TABLE_SIZE)
+
+// LED Control
+// assoiation ON. one LED ON. another blinking when TX, OFF when idle
+// no association, both LED off
+#define ASIC_LED_ACT_ON(pAd)        RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00031e46)
+#define ASIC_LED_ACT_OFF(pAd)       RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00001e46)
+
+// bit definition of the 2-byte pBEACON->Capability field
+#define CAP_IS_ESS_ON(x)                 (((x) & 0x0001) != 0)
+#define CAP_IS_IBSS_ON(x)                (((x) & 0x0002) != 0)
+#define CAP_IS_CF_POLLABLE_ON(x)         (((x) & 0x0004) != 0)
+#define CAP_IS_CF_POLL_REQ_ON(x)         (((x) & 0x0008) != 0)
+#define CAP_IS_PRIVACY_ON(x)             (((x) & 0x0010) != 0)
+#define CAP_IS_SHORT_PREAMBLE_ON(x)      (((x) & 0x0020) != 0)
+#define CAP_IS_PBCC_ON(x)                (((x) & 0x0040) != 0)
+#define CAP_IS_AGILITY_ON(x)             (((x) & 0x0080) != 0)
+#define CAP_IS_SPECTRUM_MGMT(x)          (((x) & 0x0100) != 0)  // 802.11e d9
+#define CAP_IS_QOS(x)                    (((x) & 0x0200) != 0)  // 802.11e d9
+#define CAP_IS_SHORT_SLOT(x)             (((x) & 0x0400) != 0)
+#define CAP_IS_APSD(x)                   (((x) & 0x0800) != 0)  // 802.11e d9
+#define CAP_IS_IMMED_BA(x)               (((x) & 0x1000) != 0)  // 802.11e d9
+#define CAP_IS_DSSS_OFDM(x)              (((x) & 0x2000) != 0)
+#define CAP_IS_DELAY_BA(x)               (((x) & 0x4000) != 0)  // 802.11e d9
+
+#define CAP_GENERATE(ess,ibss,priv,s_pre,s_slot,spectrum)  (((ess) ? 0x0001 : 0x0000) | ((ibss) ? 0x0002 : 0x0000) | ((priv) ? 0x0010 : 0x0000) | ((s_pre) ? 0x0020 : 0x0000) | ((s_slot) ? 0x0400 : 0x0000) | ((spectrum) ? 0x0100 : 0x0000))
+
+//#define STA_QOS_CAPABILITY               0 // 1-byte. see 802.11e d9.0 for bit definition
+
+#define ERP_IS_NON_ERP_PRESENT(x)        (((x) & 0x01) != 0)    // 802.11g
+#define ERP_IS_USE_PROTECTION(x)         (((x) & 0x02) != 0)    // 802.11g
+#define ERP_IS_USE_BARKER_PREAMBLE(x)    (((x) & 0x04) != 0)    // 802.11g
+
+#define DRS_TX_QUALITY_WORST_BOUND       8// 3  // just test by gary
+#define DRS_PENALTY                      8
+
+#define BA_NOTUSE      2
+//BA Policy subfiled value in ADDBA frame
+#define IMMED_BA       1
+#define DELAY_BA       0
+
+// BA Initiator subfield in DELBA frame
+#define ORIGINATOR     1
+#define RECIPIENT      0
+
+// ADDBA Status Code
+#define ADDBA_RESULTCODE_SUCCESS                                       0
+#define ADDBA_RESULTCODE_REFUSED                                       37
+#define ADDBA_RESULTCODE_INVALID_PARAMETERS                    38
+
+// DELBA Reason Code
+#define DELBA_REASONCODE_QSTA_LEAVING                          36
+#define DELBA_REASONCODE_END_BA                                                37
+#define DELBA_REASONCODE_UNKNOWN_BA                                    38
+#define DELBA_REASONCODE_TIMEOUT                                       39
+
+// reset all OneSecTx counters
+#define RESET_ONE_SEC_TX_CNT(__pEntry) \
+if (((__pEntry)) != NULL) \
+{ \
+       (__pEntry)->OneSecTxRetryOkCount = 0; \
+       (__pEntry)->OneSecTxFailCount = 0; \
+       (__pEntry)->OneSecTxNoRetryOkCount = 0; \
+}
+
+//
+// 802.11 frame formats
+//
+//  HT Capability INFO field in HT Cap IE .
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+       USHORT  LSIGTxopProSup:1;
+       USHORT  Forty_Mhz_Intolerant:1;
+       USHORT  PSMP:1;
+       USHORT  CCKmodein40:1;
+       USHORT  AMsduSize:1;
+       USHORT  DelayedBA:1;    //rt2860c not support
+       USHORT  RxSTBC:2;
+       USHORT  TxSTBC:1;
+       USHORT  ShortGIfor40:1; //for40MHz
+       USHORT  ShortGIfor20:1;
+       USHORT  GF:1;   //green field
+       USHORT  MimoPs:2;//momi power safe
+       USHORT  ChannelWidth:1;
+       USHORT  AdvCoding:1;
+#else
+       USHORT  AdvCoding:1;
+       USHORT  ChannelWidth:1;
+       USHORT  MimoPs:2;//momi power safe
+       USHORT  GF:1;   //green field
+       USHORT  ShortGIfor20:1;
+       USHORT  ShortGIfor40:1; //for40MHz
+       USHORT  TxSTBC:1;
+       USHORT  RxSTBC:2;
+       USHORT  DelayedBA:1;    //rt2860c not support
+       USHORT  AMsduSize:1;    // only support as zero
+       USHORT  CCKmodein40:1;
+       USHORT  PSMP:1;
+       USHORT  Forty_Mhz_Intolerant:1;
+       USHORT  LSIGTxopProSup:1;
+#endif /* !RT_BIG_ENDIAN */
+} HT_CAP_INFO, *PHT_CAP_INFO;
+
+//  HT Capability INFO field in HT Cap IE .
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+       UCHAR   rsv:3;//momi power safe
+       UCHAR   MpduDensity:3;
+       UCHAR   MaxRAmpduFactor:2;
+#else
+       UCHAR   MaxRAmpduFactor:2;
+       UCHAR   MpduDensity:3;
+       UCHAR   rsv:3;//momi power safe
+#endif /* !RT_BIG_ENDIAN */
+} HT_CAP_PARM, *PHT_CAP_PARM;
+
+//  HT Capability INFO field in HT Cap IE .
+typedef struct PACKED {
+       UCHAR   MCSSet[10];
+       UCHAR   SupRate[2];  // unit : 1Mbps
+#ifdef RT_BIG_ENDIAN
+       UCHAR   rsv:3;
+       UCHAR   MpduDensity:1;
+       UCHAR   TxStream:2;
+       UCHAR   TxRxNotEqual:1;
+       UCHAR   TxMCSSetDefined:1;
+#else
+       UCHAR   TxMCSSetDefined:1;
+       UCHAR   TxRxNotEqual:1;
+       UCHAR   TxStream:2;
+       UCHAR   MpduDensity:1;
+       UCHAR   rsv:3;
+#endif // RT_BIG_ENDIAN //
+       UCHAR   rsv3[3];
+} HT_MCS_SET, *PHT_MCS_SET;
+
+//  HT Capability INFO field in HT Cap IE .
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+       USHORT  rsv2:4;
+       USHORT  RDGSupport:1;   //reverse Direction Grant  support
+       USHORT  PlusHTC:1;      //+HTC control field support
+       USHORT  MCSFeedback:2;  //0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback,  1:rsv.
+       USHORT  rsv:5;//momi power safe
+       USHORT  TranTime:2;
+       USHORT  Pco:1;
+#else
+       USHORT  Pco:1;
+       USHORT  TranTime:2;
+       USHORT  rsv:5;//momi power safe
+       USHORT  MCSFeedback:2;  //0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback,  1:rsv.
+       USHORT  PlusHTC:1;      //+HTC control field support
+       USHORT  RDGSupport:1;   //reverse Direction Grant  support
+       USHORT  rsv2:4;
+#endif /* RT_BIG_ENDIAN */
+} EXT_HT_CAP_INFO, *PEXT_HT_CAP_INFO;
+
+//  HT Beamforming field in HT Cap IE .
+typedef struct PACKED _HT_BF_CAP{
+#ifdef RT_BIG_ENDIAN
+       ULONG   rsv:3;
+       ULONG   ChanEstimation:2;
+       ULONG   CSIRowBFSup:2;
+       ULONG   ComSteerBFAntSup:2;
+       ULONG   NoComSteerBFAntSup:2;
+       ULONG   CSIBFAntSup:2;
+       ULONG   MinGrouping:2;
+       ULONG   ExpComBF:2;
+       ULONG   ExpNoComBF:2;
+       ULONG   ExpCSIFbk:2;
+       ULONG   ExpComSteerCapable:1;
+       ULONG   ExpNoComSteerCapable:1;
+       ULONG   ExpCSICapable:1;
+       ULONG   Calibration:2;
+       ULONG   ImpTxBFCapable:1;
+       ULONG   TxNDPCapable:1;
+       ULONG   RxNDPCapable:1;
+       ULONG   TxSoundCapable:1;
+       ULONG   RxSoundCapable:1;
+       ULONG   TxBFRecCapable:1;
+#else
+       ULONG   TxBFRecCapable:1;
+       ULONG   RxSoundCapable:1;
+       ULONG   TxSoundCapable:1;
+       ULONG   RxNDPCapable:1;
+       ULONG   TxNDPCapable:1;
+       ULONG   ImpTxBFCapable:1;
+       ULONG   Calibration:2;
+       ULONG   ExpCSICapable:1;
+       ULONG   ExpNoComSteerCapable:1;
+       ULONG   ExpComSteerCapable:1;
+       ULONG   ExpCSIFbk:2;
+       ULONG   ExpNoComBF:2;
+       ULONG   ExpComBF:2;
+       ULONG   MinGrouping:2;
+       ULONG   CSIBFAntSup:2;
+       ULONG   NoComSteerBFAntSup:2;
+       ULONG   ComSteerBFAntSup:2;
+       ULONG   CSIRowBFSup:2;
+       ULONG   ChanEstimation:2;
+       ULONG   rsv:3;
+#endif // RT_BIG_ENDIAN //
+} HT_BF_CAP, *PHT_BF_CAP;
+
+//  HT antenna selection field in HT Cap IE .
+typedef struct PACKED _HT_AS_CAP{
+#ifdef RT_BIG_ENDIAN
+       UCHAR   rsv:1;
+       UCHAR   TxSoundPPDU:1;
+       UCHAR   RxASel:1;
+       UCHAR   AntIndFbk:1;
+       UCHAR   ExpCSIFbk:1;
+       UCHAR   AntIndFbkTxASEL:1;
+       UCHAR   ExpCSIFbkTxASEL:1;
+       UCHAR   AntSelect:1;
+#else
+       UCHAR   AntSelect:1;
+       UCHAR   ExpCSIFbkTxASEL:1;
+       UCHAR   AntIndFbkTxASEL:1;
+       UCHAR   ExpCSIFbk:1;
+       UCHAR   AntIndFbk:1;
+       UCHAR   RxASel:1;
+       UCHAR   TxSoundPPDU:1;
+       UCHAR   rsv:1;
+#endif // RT_BIG_ENDIAN //
+} HT_AS_CAP, *PHT_AS_CAP;
+
+// Draft 1.0 set IE length 26, but is extensible..
+#define SIZE_HT_CAP_IE         26
+// The structure for HT Capability IE.
+typedef struct PACKED _HT_CAPABILITY_IE{
+       HT_CAP_INFO             HtCapInfo;
+       HT_CAP_PARM             HtCapParm;
+//     HT_MCS_SET              HtMCSSet;
+       UCHAR                   MCSSet[16];
+       EXT_HT_CAP_INFO ExtHtCapInfo;
+       HT_BF_CAP               TxBFCap;        // beamforming cap. rt2860c not support beamforming.
+       HT_AS_CAP               ASCap;  //antenna selection.
+} HT_CAPABILITY_IE, *PHT_CAPABILITY_IE;
+
+
+// 802.11n draft3 related structure definitions.
+// 7.3.2.60
+#define dot11OBSSScanPassiveDwell                                                      20      // in TU. min amount of time that the STA continously scans each channel when performing an active OBSS scan.
+#define dot11OBSSScanActiveDwell                                                       10      // in TU.min amount of time that the STA continously scans each channel when performing an passive OBSS scan.
+#define dot11BSSWidthTriggerScanInterval                                       300  // in sec. max interval between scan operations to be performed to detect BSS channel width trigger events.
+#define dot11OBSSScanPassiveTotalPerChannel                                    200     // in TU. min total amount of time that the STA scans each channel when performing a passive OBSS scan.
+#define dot11OBSSScanActiveTotalPerChannel                                     20      //in TU. min total amount of time that the STA scans each channel when performing a active OBSS scan
+#define dot11BSSWidthChannelTransactionDelayFactor                     5       // min ratio between the delay time in performing a switch from 20MHz BSS to 20/40 BSS operation and the maxima
+                                                                                                                               //      interval between overlapping BSS scan operations.
+#define dot11BSSScanActivityThreshold                                          25      // in %%, max total time that a STA may be active on the medium during a period of
+                                                                                                                               //      (dot11BSSWidthChannelTransactionDelayFactor * dot11BSSWidthTriggerScanInterval) seconds without
+                                                                                                                               //      being obligated to perform OBSS Scan operations. default is 25(== 0.25%)
+
+typedef struct PACKED _OVERLAP_BSS_SCAN_IE{
+       USHORT          ScanPassiveDwell;
+       USHORT          ScanActiveDwell;
+       USHORT          TriggerScanInt;                         // Trigger scan interval
+       USHORT          PassiveTalPerChannel;           // passive total per channel
+       USHORT          ActiveTalPerChannel;            // active total per channel
+       USHORT          DelayFactor;                            // BSS width channel transition delay factor
+       USHORT          ScanActThre;                            // Scan Activity threshold
+}OVERLAP_BSS_SCAN_IE, *POVERLAP_BSS_SCAN_IE;
+
+
+//  7.3.2.56. 20/40 Coexistence element used in  Element ID = 72 = IE_2040_BSS_COEXIST
+typedef union PACKED _BSS_2040_COEXIST_IE{
+ struct PACKED {
+ #ifdef RT_BIG_ENDIAN
+       UCHAR   rsv:5;
+       UCHAR   BSS20WidthReq:1;
+       UCHAR   Intolerant40:1;
+       UCHAR   InfoReq:1;
+ #else
+       UCHAR   InfoReq:1;
+       UCHAR   Intolerant40:1;                 // Inter-BSS. set 1 when prohibits a receiving BSS from operating as a 20/40 Mhz BSS.
+       UCHAR   BSS20WidthReq:1;                // Intra-BSS set 1 when prohibits a receiving AP from operating its BSS as a 20/40MHz BSS.
+       UCHAR   rsv:5;
+#endif // RT_BIG_ENDIAN //
+    } field;
+ UCHAR   word;
+} BSS_2040_COEXIST_IE, *PBSS_2040_COEXIST_IE;
+
+
+typedef struct  _TRIGGER_EVENTA{
+       BOOLEAN                 bValid;
+       UCHAR   BSSID[6];
+       UCHAR   RegClass;       // Regulatory Class
+       USHORT  Channel;
+       ULONG   CDCounter;   // Maintain a seperate count down counter for each Event A.
+} TRIGGER_EVENTA, *PTRIGGER_EVENTA;
+
+// 20/40 trigger event table
+// If one Event A delete or created, or if Event B is detected or not detected, STA should send 2040BSSCoexistence to AP.
+#define MAX_TRIGGER_EVENT              64
+typedef struct  _TRIGGER_EVENT_TAB{
+       UCHAR   EventANo;
+       TRIGGER_EVENTA  EventA[MAX_TRIGGER_EVENT];
+       ULONG                   EventBCountDown;        // Count down counter for Event B.
+} TRIGGER_EVENT_TAB, *PTRIGGER_EVENT_TAB;
+
+// 7.3.27 20/40 Bss Coexistence Mgmt capability used in extended capabilities information IE( ID = 127 = IE_EXT_CAPABILITY).
+//     This is the first octet and was defined in 802.11n D3.03 and 802.11yD9.0
+typedef struct PACKED _EXT_CAP_INFO_ELEMENT{
+#ifdef RT_BIG_ENDIAN
+       UCHAR   rsv2:5;
+       UCHAR   ExtendChannelSwitch:1;
+       UCHAR   rsv:1;
+       UCHAR   BssCoexistMgmtSupport:1;
+#else
+       UCHAR   BssCoexistMgmtSupport:1;
+       UCHAR   rsv:1;
+       UCHAR   ExtendChannelSwitch:1;
+       UCHAR   rsv2:5;
+#endif // RT_BIG_ENDIAN //
+}EXT_CAP_INFO_ELEMENT, *PEXT_CAP_INFO_ELEMENT;
+
+
+// 802.11n 7.3.2.61
+typedef struct PACKED _BSS_2040_COEXIST_ELEMENT{
+       UCHAR                                   ElementID;              // ID = IE_2040_BSS_COEXIST = 72
+       UCHAR                                   Len;
+       BSS_2040_COEXIST_IE             BssCoexistIe;
+}BSS_2040_COEXIST_ELEMENT, *PBSS_2040_COEXIST_ELEMENT;
+
+
+//802.11n 7.3.2.59
+typedef struct PACKED _BSS_2040_INTOLERANT_CH_REPORT{
+       UCHAR                           ElementID;              // ID = IE_2040_BSS_INTOLERANT_REPORT = 73
+       UCHAR                           Len;
+       UCHAR                           RegulatoryClass;
+       UCHAR                           ChList[0];
+}BSS_2040_INTOLERANT_CH_REPORT, *PBSS_2040_INTOLERANT_CH_REPORT;
+
+
+// The structure for channel switch annoucement IE. This is in 802.11n D3.03
+typedef struct PACKED _CHA_SWITCH_ANNOUNCE_IE{
+       UCHAR                   SwitchMode;     //channel switch mode
+       UCHAR                   NewChannel;     //
+       UCHAR                   SwitchCount;    //
+} CHA_SWITCH_ANNOUNCE_IE, *PCHA_SWITCH_ANNOUNCE_IE;
+
+
+// The structure for channel switch annoucement IE. This is in 802.11n D3.03
+typedef struct PACKED _SEC_CHA_OFFSET_IE{
+       UCHAR                   SecondaryChannelOffset;  // 1: Secondary above, 3: Secondary below, 0: no Secondary
+} SEC_CHA_OFFSET_IE, *PSEC_CHA_OFFSET_IE;
+
+
+// This structure is extracted from struct RT_HT_CAPABILITY
+typedef struct {
+       BOOLEAN                 bHtEnable;       // If we should use ht rate.
+       BOOLEAN                 bPreNHt;         // If we should use ht rate.
+       //Substract from HT Capability IE
+       UCHAR                   MCSSet[16];     //only supoort MCS=0-15,32 ,
+} RT_HT_PHY_INFO, *PRT_HT_PHY_INFO;
+
+//This structure substracts ralink supports from all 802.11n-related features.
+//Features not listed here but contained in 802.11n spec are not supported in rt2860.
+typedef struct {
+#if 0  // move to
+       BOOLEAN                 bHtEnable;       // If we should use ht rate.
+       BOOLEAN                 bPreNHt;         // If we should use ht rate.
+       //Substract from HT Capability IE
+       UCHAR                   MCSSet[16];     //only supoort MCS=0-15,32 ,
+#endif
+#ifdef RT_BIG_ENDIAN
+       USHORT  rsv:5;
+       USHORT  AmsduSize:1;    // Max receiving A-MSDU size
+       USHORT  AmsduEnable:1;  // Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n
+       USHORT  RxSTBC:2;       // 2 bits
+       USHORT  TxSTBC:1;
+       USHORT  ShortGIfor40:1; //for40MHz
+       USHORT  ShortGIfor20:1;
+       USHORT  GF:1;   //green field
+       USHORT  MimoPs:2;//mimo power safe MMPS_
+       USHORT  ChannelWidth:1;
+#else
+       USHORT  ChannelWidth:1;
+       USHORT  MimoPs:2;//mimo power safe MMPS_
+       USHORT  GF:1;   //green field
+       USHORT  ShortGIfor20:1;
+       USHORT  ShortGIfor40:1; //for40MHz
+       USHORT  TxSTBC:1;
+       USHORT  RxSTBC:2;       // 2 bits
+       USHORT  AmsduEnable:1;  // Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n
+       USHORT  AmsduSize:1;    // Max receiving A-MSDU size
+       USHORT  rsv:5;
+#endif
+
+       //Substract from Addiont HT INFO IE
+#ifdef RT_BIG_ENDIAN
+       UCHAR   RecomWidth:1;
+       UCHAR   ExtChanOffset:2;        // Please not the difference with following     UCHAR   NewExtChannelOffset; from 802.11n
+       UCHAR   MpduDensity:3;
+       UCHAR   MaxRAmpduFactor:2;
+#else
+       UCHAR   MaxRAmpduFactor:2;
+       UCHAR   MpduDensity:3;
+       UCHAR   ExtChanOffset:2;        // Please not the difference with following     UCHAR   NewExtChannelOffset; from 802.11n
+       UCHAR   RecomWidth:1;
+#endif
+
+#ifdef RT_BIG_ENDIAN
+       USHORT  rsv2:11;
+       USHORT  OBSS_NonHTExist:1;
+       USHORT  rsv3:1;
+       USHORT  NonGfPresent:1;
+       USHORT  OperaionMode:2;
+#else
+       USHORT  OperaionMode:2;
+       USHORT  NonGfPresent:1;
+       USHORT  rsv3:1;
+       USHORT  OBSS_NonHTExist:1;
+       USHORT  rsv2:11;
+#endif
+
+       // New Extension Channel Offset IE
+       UCHAR   NewExtChannelOffset;
+       // Extension Capability IE = 127
+       UCHAR   BSSCoexist2040;
+} RT_HT_CAPABILITY, *PRT_HT_CAPABILITY;
+
+//   field in Addtional HT Information IE .
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+       UCHAR   SerInterGranu:3;
+       UCHAR   S_PSMPSup:1;
+       UCHAR   RifsMode:1;
+       UCHAR   RecomWidth:1;
+       UCHAR   ExtChanOffset:2;
+#else
+       UCHAR   ExtChanOffset:2;
+       UCHAR   RecomWidth:1;
+       UCHAR   RifsMode:1;
+       UCHAR   S_PSMPSup:1;     //Indicate support for scheduled PSMP
+       UCHAR   SerInterGranu:3;         //service interval granularity
+#endif
+} ADD_HTINFO, *PADD_HTINFO;
+
+typedef struct PACKED{
+#ifdef RT_BIG_ENDIAN
+       USHORT  rsv2:11;
+       USHORT  OBSS_NonHTExist:1;
+       USHORT  rsv:1;
+       USHORT  NonGfPresent:1;
+       USHORT  OperaionMode:2;
+#else
+       USHORT  OperaionMode:2;
+       USHORT  NonGfPresent:1;
+       USHORT  rsv:1;
+       USHORT  OBSS_NonHTExist:1;
+       USHORT  rsv2:11;
+#endif
+} ADD_HTINFO2, *PADD_HTINFO2;
+
+
+// TODO: Need sync with spec about the definition of StbcMcs. In Draft 3.03, it's reserved.
+typedef struct PACKED{
+#ifdef RT_BIG_ENDIAN
+       USHORT  rsv:4;
+       USHORT  PcoPhase:1;
+       USHORT  PcoActive:1;
+       USHORT  LsigTxopProt:1;
+       USHORT  STBCBeacon:1;
+       USHORT  DualCTSProtect:1;
+       USHORT  DualBeacon:1;
+       USHORT  StbcMcs:6;
+#else
+       USHORT  StbcMcs:6;
+       USHORT  DualBeacon:1;
+       USHORT  DualCTSProtect:1;
+       USHORT  STBCBeacon:1;
+       USHORT  LsigTxopProt:1; // L-SIG TXOP protection full support
+       USHORT  PcoActive:1;
+       USHORT  PcoPhase:1;
+       USHORT  rsv:4;
+#endif // RT_BIG_ENDIAN //
+} ADD_HTINFO3, *PADD_HTINFO3;
+
+#define SIZE_ADD_HT_INFO_IE            22
+typedef struct  PACKED{
+       UCHAR                           ControlChan;
+       ADD_HTINFO                      AddHtInfo;
+       ADD_HTINFO2                     AddHtInfo2;
+       ADD_HTINFO3                     AddHtInfo3;
+       UCHAR                           MCSSet[16];             // Basic MCS set
+} ADD_HT_INFO_IE, *PADD_HT_INFO_IE;
+
+typedef struct  PACKED{
+       UCHAR                           NewExtChanOffset;
+} NEW_EXT_CHAN_IE, *PNEW_EXT_CHAN_IE;
+
+
+// 4-byte HTC field.  maybe included in any frame except non-QOS data frame.  The Order bit must set 1.
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+    UINT32             RDG:1;  //RDG / More PPDU
+    UINT32             ACConstraint:1; //feedback request
+    UINT32             rsv:5;  //calibration sequence
+    UINT32             ZLFAnnouce:1;   // ZLF announcement
+    UINT32             CSISTEERING:2;  //CSI/ STEERING
+    UINT32             FBKReq:2;       //feedback request
+    UINT32             CalSeq:2;  //calibration sequence
+    UINT32             CalPos:2;       // calibration position
+    UINT32             MFBorASC:7;     //Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available
+    UINT32             MFS:3;  //SET to the received value of MRS. 0x111 for unsolicited MFB.
+    UINT32             MRSorASI:3;     // MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110.
+    UINT32             MRQ:1;  //MCS feedback. Request for a MCS feedback
+    UINT32             TRQ:1;  //sounding request
+    UINT32             MA:1;   //management action payload exist in (QoS Null+HTC)
+#else
+    UINT32             MA:1;   //management action payload exist in (QoS Null+HTC)
+    UINT32             TRQ:1;  //sounding request
+    UINT32             MRQ:1;  //MCS feedback. Request for a MCS feedback
+    UINT32             MRSorASI:3;     // MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110.
+    UINT32             MFS:3;  //SET to the received value of MRS. 0x111 for unsolicited MFB.
+    UINT32             MFBorASC:7;     //Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available
+    UINT32             CalPos:2;       // calibration position
+    UINT32             CalSeq:2;  //calibration sequence
+    UINT32             FBKReq:2;       //feedback request
+    UINT32             CSISTEERING:2;  //CSI/ STEERING
+    UINT32             ZLFAnnouce:1;   // ZLF announcement
+    UINT32             rsv:5;  //calibration sequence
+    UINT32             ACConstraint:1; //feedback request
+    UINT32             RDG:1;  //RDG / More PPDU
+#endif /* !RT_BIG_ENDIAN */
+} HT_CONTROL, *PHT_CONTROL;
+
+// 2-byte QOS CONTROL field
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+    USHORT      Txop_QueueSize:8;
+    USHORT      AMsduPresent:1;
+    USHORT      AckPolicy:2;  //0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP  3: BA
+    USHORT      EOSP:1;
+    USHORT      TID:4;
+#else
+    USHORT      TID:4;
+    USHORT      EOSP:1;
+    USHORT      AckPolicy:2;  //0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP  3: BA
+    USHORT      AMsduPresent:1;
+    USHORT      Txop_QueueSize:8;
+#endif /* !RT_BIG_ENDIAN */
+} QOS_CONTROL, *PQOS_CONTROL;
+
+// 2-byte Frame control field
+typedef        struct  PACKED {
+#ifdef RT_BIG_ENDIAN
+       USHORT          Order:1;                        // Strict order expected
+       USHORT          Wep:1;                          // Wep data
+       USHORT          MoreData:1;                     // More data bit
+       USHORT          PwrMgmt:1;                      // Power management bit
+       USHORT          Retry:1;                        // Retry status bit
+       USHORT          MoreFrag:1;                     // More fragment bit
+       USHORT          FrDs:1;                         // From DS indication
+       USHORT          ToDs:1;                         // To DS indication
+       USHORT          SubType:4;                      // MSDU subtype
+       USHORT          Type:2;                         // MSDU type
+       USHORT          Ver:2;                          // Protocol version
+#else
+       USHORT          Ver:2;                          // Protocol version
+       USHORT          Type:2;                         // MSDU type
+       USHORT          SubType:4;                      // MSDU subtype
+       USHORT          ToDs:1;                         // To DS indication
+       USHORT          FrDs:1;                         // From DS indication
+       USHORT          MoreFrag:1;                     // More fragment bit
+       USHORT          Retry:1;                        // Retry status bit
+       USHORT          PwrMgmt:1;                      // Power management bit
+       USHORT          MoreData:1;                     // More data bit
+       USHORT          Wep:1;                          // Wep data
+       USHORT          Order:1;                        // Strict order expected
+#endif /* !RT_BIG_ENDIAN */
+} FRAME_CONTROL, *PFRAME_CONTROL;
+
+typedef        struct  PACKED _HEADER_802_11   {
+    FRAME_CONTROL   FC;
+    USHORT          Duration;
+    UCHAR           Addr1[MAC_ADDR_LEN];
+    UCHAR           Addr2[MAC_ADDR_LEN];
+       UCHAR                   Addr3[MAC_ADDR_LEN];
+#ifdef RT_BIG_ENDIAN
+       USHORT                  Sequence:12;
+       USHORT                  Frag:4;
+#else
+       USHORT                  Frag:4;
+       USHORT                  Sequence:12;
+#endif /* !RT_BIG_ENDIAN */
+       UCHAR                   Octet[0];
+}      HEADER_802_11, *PHEADER_802_11;
+
+typedef struct PACKED _FRAME_802_11 {
+    HEADER_802_11   Hdr;
+    UCHAR            Octet[1];
+}   FRAME_802_11, *PFRAME_802_11;
+
+// QoSNull embedding of management action. When HT Control MA field set to 1.
+typedef struct PACKED _MA_BODY {
+    UCHAR            Category;
+    UCHAR            Action;
+    UCHAR            Octet[1];
+}   MA_BODY, *PMA_BODY;
+
+typedef        struct  PACKED _HEADER_802_3    {
+    UCHAR           DAAddr1[MAC_ADDR_LEN];
+    UCHAR           SAAddr2[MAC_ADDR_LEN];
+    UCHAR           Octet[2];
+}      HEADER_802_3, *PHEADER_802_3;
+////Block ACK related format
+// 2-byte BA Parameter  field  in      DELBA frames to terminate an already set up bA
+typedef struct PACKED{
+#ifdef RT_BIG_ENDIAN
+    USHORT      TID:4; // value of TC os TS
+    USHORT      Initiator:1;   // 1: originator    0:recipient
+    USHORT      Rsv:11;        // always set to 0
+#else
+    USHORT      Rsv:11;        // always set to 0
+    USHORT      Initiator:1;   // 1: originator    0:recipient
+    USHORT      TID:4; // value of TC os TS
+#endif /* !RT_BIG_ENDIAN */
+} DELBA_PARM, *PDELBA_PARM;
+
+// 2-byte BA Parameter Set field  in ADDBA frames to signal parm for setting up a BA
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+    USHORT      BufSize:10;    // number of buffe of size 2304 octetsr
+    USHORT      TID:4; // value of TC os TS
+    USHORT      BAPolicy:1;    // 1: immediately BA    0:delayed BA
+    USHORT      AMSDUSupported:1;      // 0: not permitted             1: permitted
+#else
+    USHORT      AMSDUSupported:1;      // 0: not permitted             1: permitted
+    USHORT      BAPolicy:1;    // 1: immediately BA    0:delayed BA
+    USHORT      TID:4; // value of TC os TS
+    USHORT      BufSize:10;    // number of buffe of size 2304 octetsr
+#endif /* !RT_BIG_ENDIAN */
+} BA_PARM, *PBA_PARM;
+
+// 2-byte BA Starting Seq CONTROL field
+typedef union PACKED {
+    struct PACKED {
+#ifdef RT_BIG_ENDIAN
+    USHORT      StartSeq:12;   // sequence number of the 1st MSDU for which this BAR is sent
+       USHORT      FragNum:4;  // always set to 0
+#else
+    USHORT      FragNum:4;     // always set to 0
+       USHORT      StartSeq:12;   // sequence number of the 1st MSDU for which this BAR is sent
+#endif /* RT_BIG_ENDIAN */
+    }   field;
+    USHORT           word;
+} BASEQ_CONTROL, *PBASEQ_CONTROL;
+
+//BAControl and BARControl are the same
+// 2-byte BA CONTROL field in BA frame
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+    USHORT      TID:4;
+    USHORT      Rsv:9;
+    USHORT      Compressed:1;
+    USHORT      MTID:1;                //EWC V1.24
+    USHORT      ACKPolicy:1; // only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK  1:No ACK
+#else
+    USHORT      ACKPolicy:1; // only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK  1:No ACK
+    USHORT      MTID:1;                //EWC V1.24
+    USHORT      Compressed:1;
+    USHORT      Rsv:9;
+    USHORT      TID:4;
+#endif /* !RT_BIG_ENDIAN */
+} BA_CONTROL, *PBA_CONTROL;
+
+// 2-byte BAR CONTROL field in BAR frame
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+    USHORT      TID:4;
+    USHORT      Rsv1:9;
+    USHORT      Compressed:1;
+    USHORT      MTID:1;                //if this bit1, use  FRAME_MTBA_REQ,  if 0, use FRAME_BA_REQ
+    USHORT      ACKPolicy:1;
+#else
+    USHORT      ACKPolicy:1; // 0:normal ack,  1:no ack.
+    USHORT      MTID:1;                //if this bit1, use  FRAME_MTBA_REQ,  if 0, use FRAME_BA_REQ
+    USHORT      Compressed:1;
+    USHORT      Rsv1:9;
+    USHORT      TID:4;
+#endif /* !RT_BIG_ENDIAN */
+} BAR_CONTROL, *PBAR_CONTROL;
+
+// BARControl in MTBAR frame
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+    USHORT      NumTID:4;
+    USHORT      Rsv1:9;
+    USHORT      Compressed:1;
+    USHORT      MTID:1;
+    USHORT      ACKPolicy:1;
+#else
+    USHORT      ACKPolicy:1;
+    USHORT      MTID:1;
+    USHORT      Compressed:1;
+    USHORT      Rsv1:9;
+    USHORT      NumTID:4;
+#endif /* !RT_BIG_ENDIAN */
+} MTBAR_CONTROL, *PMTBAR_CONTROL;
+
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+    USHORT      TID:4;
+    USHORT      Rsv1:12;
+#else
+    USHORT      Rsv1:12;
+    USHORT      TID:4;
+#endif /* !RT_BIG_ENDIAN */
+} PER_TID_INFO, *PPER_TID_INFO;
+
+typedef struct {
+       PER_TID_INFO      PerTID;
+       BASEQ_CONTROL    BAStartingSeq;
+} EACH_TID, *PEACH_TID;
+
+
+typedef struct PACKED _PSPOLL_FRAME {
+    FRAME_CONTROL   FC;
+    USHORT          Aid;
+    UCHAR           Bssid[MAC_ADDR_LEN];
+    UCHAR           Ta[MAC_ADDR_LEN];
+}   PSPOLL_FRAME, *PPSPOLL_FRAME;
+
+typedef        struct  PACKED _RTS_FRAME       {
+    FRAME_CONTROL   FC;
+    USHORT          Duration;
+    UCHAR           Addr1[MAC_ADDR_LEN];
+    UCHAR           Addr2[MAC_ADDR_LEN];
+}RTS_FRAME, *PRTS_FRAME;
+
+// BAREQ AND MTBAREQ have the same subtype BAR, 802.11n BAR use compressed bitmap.
+typedef struct PACKED _FRAME_BA_REQ {
+       FRAME_CONTROL   FC;
+       USHORT          Duration;
+       UCHAR           Addr1[MAC_ADDR_LEN];
+       UCHAR           Addr2[MAC_ADDR_LEN];
+       BAR_CONTROL  BARControl;
+       BASEQ_CONTROL    BAStartingSeq;
+}   FRAME_BA_REQ, *PFRAME_BA_REQ;
+
+typedef struct PACKED _FRAME_MTBA_REQ {
+       FRAME_CONTROL   FC;
+       USHORT          Duration;
+       UCHAR           Addr1[MAC_ADDR_LEN];
+       UCHAR           Addr2[MAC_ADDR_LEN];
+       MTBAR_CONTROL  MTBARControl;
+       PER_TID_INFO    PerTIDInfo;
+       BASEQ_CONTROL    BAStartingSeq;
+}   FRAME_MTBA_REQ, *PFRAME_MTBA_REQ;
+
+// Compressed format is mandantory in HT STA
+typedef struct PACKED _FRAME_MTBA {
+       FRAME_CONTROL   FC;
+       USHORT          Duration;
+       UCHAR           Addr1[MAC_ADDR_LEN];
+       UCHAR           Addr2[MAC_ADDR_LEN];
+       BA_CONTROL  BAControl;
+       BASEQ_CONTROL    BAStartingSeq;
+       UCHAR           BitMap[8];
+}   FRAME_MTBA, *PFRAME_MTBA;
+
+typedef struct PACKED _FRAME_PSMP_ACTION {
+       HEADER_802_11   Hdr;
+       UCHAR   Category;
+       UCHAR   Action;
+       UCHAR   Psmp;   // 7.3.1.25
+}   FRAME_PSMP_ACTION, *PFRAME_PSMP_ACTION;
+
+typedef struct PACKED _FRAME_ACTION_HDR {
+       HEADER_802_11   Hdr;
+       UCHAR   Category;
+       UCHAR   Action;
+}   FRAME_ACTION_HDR, *PFRAME_ACTION_HDR;
+
+//Action Frame
+//Action Frame  Category:Spectrum,  Action:Channel Switch. 7.3.2.20
+typedef struct PACKED _CHAN_SWITCH_ANNOUNCE {
+       UCHAR                                   ElementID;      // ID = IE_CHANNEL_SWITCH_ANNOUNCEMENT = 37
+       UCHAR                                   Len;
+       CHA_SWITCH_ANNOUNCE_IE  CSAnnounceIe;
+}   CHAN_SWITCH_ANNOUNCE, *PCHAN_SWITCH_ANNOUNCE;
+
+
+//802.11n : 7.3.2.20a
+typedef struct PACKED _SECOND_CHAN_OFFSET {
+       UCHAR                           ElementID;              // ID = IE_SECONDARY_CH_OFFSET = 62
+       UCHAR                           Len;
+       SEC_CHA_OFFSET_IE       SecChOffsetIe;
+}   SECOND_CHAN_OFFSET, *PSECOND_CHAN_OFFSET;
+
+
+typedef struct PACKED _FRAME_SPETRUM_CS {
+       HEADER_802_11   Hdr;
+       UCHAR   Category;
+       UCHAR   Action;
+       CHAN_SWITCH_ANNOUNCE    CSAnnounce;
+       SECOND_CHAN_OFFSET              SecondChannel;
+}   FRAME_SPETRUM_CS, *PFRAME_SPETRUM_CS;
+
+
+typedef struct PACKED _FRAME_ADDBA_REQ {
+       HEADER_802_11   Hdr;
+       UCHAR   Category;
+       UCHAR   Action;
+       UCHAR   Token;  // 1
+       BA_PARM         BaParm;       //  2 - 10
+       USHORT          TimeOutValue;   // 0 - 0
+       BASEQ_CONTROL   BaStartSeq; // 0-0
+}   FRAME_ADDBA_REQ, *PFRAME_ADDBA_REQ;
+
+typedef struct PACKED _FRAME_ADDBA_RSP {
+       HEADER_802_11   Hdr;
+       UCHAR   Category;
+       UCHAR   Action;
+       UCHAR   Token;
+       USHORT  StatusCode;
+       BA_PARM         BaParm; //0 - 2
+       USHORT          TimeOutValue;
+}   FRAME_ADDBA_RSP, *PFRAME_ADDBA_RSP;
+
+typedef struct PACKED _FRAME_DELBA_REQ {
+       HEADER_802_11   Hdr;
+       UCHAR   Category;
+       UCHAR   Action;
+       DELBA_PARM              DelbaParm;
+       USHORT  ReasonCode;
+}   FRAME_DELBA_REQ, *PFRAME_DELBA_REQ;
+
+
+//7.2.1.7
+typedef struct PACKED _FRAME_BAR {
+       FRAME_CONTROL   FC;
+       USHORT          Duration;
+       UCHAR           Addr1[MAC_ADDR_LEN];
+       UCHAR           Addr2[MAC_ADDR_LEN];
+       BAR_CONTROL             BarControl;
+       BASEQ_CONTROL   StartingSeq;
+}   FRAME_BAR, *PFRAME_BAR;
+
+//7.2.1.7
+typedef struct PACKED _FRAME_BA {
+       FRAME_CONTROL   FC;
+       USHORT          Duration;
+       UCHAR           Addr1[MAC_ADDR_LEN];
+       UCHAR           Addr2[MAC_ADDR_LEN];
+       BAR_CONTROL             BarControl;
+       BASEQ_CONTROL   StartingSeq;
+       UCHAR           bitmask[8];
+}   FRAME_BA, *PFRAME_BA;
+
+
+// Radio Measuement Request Frame Format
+typedef struct PACKED _FRAME_RM_REQ_ACTION {
+       HEADER_802_11   Hdr;
+       UCHAR   Category;
+       UCHAR   Action;
+       UCHAR   Token;
+       USHORT  Repetition;
+       UCHAR   data[0];
+}   FRAME_RM_REQ_ACTION, *PFRAME_RM_REQ_ACTION;
+
+typedef struct PACKED {
+       UCHAR           ID;
+       UCHAR           Length;
+       UCHAR           ChannelSwitchMode;
+       UCHAR           NewRegClass;
+       UCHAR           NewChannelNum;
+       UCHAR           ChannelSwitchCount;
+} HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE, *PHT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE;
+
+
+//
+// _Limit must be the 2**n - 1
+// _SEQ1 , _SEQ2 must be within 0 ~ _Limit
+//
+#define SEQ_STEPONE(_SEQ1, _SEQ2, _Limit)      ((_SEQ1 == ((_SEQ2+1) & _Limit)))
+#define SEQ_SMALLER(_SEQ1, _SEQ2, _Limit)      (((_SEQ1-_SEQ2) & ((_Limit+1)>>1)))
+#define SEQ_LARGER(_SEQ1, _SEQ2, _Limit)       ((_SEQ1 != _SEQ2) && !(((_SEQ1-_SEQ2) & ((_Limit+1)>>1))))
+#define SEQ_WITHIN_WIN(_SEQ1, _SEQ2, _WIN, _Limit) (SEQ_LARGER(_SEQ1, _SEQ2, _Limit) &&  \
+                                                                                               SEQ_SMALLER(_SEQ1, ((_SEQ2+_WIN+1)&_Limit), _Limit))
+
+//
+// Contention-free parameter (without ID and Length)
+//
+typedef struct PACKED {
+    BOOLEAN     bValid;         // 1: variable contains valid value
+    UCHAR       CfpCount;
+    UCHAR       CfpPeriod;
+    USHORT      CfpMaxDuration;
+    USHORT      CfpDurRemaining;
+} CF_PARM, *PCF_PARM;
+
+typedef        struct  _CIPHER_SUITE   {
+       NDIS_802_11_ENCRYPTION_STATUS   PairCipher;             // Unicast cipher 1, this one has more secured cipher suite
+       NDIS_802_11_ENCRYPTION_STATUS   PairCipherAux;  // Unicast cipher 2 if AP announce two unicast cipher suite
+       NDIS_802_11_ENCRYPTION_STATUS   GroupCipher;    // Group cipher
+       USHORT                                                  RsnCapability;  // RSN capability from beacon
+       BOOLEAN                                                 bMixMode;               // Indicate Pair & Group cipher might be different
+}      CIPHER_SUITE, *PCIPHER_SUITE;
+
+// EDCA configuration from AP's BEACON/ProbeRsp
+typedef struct {
+    BOOLEAN     bValid;         // 1: variable contains valid value
+    BOOLEAN     bAdd;         // 1: variable contains valid value
+    BOOLEAN     bQAck;
+    BOOLEAN     bQueueRequest;
+    BOOLEAN     bTxopRequest;
+    BOOLEAN     bAPSDCapable;
+//  BOOLEAN     bMoreDataAck;
+    UCHAR       EdcaUpdateCount;
+    UCHAR       Aifsn[4];       // 0:AC_BK, 1:AC_BE, 2:AC_VI, 3:AC_VO
+    UCHAR       Cwmin[4];
+    UCHAR       Cwmax[4];
+    USHORT      Txop[4];      // in unit of 32-us
+    BOOLEAN     bACM[4];      // 1: Admission Control of AC_BK is mandattory
+} EDCA_PARM, *PEDCA_PARM;
+
+// QBSS LOAD information from QAP's BEACON/ProbeRsp
+typedef struct {
+    BOOLEAN     bValid;                     // 1: variable contains valid value
+    USHORT      StaNum;
+    UCHAR       ChannelUtilization;
+    USHORT      RemainingAdmissionControl;  // in unit of 32-us
+} QBSS_LOAD_PARM, *PQBSS_LOAD_PARM;
+
+// QBSS Info field in QSTA's assoc req
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+       UCHAR           Rsv2:1;
+       UCHAR           MaxSPLength:2;
+       UCHAR           Rsv1:1;
+       UCHAR           UAPSD_AC_BE:1;
+       UCHAR           UAPSD_AC_BK:1;
+       UCHAR           UAPSD_AC_VI:1;
+       UCHAR           UAPSD_AC_VO:1;
+#else
+    UCHAR              UAPSD_AC_VO:1;
+       UCHAR           UAPSD_AC_VI:1;
+       UCHAR           UAPSD_AC_BK:1;
+       UCHAR           UAPSD_AC_BE:1;
+       UCHAR           Rsv1:1;
+       UCHAR           MaxSPLength:2;
+       UCHAR           Rsv2:1;
+#endif /* !RT_BIG_ENDIAN */
+} QBSS_STA_INFO_PARM, *PQBSS_STA_INFO_PARM;
+
+// QBSS Info field in QAP's Beacon/ProbeRsp
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+       UCHAR           UAPSD:1;
+       UCHAR           Rsv:3;
+    UCHAR              ParamSetCount:4;
+#else
+    UCHAR              ParamSetCount:4;
+       UCHAR           Rsv:3;
+       UCHAR           UAPSD:1;
+#endif /* !RT_BIG_ENDIAN */
+} QBSS_AP_INFO_PARM, *PQBSS_AP_INFO_PARM;
+
+// QOS Capability reported in QAP's BEACON/ProbeRsp
+// QOS Capability sent out in QSTA's AssociateReq/ReAssociateReq
+typedef struct {
+    BOOLEAN     bValid;                     // 1: variable contains valid value
+    BOOLEAN     bQAck;
+    BOOLEAN     bQueueRequest;
+    BOOLEAN     bTxopRequest;
+//  BOOLEAN     bMoreDataAck;
+    UCHAR       EdcaUpdateCount;
+} QOS_CAPABILITY_PARM, *PQOS_CAPABILITY_PARM;
+
+#ifdef CONFIG_STA_SUPPORT
+typedef struct {
+    UCHAR       IELen;
+    UCHAR       IE[MAX_CUSTOM_LEN];
+} WPA_IE_;
+#endif // CONFIG_STA_SUPPORT //
+
+
+typedef struct {
+    UCHAR   Bssid[MAC_ADDR_LEN];
+    UCHAR   Channel;
+       UCHAR   CentralChannel; //Store the wide-band central channel for 40MHz.  .used in 40MHz AP. Or this is the same as Channel.
+    UCHAR   BssType;
+    USHORT  AtimWin;
+    USHORT  BeaconPeriod;
+
+    UCHAR   SupRate[MAX_LEN_OF_SUPPORTED_RATES];
+    UCHAR   SupRateLen;
+    UCHAR   ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+    UCHAR   ExtRateLen;
+       HT_CAPABILITY_IE HtCapability;
+       UCHAR                   HtCapabilityLen;
+       ADD_HT_INFO_IE AddHtInfo;       // AP might use this additional ht info IE
+       UCHAR                   AddHtInfoLen;
+       UCHAR                   NewExtChanOffset;
+       CHAR    Rssi;
+    UCHAR   Privacy;                   // Indicate security function ON/OFF. Don't mess up with auth mode.
+       UCHAR   Hidden;
+
+    USHORT  DtimPeriod;
+    USHORT  CapabilityInfo;
+
+    USHORT  CfpCount;
+    USHORT  CfpPeriod;
+    USHORT  CfpMaxDuration;
+    USHORT  CfpDurRemaining;
+    UCHAR   SsidLen;
+    CHAR    Ssid[MAX_LEN_OF_SSID];
+
+    ULONG   LastBeaconRxTime; // OS's timestamp
+
+       BOOLEAN bSES;
+
+       // New for WPA2
+       CIPHER_SUITE                                    WPA;                    // AP announced WPA cipher suite
+       CIPHER_SUITE                                    WPA2;                   // AP announced WPA2 cipher suite
+
+       // New for microsoft WPA support
+       NDIS_802_11_FIXED_IEs   FixIEs;
+       NDIS_802_11_AUTHENTICATION_MODE AuthModeAux;    // Addition mode for WPA2 / WPA capable AP
+       NDIS_802_11_AUTHENTICATION_MODE AuthMode;
+       NDIS_802_11_WEP_STATUS  WepStatus;                              // Unicast Encryption Algorithm extract from VAR_IE
+       USHORT                                  VarIELen;                               // Length of next VIE include EID & Length
+       UCHAR                                   VarIEs[MAX_VIE_LEN];
+
+       // CCX Ckip information
+    UCHAR   CkipFlag;
+
+       // CCX 2 TSF
+       UCHAR   PTSF[4];                // Parent TSF
+       UCHAR   TTSF[8];                // Target TSF
+
+    // 802.11e d9, and WMM
+       EDCA_PARM           EdcaParm;
+       QOS_CAPABILITY_PARM QosCapability;
+       QBSS_LOAD_PARM      QbssLoad;
+#ifdef CONFIG_STA_SUPPORT
+    WPA_IE_     WpaIE;
+    WPA_IE_     RsnIE;
+#ifdef EXT_BUILD_CHANNEL_LIST
+       UCHAR           CountryString[3];
+       BOOLEAN         bHasCountryIE;
+#endif // EXT_BUILD_CHANNEL_LIST //
+#endif // CONFIG_STA_SUPPORT //
+} BSS_ENTRY, *PBSS_ENTRY;
+
+typedef struct {
+    UCHAR           BssNr;
+    UCHAR           BssOverlapNr;
+    BSS_ENTRY       BssEntry[MAX_LEN_OF_BSS_TABLE];
+} BSS_TABLE, *PBSS_TABLE;
+
+
+typedef struct _MLME_QUEUE_ELEM {
+    ULONG             Machine;
+    ULONG             MsgType;
+    ULONG             MsgLen;
+    UCHAR             Msg[MGMT_DMA_BUFFER_SIZE];
+    LARGE_INTEGER     TimeStamp;
+    UCHAR             Rssi0;
+    UCHAR             Rssi1;
+    UCHAR             Rssi2;
+    UCHAR             Signal;
+    UCHAR             Channel;
+    UCHAR             Wcid;
+    BOOLEAN           Occupied;
+} MLME_QUEUE_ELEM, *PMLME_QUEUE_ELEM;
+
+typedef struct _MLME_QUEUE {
+    ULONG             Num;
+    ULONG             Head;
+    ULONG             Tail;
+    NDIS_SPIN_LOCK   Lock;
+    MLME_QUEUE_ELEM  Entry[MAX_LEN_OF_MLME_QUEUE];
+} MLME_QUEUE, *PMLME_QUEUE;
+
+typedef VOID (*STATE_MACHINE_FUNC)(VOID *Adaptor, MLME_QUEUE_ELEM *Elem);
+
+typedef struct _STATE_MACHINE {
+    ULONG                           Base;
+    ULONG                           NrState;
+    ULONG                           NrMsg;
+    ULONG                           CurrState;
+    STATE_MACHINE_FUNC             *TransFunc;
+} STATE_MACHINE, *PSTATE_MACHINE;
+
+
+// MLME AUX data structure that hold temporarliy settings during a connection attempt.
+// Once this attemp succeeds, all settings will be copy to pAd->StaActive.
+// A connection attempt (user set OID, roaming, CCX fast roaming,..) consists of
+// several steps (JOIN, AUTH, ASSOC or REASSOC) and may fail at any step. We purposely
+// separate this under-trial settings away from pAd->StaActive so that once
+// this new attempt failed, driver can auto-recover back to the active settings.
+typedef struct _MLME_AUX {
+    UCHAR               BssType;
+    UCHAR               Ssid[MAX_LEN_OF_SSID];
+    UCHAR               SsidLen;
+    UCHAR               Bssid[MAC_ADDR_LEN];
+       UCHAR                           AutoReconnectSsid[MAX_LEN_OF_SSID];
+       UCHAR                           AutoReconnectSsidLen;
+    USHORT              Alg;
+    UCHAR               ScanType;
+    UCHAR               Channel;
+       UCHAR               CentralChannel;
+    USHORT              Aid;
+    USHORT              CapabilityInfo;
+    USHORT              BeaconPeriod;
+    USHORT              CfpMaxDuration;
+    USHORT              CfpPeriod;
+    USHORT              AtimWin;
+
+       // Copy supported rate from desired AP's beacon. We are trying to match
+       // AP's supported and extended rate settings.
+       UCHAR                   SupRate[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR                   ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR                   SupRateLen;
+       UCHAR                   ExtRateLen;
+       HT_CAPABILITY_IE                HtCapability;
+       UCHAR                           HtCapabilityLen;
+       ADD_HT_INFO_IE          AddHtInfo;      // AP might use this additional ht info IE
+       UCHAR                   NewExtChannelOffset;
+       //RT_HT_CAPABILITY      SupportedHtPhy;
+
+    // new for QOS
+    QOS_CAPABILITY_PARM APQosCapability;    // QOS capability of the current associated AP
+    EDCA_PARM           APEdcaParm;         // EDCA parameters of the current associated AP
+    QBSS_LOAD_PARM      APQbssLoad;         // QBSS load of the current associated AP
+
+    // new to keep Ralink specific feature
+    ULONG               APRalinkIe;
+
+    BSS_TABLE           SsidBssTab;     // AP list for the same SSID
+    BSS_TABLE           RoamTab;        // AP list eligible for roaming
+    ULONG               BssIdx;
+    ULONG               RoamIdx;
+
+       BOOLEAN                         CurrReqIsFromNdis;
+
+    RALINK_TIMER_STRUCT BeaconTimer, ScanTimer;
+    RALINK_TIMER_STRUCT AuthTimer;
+    RALINK_TIMER_STRUCT AssocTimer, ReassocTimer, DisassocTimer;
+} MLME_AUX, *PMLME_AUX;
+
+typedef struct _MLME_ADDBA_REQ_STRUCT{
+       UCHAR   Wcid;   //
+       UCHAR   pAddr[MAC_ADDR_LEN];
+       UCHAR   BaBufSize;
+       USHORT  TimeOutValue;
+       UCHAR   TID;
+       UCHAR   Token;
+       USHORT  BaStartSeq;
+} MLME_ADDBA_REQ_STRUCT, *PMLME_ADDBA_REQ_STRUCT;
+
+
+typedef struct _MLME_DELBA_REQ_STRUCT{
+       UCHAR   Wcid;   //
+       UCHAR     Addr[MAC_ADDR_LEN];
+       UCHAR   TID;
+       UCHAR   Initiator;
+} MLME_DELBA_REQ_STRUCT, *PMLME_DELBA_REQ_STRUCT;
+
+// assoc struct is equal to reassoc
+typedef struct _MLME_ASSOC_REQ_STRUCT{
+    UCHAR     Addr[MAC_ADDR_LEN];
+    USHORT    CapabilityInfo;
+    USHORT    ListenIntv;
+    ULONG     Timeout;
+} MLME_ASSOC_REQ_STRUCT, *PMLME_ASSOC_REQ_STRUCT, MLME_REASSOC_REQ_STRUCT, *PMLME_REASSOC_REQ_STRUCT;
+
+typedef struct _MLME_DISASSOC_REQ_STRUCT{
+    UCHAR     Addr[MAC_ADDR_LEN];
+    USHORT    Reason;
+} MLME_DISASSOC_REQ_STRUCT, *PMLME_DISASSOC_REQ_STRUCT;
+
+typedef struct _MLME_AUTH_REQ_STRUCT {
+    UCHAR        Addr[MAC_ADDR_LEN];
+    USHORT       Alg;
+    ULONG        Timeout;
+} MLME_AUTH_REQ_STRUCT, *PMLME_AUTH_REQ_STRUCT;
+
+typedef struct _MLME_DEAUTH_REQ_STRUCT {
+    UCHAR        Addr[MAC_ADDR_LEN];
+    USHORT       Reason;
+} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT;
+
+typedef struct {
+    ULONG      BssIdx;
+} MLME_JOIN_REQ_STRUCT;
+
+typedef struct _MLME_SCAN_REQ_STRUCT {
+    UCHAR      Bssid[MAC_ADDR_LEN];
+    UCHAR      BssType;
+    UCHAR      ScanType;
+    UCHAR      SsidLen;
+    CHAR       Ssid[MAX_LEN_OF_SSID];
+} MLME_SCAN_REQ_STRUCT, *PMLME_SCAN_REQ_STRUCT;
+
+typedef struct _MLME_START_REQ_STRUCT {
+    CHAR        Ssid[MAX_LEN_OF_SSID];
+    UCHAR       SsidLen;
+} MLME_START_REQ_STRUCT, *PMLME_START_REQ_STRUCT;
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+// structure for DLS
+typedef struct _RT_802_11_DLS {
+       USHORT                                          TimeOut;                // Use to time out while slience, unit: second , set by UI
+       USHORT                                          CountDownTimer; // Use to time out while slience,unit: second , used by driver only
+       NDIS_802_11_MAC_ADDRESS         MacAddr;                // set by UI
+       UCHAR                                           Status;                 // 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only
+       BOOLEAN                                         Valid;                  // 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link
+       RALINK_TIMER_STRUCT                     Timer;                  // Use to time out while handshake
+       USHORT                                          Sequence;
+       USHORT                                          MacTabMatchWCID;        // ASIC
+       BOOLEAN                                         bHTCap;
+       PVOID                                           pAd;
+} RT_802_11_DLS, *PRT_802_11_DLS;
+
+typedef struct _MLME_DLS_REQ_STRUCT {
+    PRT_802_11_DLS     pDLS;
+    USHORT                     Reason;
+} MLME_DLS_REQ_STRUCT, *PMLME_DLS_REQ_STRUCT;
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+typedef struct PACKED {
+    UCHAR   Eid;
+    UCHAR   Len;
+    CHAR   Octet[1];
+} EID_STRUCT,*PEID_STRUCT, BEACON_EID_STRUCT, *PBEACON_EID_STRUCT;
+
+typedef struct PACKED _RTMP_TX_RATE_SWITCH
+{
+       UCHAR   ItemNo;
+#ifdef RT_BIG_ENDIAN
+       UCHAR   Rsv2:2;
+       UCHAR   Mode:2;
+       UCHAR   Rsv1:1;
+       UCHAR   BW:1;
+       UCHAR   ShortGI:1;
+       UCHAR   STBC:1;
+#else
+       UCHAR   STBC:1;
+       UCHAR   ShortGI:1;
+       UCHAR   BW:1;
+       UCHAR   Rsv1:1;
+       UCHAR   Mode:2;
+       UCHAR   Rsv2:2;
+#endif
+       UCHAR   CurrMCS;
+       UCHAR   TrainUp;
+       UCHAR   TrainDown;
+} RRTMP_TX_RATE_SWITCH, *PRTMP_TX_RATE_SWITCH;
+
+// ========================== AP mlme.h ===============================
+#define TBTT_PRELOAD_TIME       384        // usec. LomgPreamble + 24-byte at 1Mbps
+#define DEFAULT_DTIM_PERIOD     1
+
+// weighting factor to calculate Channel quality, total should be 100%
+//#define RSSI_WEIGHTING                   0
+//#define TX_WEIGHTING                     40
+//#define RX_WEIGHTING                     60
+
+#define MAC_TABLE_AGEOUT_TIME                  300                     // unit: sec
+#define MAC_TABLE_ASSOC_TIMEOUT                        5                       // unit: sec
+#define MAC_TABLE_FULL(Tab)                            ((Tab).size == MAX_LEN_OF_MAC_TABLE)
+
+// AP shall drop the sta if contine Tx fail count reach it.
+#define MAC_ENTRY_LIFE_CHECK_CNT               20                      // packet cnt.
+
+// Value domain of pMacEntry->Sst
+typedef enum _Sst {
+    SST_NOT_AUTH,   // 0: equivalent to IEEE 802.11/1999 state 1
+    SST_AUTH,       // 1: equivalent to IEEE 802.11/1999 state 2
+    SST_ASSOC       // 2: equivalent to IEEE 802.11/1999 state 3
+} SST;
+
+// value domain of pMacEntry->AuthState
+typedef enum _AuthState {
+    AS_NOT_AUTH,
+    AS_AUTH_OPEN,       // STA has been authenticated using OPEN SYSTEM
+    AS_AUTH_KEY,        // STA has been authenticated using SHARED KEY
+    AS_AUTHENTICATING   // STA is waiting for AUTH seq#3 using SHARED KEY
+} AUTH_STATE;
+
+//for-wpa value domain of pMacEntry->WpaState  802.1i D3   p.114
+typedef enum _ApWpaState {
+    AS_NOTUSE,              // 0
+    AS_DISCONNECT,          // 1
+    AS_DISCONNECTED,        // 2
+    AS_INITIALIZE,          // 3
+    AS_AUTHENTICATION,      // 4
+    AS_AUTHENTICATION2,     // 5
+    AS_INITPMK,             // 6
+    AS_INITPSK,             // 7
+    AS_PTKSTART,            // 8
+    AS_PTKINIT_NEGOTIATING, // 9
+    AS_PTKINITDONE,         // 10
+    AS_UPDATEKEYS,          // 11
+    AS_INTEGRITY_FAILURE,   // 12
+    AS_KEYUPDATE,           // 13
+} AP_WPA_STATE;
+
+// for-wpa value domain of pMacEntry->WpaState  802.1i D3   p.114
+typedef enum _GTKState {
+    REKEY_NEGOTIATING,
+    REKEY_ESTABLISHED,
+    KEYERROR,
+} GTK_STATE;
+
+//  for-wpa  value domain of pMacEntry->WpaState  802.1i D3   p.114
+typedef enum _WpaGTKState {
+    SETKEYS,
+    SETKEYS_DONE,
+} WPA_GTK_STATE;
+// ====================== end of AP mlme.h ============================
+
+
+#endif // MLME_H__
diff --git a/drivers/staging/rt2870/netif_block.h b/drivers/staging/rt2870/netif_block.h
new file mode 100644 (file)
index 0000000..6e5151c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#ifndef __NET_IF_BLOCK_H__
+#define __NET_IF_BLOCK_H__
+
+//#include <linux/device.h>
+#include "link_list.h"
+#include "rtmp.h"
+
+#define FREE_NETIF_POOL_SIZE 32
+
+typedef struct _NETIF_ENTRY
+{
+       struct _NETIF_ENTRY *pNext;
+       PNET_DEV pNetDev;
+} NETIF_ENTRY, *PNETIF_ENTRY;
+
+void initblockQueueTab(
+       IN PRTMP_ADAPTER pAd);
+
+BOOLEAN blockNetIf(
+       IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry,
+       IN PNET_DEV pNetDev);
+
+VOID releaseNetIf(
+       IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry);
+
+VOID StopNetIfQueue(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR QueIdx,
+       IN PNDIS_PACKET pPacket);
+#endif // __NET_IF_BLOCK_H__
+
diff --git a/drivers/staging/rt2870/oid.h b/drivers/staging/rt2870/oid.h
new file mode 100644 (file)
index 0000000..d788db6
--- /dev/null
@@ -0,0 +1,1091 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       oid.h
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Name            Date                    Modification logs
+*/
+#ifndef _OID_H_
+#define _OID_H_
+
+#define TRUE                           1
+#define FALSE                          0
+//
+// IEEE 802.11 Structures and definitions
+//
+#define MAX_TX_POWER_LEVEL              100   /* mW */
+#define MAX_RSSI_TRIGGER                -10    /* dBm */
+#define MIN_RSSI_TRIGGER                -200   /* dBm */
+#define MAX_FRAG_THRESHOLD              2346  /* byte count */
+#define MIN_FRAG_THRESHOLD              256   /* byte count */
+#define MAX_RTS_THRESHOLD               2347  /* byte count */
+
+// new types for Media Specific Indications
+// Extension channel offset
+#define EXTCHA_NONE                    0
+#define EXTCHA_ABOVE           0x1
+#define EXTCHA_BELOW           0x3
+
+// BW
+#define BAND_WIDTH_20          0
+#define BAND_WIDTH_40          1
+#define BAND_WIDTH_BOTH                2
+#define BAND_WIDTH_10          3       // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field.
+// SHORTGI
+#define GAP_INTERVAL_400       1       // only support in HT mode
+#define GAP_INTERVAL_800       0
+#define GAP_INTERVAL_BOTH      2
+
+#define NdisMediaStateConnected                        1
+#define NdisMediaStateDisconnected             0
+
+#define NDIS_802_11_LENGTH_SSID         32
+#define NDIS_802_11_LENGTH_RATES        8
+#define NDIS_802_11_LENGTH_RATES_EX     16
+#define MAC_ADDR_LENGTH                 6
+#define MAX_NUM_OF_CHS                                 49 // 14 channels @2.4G +  12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL terminationc
+#define MAX_NUMBER_OF_EVENT                            10  // entry # in EVENT table
+#define MAX_NUMBER_OF_MAC                              32 // if MAX_MBSSID_NUM is 8, this value can't be larger than 211
+#define MAX_NUMBER_OF_ACL                              64
+#define MAX_LENGTH_OF_SUPPORT_RATES            12    // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
+#define MAX_NUMBER_OF_DLS_ENTRY                        4
+
+#ifndef UNDER_CE
+// OID definition, since NDIS 5.0 didn't define these, we need to define for our own
+//#if _WIN32_WINNT<=0x0500
+
+#define OID_GEN_MACHINE_NAME               0x0001021A
+
+#ifdef RALINK_ATE
+#define RT_QUERY_ATE_TXDONE_COUNT                      0x0401
+#endif // RALINK_ATE //
+#define RT_QUERY_SIGNAL_CONTEXT                                0x0402
+#define RT_SET_IAPP_PID                        0x0404
+#define RT_SET_APD_PID                                         0x0405
+#define RT_SET_DEL_MAC_ENTRY                           0x0406
+
+//
+// IEEE 802.11 OIDs
+//
+#define        OID_GET_SET_TOGGLE                      0x8000
+
+#define        OID_802_11_NETWORK_TYPES_SUPPORTED                      0x0103
+#define        OID_802_11_NETWORK_TYPE_IN_USE                          0x0104
+#define        OID_802_11_RSSI_TRIGGER                                         0x0107
+#define        RT_OID_802_11_RSSI                                                      0x0108 //rt2860 only , kathy
+#define        RT_OID_802_11_RSSI_1                                            0x0109 //rt2860 only , kathy
+#define        RT_OID_802_11_RSSI_2                                            0x010A //rt2860 only , kathy
+#define        OID_802_11_NUMBER_OF_ANTENNAS                           0x010B
+#define        OID_802_11_RX_ANTENNA_SELECTED                          0x010C
+#define        OID_802_11_TX_ANTENNA_SELECTED                          0x010D
+#define        OID_802_11_SUPPORTED_RATES                                      0x010E
+#define        OID_802_11_ADD_WEP                                                      0x0112
+#define        OID_802_11_REMOVE_WEP                                           0x0113
+#define        OID_802_11_DISASSOCIATE                                         0x0114
+#define        OID_802_11_PRIVACY_FILTER                                       0x0118
+#define        OID_802_11_ASSOCIATION_INFORMATION                      0x011E
+#define        OID_802_11_TEST                                                         0x011F
+#define        RT_OID_802_11_COUNTRY_REGION                            0x0507
+#define        OID_802_11_BSSID_LIST_SCAN                                      0x0508
+#define        OID_802_11_SSID                                                         0x0509
+#define        OID_802_11_BSSID                                                        0x050A
+#define        RT_OID_802_11_RADIO                                                     0x050B
+#define        RT_OID_802_11_PHY_MODE                                          0x050C
+#define        RT_OID_802_11_STA_CONFIG                                        0x050D
+#define        OID_802_11_DESIRED_RATES                                        0x050E
+#define        RT_OID_802_11_PREAMBLE                                          0x050F
+#define        OID_802_11_WEP_STATUS                                           0x0510
+#define        OID_802_11_AUTHENTICATION_MODE                          0x0511
+#define        OID_802_11_INFRASTRUCTURE_MODE                          0x0512
+#define        RT_OID_802_11_RESET_COUNTERS                            0x0513
+#define        OID_802_11_RTS_THRESHOLD                                        0x0514
+#define        OID_802_11_FRAGMENTATION_THRESHOLD                      0x0515
+#define        OID_802_11_POWER_MODE                                           0x0516
+#define        OID_802_11_TX_POWER_LEVEL                                       0x0517
+#define        RT_OID_802_11_ADD_WPA                                           0x0518
+#define        OID_802_11_REMOVE_KEY                                           0x0519
+#define        OID_802_11_ADD_KEY                                                      0x0520
+#define        OID_802_11_CONFIGURATION                                        0x0521
+#define        OID_802_11_TX_PACKET_BURST                                      0x0522
+#define        RT_OID_802_11_QUERY_NOISE_LEVEL                         0x0523
+#define        RT_OID_802_11_EXTRA_INFO                                        0x0524
+#ifdef DBG
+#define        RT_OID_802_11_HARDWARE_REGISTER                         0x0525
+#endif
+#define OID_802_11_ENCRYPTION_STATUS            OID_802_11_WEP_STATUS
+#define OID_802_11_DEAUTHENTICATION                 0x0526
+#define OID_802_11_DROP_UNENCRYPTED                 0x0527
+#define OID_802_11_MIC_FAILURE_REPORT_FRAME         0x0528
+
+// For 802.1x daemin using to require current driver configuration
+#define OID_802_11_RADIUS_QUERY_SETTING                                0x0540
+
+#define        RT_OID_DEVICE_NAME                                                      0x0607
+#define        RT_OID_VERSION_INFO                                                     0x0608
+#define        OID_802_11_BSSID_LIST                                           0x0609
+#define        OID_802_3_CURRENT_ADDRESS                                       0x060A
+#define        OID_GEN_MEDIA_CONNECT_STATUS                            0x060B
+#define        RT_OID_802_11_QUERY_LINK_STATUS                         0x060C
+#define        OID_802_11_RSSI                                                         0x060D
+#define        OID_802_11_STATISTICS                                           0x060E
+#define        OID_GEN_RCV_OK                                                          0x060F
+#define        OID_GEN_RCV_NO_BUFFER                                           0x0610
+#define        RT_OID_802_11_QUERY_EEPROM_VERSION                      0x0611
+#define        RT_OID_802_11_QUERY_FIRMWARE_VERSION            0x0612
+#define        RT_OID_802_11_QUERY_LAST_RX_RATE                        0x0613
+#define        RT_OID_802_11_TX_POWER_LEVEL_1                          0x0614
+#define        RT_OID_802_11_QUERY_PIDVID                                      0x0615
+//for WPA_SUPPLICANT_SUPPORT
+#define OID_SET_COUNTERMEASURES                     0x0616
+#define OID_802_11_SET_IEEE8021X                    0x0617
+#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY        0x0618
+#define OID_802_11_PMKID                            0x0620
+#define RT_OID_WPA_SUPPLICANT_SUPPORT               0x0621
+#define RT_OID_WE_VERSION_COMPILED                  0x0622
+#define RT_OID_NEW_DRIVER                           0x0623
+
+
+//rt2860 , kathy
+#define        RT_OID_802_11_SNR_0                                                     0x0630
+#define        RT_OID_802_11_SNR_1                                                     0x0631
+#define        RT_OID_802_11_QUERY_LAST_TX_RATE                        0x0632
+#define        RT_OID_802_11_QUERY_HT_PHYMODE                          0x0633
+#define        RT_OID_802_11_SET_HT_PHYMODE                            0x0634
+#define        OID_802_11_RELOAD_DEFAULTS                                      0x0635
+#define        RT_OID_802_11_QUERY_APSD_SETTING                        0x0636
+#define        RT_OID_802_11_SET_APSD_SETTING                          0x0637
+#define        RT_OID_802_11_QUERY_APSD_PSM                            0x0638
+#define        RT_OID_802_11_SET_APSD_PSM                                      0x0639
+#define        RT_OID_802_11_QUERY_DLS                                         0x063A
+#define        RT_OID_802_11_SET_DLS                                           0x063B
+#define        RT_OID_802_11_QUERY_DLS_PARAM                           0x063C
+#define        RT_OID_802_11_SET_DLS_PARAM                                     0x063D
+#define RT_OID_802_11_QUERY_WMM                        0x063E
+#define RT_OID_802_11_SET_WMM                                          0x063F
+#define RT_OID_802_11_QUERY_IMME_BA_CAP                                0x0640
+#define RT_OID_802_11_SET_IMME_BA_CAP                          0x0641
+#define RT_OID_802_11_QUERY_BATABLE                                    0x0642
+#define RT_OID_802_11_ADD_IMME_BA                                      0x0643
+#define RT_OID_802_11_TEAR_IMME_BA                                     0x0644
+#define RT_OID_DRIVER_DEVICE_NAME                   0x0645
+#define RT_OID_802_11_QUERY_DAT_HT_PHYMODE          0x0646
+#define RT_OID_QUERY_MULTIPLE_CARD_SUPPORT          0x0647
+
+// Ralink defined OIDs
+// Dennis Lee move to platform specific
+
+#define        RT_OID_802_11_BSSID                                       (OID_GET_SET_TOGGLE | OID_802_11_BSSID)
+#define        RT_OID_802_11_SSID                                        (OID_GET_SET_TOGGLE | OID_802_11_SSID)
+#define        RT_OID_802_11_INFRASTRUCTURE_MODE         (OID_GET_SET_TOGGLE | OID_802_11_INFRASTRUCTURE_MODE)
+#define        RT_OID_802_11_ADD_WEP                             (OID_GET_SET_TOGGLE | OID_802_11_ADD_WEP)
+#define        RT_OID_802_11_ADD_KEY                             (OID_GET_SET_TOGGLE | OID_802_11_ADD_KEY)
+#define        RT_OID_802_11_REMOVE_WEP                          (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_WEP)
+#define        RT_OID_802_11_REMOVE_KEY                          (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_KEY)
+#define        RT_OID_802_11_DISASSOCIATE                        (OID_GET_SET_TOGGLE | OID_802_11_DISASSOCIATE)
+#define        RT_OID_802_11_AUTHENTICATION_MODE         (OID_GET_SET_TOGGLE | OID_802_11_AUTHENTICATION_MODE)
+#define        RT_OID_802_11_PRIVACY_FILTER              (OID_GET_SET_TOGGLE | OID_802_11_PRIVACY_FILTER)
+#define        RT_OID_802_11_BSSID_LIST_SCAN             (OID_GET_SET_TOGGLE | OID_802_11_BSSID_LIST_SCAN)
+#define        RT_OID_802_11_WEP_STATUS                          (OID_GET_SET_TOGGLE | OID_802_11_WEP_STATUS)
+#define        RT_OID_802_11_RELOAD_DEFAULTS             (OID_GET_SET_TOGGLE | OID_802_11_RELOAD_DEFAULTS)
+#define        RT_OID_802_11_NETWORK_TYPE_IN_USE         (OID_GET_SET_TOGGLE | OID_802_11_NETWORK_TYPE_IN_USE)
+#define        RT_OID_802_11_TX_POWER_LEVEL              (OID_GET_SET_TOGGLE | OID_802_11_TX_POWER_LEVEL)
+#define        RT_OID_802_11_RSSI_TRIGGER                        (OID_GET_SET_TOGGLE | OID_802_11_RSSI_TRIGGER)
+#define        RT_OID_802_11_FRAGMENTATION_THRESHOLD (OID_GET_SET_TOGGLE |     OID_802_11_FRAGMENTATION_THRESHOLD)
+#define        RT_OID_802_11_RTS_THRESHOLD                       (OID_GET_SET_TOGGLE | OID_802_11_RTS_THRESHOLD)
+#define        RT_OID_802_11_RX_ANTENNA_SELECTED         (OID_GET_SET_TOGGLE | OID_802_11_RX_ANTENNA_SELECTED)
+#define        RT_OID_802_11_TX_ANTENNA_SELECTED         (OID_GET_SET_TOGGLE | OID_802_11_TX_ANTENNA_SELECTED)
+#define        RT_OID_802_11_SUPPORTED_RATES             (OID_GET_SET_TOGGLE | OID_802_11_SUPPORTED_RATES)
+#define        RT_OID_802_11_DESIRED_RATES                       (OID_GET_SET_TOGGLE | OID_802_11_DESIRED_RATES)
+#define        RT_OID_802_11_CONFIGURATION                       (OID_GET_SET_TOGGLE | OID_802_11_CONFIGURATION)
+#define        RT_OID_802_11_POWER_MODE                          (OID_GET_SET_TOGGLE | OID_802_11_POWER_MODE)
+
+typedef enum _NDIS_802_11_STATUS_TYPE
+{
+    Ndis802_11StatusType_Authentication,
+    Ndis802_11StatusType_MediaStreamMode,
+    Ndis802_11StatusType_PMKID_CandidateList,
+    Ndis802_11StatusTypeMax    // not a real type, defined as an upper bound
+} NDIS_802_11_STATUS_TYPE, *PNDIS_802_11_STATUS_TYPE;
+
+typedef UCHAR   NDIS_802_11_MAC_ADDRESS[6];
+
+typedef struct _NDIS_802_11_STATUS_INDICATION
+{
+    NDIS_802_11_STATUS_TYPE StatusType;
+} NDIS_802_11_STATUS_INDICATION, *PNDIS_802_11_STATUS_INDICATION;
+
+// mask for authentication/integrity fields
+#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS        0x0f
+
+#define NDIS_802_11_AUTH_REQUEST_REAUTH             0x01
+#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE          0x02
+#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR     0x06
+#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR        0x0E
+
+typedef struct _NDIS_802_11_AUTHENTICATION_REQUEST
+{
+    ULONG Length;            // Length of structure
+    NDIS_802_11_MAC_ADDRESS Bssid;
+    ULONG Flags;
+} NDIS_802_11_AUTHENTICATION_REQUEST, *PNDIS_802_11_AUTHENTICATION_REQUEST;
+
+//Added new types for PMKID Candidate lists.
+typedef struct _PMKID_CANDIDATE {
+    NDIS_802_11_MAC_ADDRESS BSSID;
+    ULONG Flags;
+} PMKID_CANDIDATE, *PPMKID_CANDIDATE;
+
+typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST
+{
+    ULONG Version;       // Version of the structure
+    ULONG NumCandidates; // No. of pmkid candidates
+    PMKID_CANDIDATE CandidateList[1];
+} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST;
+
+//Flags for PMKID Candidate list structure
+#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED    0x01
+
+// Added new types for OFDM 5G and 2.4G
+typedef enum _NDIS_802_11_NETWORK_TYPE
+{
+   Ndis802_11FH,
+   Ndis802_11DS,
+    Ndis802_11OFDM5,
+    Ndis802_11OFDM5_N,
+    Ndis802_11OFDM24,
+    Ndis802_11OFDM24_N,
+   Ndis802_11Automode,
+    Ndis802_11NetworkTypeMax    // not a real type, defined as an upper bound
+} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE;
+
+typedef struct _NDIS_802_11_NETWORK_TYPE_LIST
+{
+    UINT                       NumberOfItems;  // in list below, at least 1
+   NDIS_802_11_NETWORK_TYPE    NetworkType [1];
+} NDIS_802_11_NETWORK_TYPE_LIST, *PNDIS_802_11_NETWORK_TYPE_LIST;
+
+typedef enum _NDIS_802_11_POWER_MODE
+{
+    Ndis802_11PowerModeCAM,
+    Ndis802_11PowerModeMAX_PSP,
+    Ndis802_11PowerModeFast_PSP,
+    Ndis802_11PowerModeLegacy_PSP,
+    Ndis802_11PowerModeMax      // not a real mode, defined as an upper bound
+} NDIS_802_11_POWER_MODE, *PNDIS_802_11_POWER_MODE;
+
+typedef ULONG   NDIS_802_11_TX_POWER_LEVEL; // in milliwatts
+
+//
+// Received Signal Strength Indication
+//
+typedef LONG    NDIS_802_11_RSSI;           // in dBm
+
+typedef struct _NDIS_802_11_CONFIGURATION_FH
+{
+   ULONG           Length;            // Length of structure
+   ULONG           HopPattern;        // As defined by 802.11, MSB set
+   ULONG           HopSet;            // to one if non-802.11
+   ULONG           DwellTime;         // units are Kusec
+} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH;
+
+typedef struct _NDIS_802_11_CONFIGURATION
+{
+   ULONG                           Length;             // Length of structure
+   ULONG                           BeaconPeriod;       // units are Kusec
+   ULONG                           ATIMWindow;         // units are Kusec
+   ULONG                           DSConfig;           // Frequency, units are kHz
+   NDIS_802_11_CONFIGURATION_FH    FHConfig;
+} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION;
+
+typedef struct _NDIS_802_11_STATISTICS
+{
+   ULONG           Length;             // Length of structure
+   LARGE_INTEGER   TransmittedFragmentCount;
+   LARGE_INTEGER   MulticastTransmittedFrameCount;
+   LARGE_INTEGER   FailedCount;
+   LARGE_INTEGER   RetryCount;
+   LARGE_INTEGER   MultipleRetryCount;
+   LARGE_INTEGER   RTSSuccessCount;
+   LARGE_INTEGER   RTSFailureCount;
+   LARGE_INTEGER   ACKFailureCount;
+   LARGE_INTEGER   FrameDuplicateCount;
+   LARGE_INTEGER   ReceivedFragmentCount;
+   LARGE_INTEGER   MulticastReceivedFrameCount;
+   LARGE_INTEGER   FCSErrorCount;
+   LARGE_INTEGER   TKIPLocalMICFailures;
+   LARGE_INTEGER   TKIPRemoteMICErrors;
+   LARGE_INTEGER   TKIPICVErrors;
+   LARGE_INTEGER   TKIPCounterMeasuresInvoked;
+   LARGE_INTEGER   TKIPReplays;
+   LARGE_INTEGER   CCMPFormatErrors;
+   LARGE_INTEGER   CCMPReplays;
+   LARGE_INTEGER   CCMPDecryptErrors;
+   LARGE_INTEGER   FourWayHandshakeFailures;
+} NDIS_802_11_STATISTICS, *PNDIS_802_11_STATISTICS;
+
+typedef  ULONG  NDIS_802_11_KEY_INDEX;
+typedef ULONGLONG   NDIS_802_11_KEY_RSC;
+
+#define MAX_RADIUS_SRV_NUM                     2         // 802.1x failover number
+
+typedef struct PACKED _RADIUS_SRV_INFO {
+       UINT32                  radius_ip;
+       UINT32                  radius_port;
+       UCHAR                   radius_key[64];
+       UCHAR                   radius_key_len;
+} RADIUS_SRV_INFO, *PRADIUS_SRV_INFO;
+
+typedef struct PACKED _RADIUS_KEY_INFO
+{
+       UCHAR                   radius_srv_num;
+       RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM];
+       UCHAR                   ieee8021xWEP;            // dynamic WEP
+    UCHAR           key_index;
+    UCHAR           key_length;          // length of key in bytes
+    UCHAR           key_material[13];
+} RADIUS_KEY_INFO, *PRADIUS_KEY_INFO;
+
+// It's used by 802.1x daemon to require relative configuration
+typedef struct PACKED _RADIUS_CONF
+{
+    UINT32          Length;             // Length of this structure
+    UCHAR                      mbss_num;                       // indicate multiple BSS number
+       UINT32                  own_ip_addr;
+       UINT32                  retry_interval;
+       UINT32                  session_timeout_interval;
+       UCHAR                   EAPifname[IFNAMSIZ];
+       UCHAR                   EAPifname_len;
+       UCHAR                   PreAuthifname[IFNAMSIZ];
+       UCHAR                   PreAuthifname_len;
+       RADIUS_KEY_INFO RadiusInfo[8/*MAX_MBSSID_NUM*/];
+} RADIUS_CONF, *PRADIUS_CONF;
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+// Key mapping keys require a BSSID
+typedef struct _NDIS_802_11_KEY
+{
+    UINT           Length;             // Length of this structure
+    UINT           KeyIndex;
+    UINT           KeyLength;          // length of key in bytes
+    NDIS_802_11_MAC_ADDRESS BSSID;
+    NDIS_802_11_KEY_RSC KeyRSC;
+    UCHAR           KeyMaterial[1];     // variable length depending on above field
+} NDIS_802_11_KEY, *PNDIS_802_11_KEY;
+#endif // CONFIG_STA_SUPPORT //
+
+typedef struct _NDIS_802_11_REMOVE_KEY
+{
+    UINT           Length;             // Length of this structure
+    UINT           KeyIndex;
+    NDIS_802_11_MAC_ADDRESS BSSID;
+} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY;
+
+typedef struct _NDIS_802_11_WEP
+{
+   UINT     Length;        // Length of this structure
+   UINT     KeyIndex;           // 0 is the per-client key, 1-N are the
+                                        // global keys
+   UINT     KeyLength;     // length of key in bytes
+   UCHAR     KeyMaterial[1];// variable length depending on above field
+} NDIS_802_11_WEP, *PNDIS_802_11_WEP;
+
+
+typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE
+{
+   Ndis802_11IBSS,
+   Ndis802_11Infrastructure,
+   Ndis802_11AutoUnknown,
+   Ndis802_11Monitor,
+   Ndis802_11InfrastructureMax     // Not a real value, defined as upper bound
+} NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE;
+
+// Add new authentication modes
+typedef enum _NDIS_802_11_AUTHENTICATION_MODE
+{
+   Ndis802_11AuthModeOpen,
+   Ndis802_11AuthModeShared,
+   Ndis802_11AuthModeAutoSwitch,
+    Ndis802_11AuthModeWPA,
+    Ndis802_11AuthModeWPAPSK,
+    Ndis802_11AuthModeWPANone,
+   Ndis802_11AuthModeWPA2,
+   Ndis802_11AuthModeWPA2PSK,
+       Ndis802_11AuthModeWPA1WPA2,
+       Ndis802_11AuthModeWPA1PSKWPA2PSK,
+   Ndis802_11AuthModeMax           // Not a real mode, defined as upper bound
+} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE;
+
+typedef UCHAR   NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES];        // Set of 8 data rates
+typedef UCHAR   NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];  // Set of 16 data rates
+
+typedef struct PACKED _NDIS_802_11_SSID
+{
+    UINT   SsidLength;         // length of SSID field below, in bytes;
+                                // this can be zero.
+    UCHAR   Ssid[NDIS_802_11_LENGTH_SSID];           // SSID information field
+} NDIS_802_11_SSID, *PNDIS_802_11_SSID;
+
+
+typedef struct PACKED _NDIS_WLAN_BSSID
+{
+   ULONG                               Length;     // Length of this structure
+   NDIS_802_11_MAC_ADDRESS             MacAddress; // BSSID
+   UCHAR                               Reserved[2];
+   NDIS_802_11_SSID                    Ssid;       // SSID
+   ULONG                               Privacy;    // WEP encryption requirement
+   NDIS_802_11_RSSI                    Rssi;       // receive signal strength in dBm
+   NDIS_802_11_NETWORK_TYPE            NetworkTypeInUse;
+   NDIS_802_11_CONFIGURATION           Configuration;
+   NDIS_802_11_NETWORK_INFRASTRUCTURE  InfrastructureMode;
+   NDIS_802_11_RATES                   SupportedRates;
+} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID;
+
+typedef struct PACKED _NDIS_802_11_BSSID_LIST
+{
+   UINT           NumberOfItems;      // in list below, at least 1
+   NDIS_WLAN_BSSID Bssid[1];
+} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST;
+
+// Added Capabilities, IELength and IEs for each BSSID
+typedef struct PACKED _NDIS_WLAN_BSSID_EX
+{
+    ULONG                               Length;             // Length of this structure
+    NDIS_802_11_MAC_ADDRESS             MacAddress;         // BSSID
+    UCHAR                               Reserved[2];
+    NDIS_802_11_SSID                    Ssid;               // SSID
+    UINT                                Privacy;            // WEP encryption requirement
+    NDIS_802_11_RSSI                    Rssi;               // receive signal
+                                                            // strength in dBm
+    NDIS_802_11_NETWORK_TYPE            NetworkTypeInUse;
+    NDIS_802_11_CONFIGURATION           Configuration;
+    NDIS_802_11_NETWORK_INFRASTRUCTURE  InfrastructureMode;
+    NDIS_802_11_RATES_EX                SupportedRates;
+    ULONG                               IELength;
+    UCHAR                               IEs[1];
+} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX;
+
+typedef struct PACKED _NDIS_802_11_BSSID_LIST_EX
+{
+    UINT                   NumberOfItems;      // in list below, at least 1
+    NDIS_WLAN_BSSID_EX      Bssid[1];
+} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX;
+
+typedef struct PACKED _NDIS_802_11_FIXED_IEs
+{
+    UCHAR Timestamp[8];
+    USHORT BeaconInterval;
+    USHORT Capabilities;
+} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs;
+
+typedef struct _NDIS_802_11_VARIABLE_IEs
+{
+    UCHAR ElementID;
+    UCHAR Length;    // Number of bytes in data field
+    UCHAR data[1];
+} NDIS_802_11_VARIABLE_IEs, *PNDIS_802_11_VARIABLE_IEs;
+
+typedef  ULONG   NDIS_802_11_FRAGMENTATION_THRESHOLD;
+
+typedef  ULONG   NDIS_802_11_RTS_THRESHOLD;
+
+typedef  ULONG   NDIS_802_11_ANTENNA;
+
+typedef enum _NDIS_802_11_PRIVACY_FILTER
+{
+   Ndis802_11PrivFilterAcceptAll,
+   Ndis802_11PrivFilter8021xWEP
+} NDIS_802_11_PRIVACY_FILTER, *PNDIS_802_11_PRIVACY_FILTER;
+
+// Added new encryption types
+// Also aliased typedef to new name
+typedef enum _NDIS_802_11_WEP_STATUS
+{
+   Ndis802_11WEPEnabled,
+    Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
+   Ndis802_11WEPDisabled,
+    Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
+   Ndis802_11WEPKeyAbsent,
+    Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
+   Ndis802_11WEPNotSupported,
+    Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
+    Ndis802_11Encryption2Enabled,
+    Ndis802_11Encryption2KeyAbsent,
+    Ndis802_11Encryption3Enabled,
+    Ndis802_11Encryption3KeyAbsent,
+    Ndis802_11Encryption4Enabled,      // TKIP or AES mix
+    Ndis802_11Encryption4KeyAbsent,
+    Ndis802_11GroupWEP40Enabled,
+       Ndis802_11GroupWEP104Enabled,
+} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS,
+  NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS;
+
+typedef enum _NDIS_802_11_RELOAD_DEFAULTS
+{
+   Ndis802_11ReloadWEPKeys
+} NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS;
+
+#define NDIS_802_11_AI_REQFI_CAPABILITIES      1
+#define NDIS_802_11_AI_REQFI_LISTENINTERVAL    2
+#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS  4
+
+#define NDIS_802_11_AI_RESFI_CAPABILITIES      1
+#define NDIS_802_11_AI_RESFI_STATUSCODE        2
+#define NDIS_802_11_AI_RESFI_ASSOCIATIONID     4
+
+typedef struct _NDIS_802_11_AI_REQFI
+{
+    USHORT Capabilities;
+    USHORT ListenInterval;
+    NDIS_802_11_MAC_ADDRESS  CurrentAPAddress;
+} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI;
+
+typedef struct _NDIS_802_11_AI_RESFI
+{
+    USHORT Capabilities;
+    USHORT StatusCode;
+    USHORT AssociationId;
+} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI;
+
+typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION
+{
+    ULONG                   Length;
+    USHORT                  AvailableRequestFixedIEs;
+    NDIS_802_11_AI_REQFI    RequestFixedIEs;
+    ULONG                   RequestIELength;
+    ULONG                   OffsetRequestIEs;
+    USHORT                  AvailableResponseFixedIEs;
+    NDIS_802_11_AI_RESFI    ResponseFixedIEs;
+    ULONG                   ResponseIELength;
+    ULONG                   OffsetResponseIEs;
+} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION;
+
+typedef struct _NDIS_802_11_AUTHENTICATION_EVENT
+{
+    NDIS_802_11_STATUS_INDICATION       Status;
+    NDIS_802_11_AUTHENTICATION_REQUEST  Request[1];
+} NDIS_802_11_AUTHENTICATION_EVENT, *PNDIS_802_11_AUTHENTICATION_EVENT;
+
+/*
+typedef struct _NDIS_802_11_TEST
+{
+    ULONG Length;
+    ULONG Type;
+    union
+    {
+        NDIS_802_11_AUTHENTICATION_EVENT AuthenticationEvent;
+        NDIS_802_11_RSSI RssiTrigger;
+    };
+} NDIS_802_11_TEST, *PNDIS_802_11_TEST;
+ */
+
+// 802.11 Media stream constraints, associated with OID_802_11_MEDIA_STREAM_MODE
+typedef enum _NDIS_802_11_MEDIA_STREAM_MODE
+{
+    Ndis802_11MediaStreamOff,
+    Ndis802_11MediaStreamOn,
+} NDIS_802_11_MEDIA_STREAM_MODE, *PNDIS_802_11_MEDIA_STREAM_MODE;
+
+// PMKID Structures
+typedef UCHAR   NDIS_802_11_PMKID_VALUE[16];
+
+#ifdef CONFIG_STA_SUPPORT
+typedef struct _BSSID_INFO
+{
+    NDIS_802_11_MAC_ADDRESS BSSID;
+    NDIS_802_11_PMKID_VALUE PMKID;
+} BSSID_INFO, *PBSSID_INFO;
+
+typedef struct _NDIS_802_11_PMKID
+{
+    UINT    Length;
+    UINT    BSSIDInfoCount;
+    BSSID_INFO BSSIDInfo[1];
+} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID;
+#endif // CONFIG_STA_SUPPORT //
+
+
+typedef struct _NDIS_802_11_AUTHENTICATION_ENCRYPTION
+{
+    NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported;
+    NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported;
+} NDIS_802_11_AUTHENTICATION_ENCRYPTION, *PNDIS_802_11_AUTHENTICATION_ENCRYPTION;
+
+typedef struct _NDIS_802_11_CAPABILITY
+{
+     ULONG Length;
+     ULONG Version;
+     ULONG NoOfPMKIDs;
+     ULONG NoOfAuthEncryptPairsSupported;
+     NDIS_802_11_AUTHENTICATION_ENCRYPTION AuthenticationEncryptionSupported[1];
+} NDIS_802_11_CAPABILITY, *PNDIS_802_11_CAPABILITY;
+
+//#endif //of WIN 2k
+#endif //UNDER_CE
+
+#if WIRELESS_EXT <= 11
+#ifndef SIOCDEVPRIVATE
+#define SIOCDEVPRIVATE                              0x8BE0
+#endif
+#define SIOCIWFIRSTPRIV                                                                SIOCDEVPRIVATE
+#endif
+
+#ifdef CONFIG_STA_SUPPORT
+#define RTPRIV_IOCTL_SET                                                       (SIOCIWFIRSTPRIV + 0x02)
+
+#ifdef DBG
+#define RTPRIV_IOCTL_BBP                            (SIOCIWFIRSTPRIV + 0x03)
+#define RTPRIV_IOCTL_MAC                            (SIOCIWFIRSTPRIV + 0x05)
+#define RTPRIV_IOCTL_E2P                            (SIOCIWFIRSTPRIV + 0x07)
+#endif
+
+#ifdef RALINK_ATE
+#ifdef RALINK_28xx_QA
+#define RTPRIV_IOCTL_ATE                                                       (SIOCIWFIRSTPRIV + 0x08)
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+#define RTPRIV_IOCTL_STATISTICS                     (SIOCIWFIRSTPRIV + 0x09)
+#define RTPRIV_IOCTL_ADD_PMKID_CACHE                (SIOCIWFIRSTPRIV + 0x0A)
+#define RTPRIV_IOCTL_RADIUS_DATA                    (SIOCIWFIRSTPRIV + 0x0C)
+#define RTPRIV_IOCTL_GSITESURVEY                                       (SIOCIWFIRSTPRIV + 0x0D)
+#define RT_PRIV_IOCTL                                                          (SIOCIWFIRSTPRIV + 0x0E) // Sync. with RT61 (for wpa_supplicant)
+#define RTPRIV_IOCTL_GET_MAC_TABLE                                     (SIOCIWFIRSTPRIV + 0x0F)
+
+#define RTPRIV_IOCTL_SHOW                                                      (SIOCIWFIRSTPRIV + 0x11)
+enum {
+    SHOW_CONN_STATUS = 4,
+    SHOW_DRVIER_VERION = 5,
+    SHOW_BA_INFO = 6,
+       SHOW_DESC_INFO = 7,
+#ifdef RT2870
+       SHOW_RXBULK_INFO = 8,
+       SHOW_TXBULK_INFO = 9,
+#endif // RT2870 //
+    RAIO_OFF = 10,
+    RAIO_ON = 11,
+#ifdef QOS_DLS_SUPPORT
+       SHOW_DLS_ENTRY_INFO = 19,
+#endif // QOS_DLS_SUPPORT //
+       SHOW_CFG_VALUE = 20,
+       SHOW_ADHOC_ENTRY_INFO = 21,
+};
+
+
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef SNMP_SUPPORT
+//SNMP ieee 802dot11, kathy , 2008_0220
+// dot11res(3)
+#define RT_OID_802_11_MANUFACTUREROUI                  0x0700
+#define RT_OID_802_11_MANUFACTURERNAME                 0x0701
+#define RT_OID_802_11_RESOURCETYPEIDNAME               0x0702
+
+// dot11smt(1)
+#define RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED 0x0703
+#define RT_OID_802_11_POWERMANAGEMENTMODE              0x0704
+#define OID_802_11_WEPDEFAULTKEYVALUE                  0x0705 // read , write
+#define OID_802_11_WEPDEFAULTKEYID                             0x0706
+#define RT_OID_802_11_WEPKEYMAPPINGLENGTH              0x0707
+#define OID_802_11_SHORTRETRYLIMIT                             0x0708
+#define OID_802_11_LONGRETRYLIMIT                              0x0709
+#define RT_OID_802_11_PRODUCTID                                        0x0710
+#define RT_OID_802_11_MANUFACTUREID                            0x0711
+
+// //dot11Phy(4)
+#define OID_802_11_CURRENTCHANNEL                              0x0712
+
+//dot11mac
+#define RT_OID_802_11_MAC_ADDRESS                              0x0713
+#endif // SNMP_SUPPORT //
+
+#define OID_802_11_BUILD_CHANNEL_EX                            0x0714
+#define OID_802_11_GET_CH_LIST                                 0x0715
+#define OID_802_11_GET_COUNTRY_CODE                            0x0716
+#define OID_802_11_GET_CHANNEL_GEOGRAPHY               0x0717
+
+#ifdef LLTD_SUPPORT
+// for consistency with RT61
+#define RT_OID_GET_PHY_MODE                         0x761
+#endif // LLTD_SUPPORT //
+
+// MIMO Tx parameter, ShortGI, MCS, STBC, etc.  these are fields in TXWI. Don't change this definition!!!
+typedef union  _HTTRANSMIT_SETTING {
+#ifdef RT_BIG_ENDIAN
+       struct  {
+       USHORT          MODE:2; // Use definition MODE_xxx.
+//     USHORT          rsv:3;
+       USHORT          TxBF:1;
+       USHORT          rsv:2;
+       USHORT          STBC:2; //SPACE
+       USHORT          ShortGI:1;
+       USHORT          BW:1;   //channel bandwidth 20MHz or 40 MHz
+       USHORT          MCS:7;                 // MCS
+       }       field;
+#else
+       struct  {
+       USHORT          MCS:7;                 // MCS
+       USHORT          BW:1;   //channel bandwidth 20MHz or 40 MHz
+       USHORT          ShortGI:1;
+       USHORT          STBC:2; //SPACE
+//     USHORT          rsv:3;
+       USHORT          rsv:2;
+       USHORT          TxBF:1;
+       USHORT          MODE:2; // Use definition MODE_xxx.
+       }       field;
+#endif
+       USHORT          word;
+ } HTTRANSMIT_SETTING, *PHTTRANSMIT_SETTING;
+
+typedef enum _RT_802_11_PREAMBLE {
+    Rt802_11PreambleLong,
+    Rt802_11PreambleShort,
+    Rt802_11PreambleAuto
+} RT_802_11_PREAMBLE, *PRT_802_11_PREAMBLE;
+
+// Only for STA, need to sync with AP
+typedef enum _RT_802_11_PHY_MODE {
+       PHY_11BG_MIXED = 0,
+       PHY_11B,
+       PHY_11A,
+       PHY_11ABG_MIXED,
+       PHY_11G,
+#ifdef DOT11_N_SUPPORT
+       PHY_11ABGN_MIXED,       // both band   5
+       PHY_11N_2_4G,           // 11n-only with 2.4G band      6
+       PHY_11GN_MIXED, // 2.4G band      7
+       PHY_11AN_MIXED, // 5G  band       8
+       PHY_11BGN_MIXED,        // if check 802.11b.      9
+       PHY_11AGN_MIXED,        // if check 802.11b.      10
+       PHY_11N_5G,                     // 11n-only with 5G band                11
+#endif // DOT11_N_SUPPORT //
+} RT_802_11_PHY_MODE;
+
+// put all proprietery for-query objects here to reduce # of Query_OID
+typedef struct _RT_802_11_LINK_STATUS {
+    ULONG   CurrTxRate;         // in units of 0.5Mbps
+    ULONG   ChannelQuality;     // 0..100 %
+    ULONG   TxByteCount;        // both ok and fail
+    ULONG   RxByteCount;        // both ok and fail
+    ULONG      CentralChannel;         // 40MHz central channel number
+} RT_802_11_LINK_STATUS, *PRT_802_11_LINK_STATUS;
+
+typedef struct _RT_802_11_EVENT_LOG {
+    LARGE_INTEGER   SystemTime;  // timestammp via NdisGetCurrentSystemTime()
+    UCHAR           Addr[MAC_ADDR_LENGTH];
+    USHORT          Event;       // EVENT_xxx
+} RT_802_11_EVENT_LOG, *PRT_802_11_EVENT_LOG;
+
+typedef struct _RT_802_11_EVENT_TABLE {
+    ULONG       Num;
+    ULONG       Rsv;     // to align Log[] at LARGE_INEGER boundary
+    RT_802_11_EVENT_LOG   Log[MAX_NUMBER_OF_EVENT];
+} RT_802_11_EVENT_TABLE, PRT_802_11_EVENT_TABLE;
+
+// MIMO Tx parameter, ShortGI, MCS, STBC, etc.  these are fields in TXWI. Don't change this definition!!!
+typedef union  _MACHTTRANSMIT_SETTING {
+       struct  {
+       USHORT          MCS:7;                 // MCS
+       USHORT          BW:1;   //channel bandwidth 20MHz or 40 MHz
+       USHORT          ShortGI:1;
+       USHORT          STBC:2; //SPACE
+       USHORT          rsv:3;
+       USHORT          MODE:2; // Use definition MODE_xxx.
+       }       field;
+       USHORT          word;
+ } MACHTTRANSMIT_SETTING, *PMACHTTRANSMIT_SETTING;
+
+typedef struct _RT_802_11_MAC_ENTRY {
+    UCHAR       Addr[MAC_ADDR_LENGTH];
+    UCHAR       Aid;
+    UCHAR       Psm;     // 0:PWR_ACTIVE, 1:PWR_SAVE
+    UCHAR              MimoPs;  // 0:MMPS_STATIC, 1:MMPS_DYNAMIC, 3:MMPS_Enabled
+    CHAR               AvgRssi0;
+       CHAR            AvgRssi1;
+       CHAR            AvgRssi2;
+       UINT32          ConnectedTime;
+    MACHTTRANSMIT_SETTING      TxRate;
+} RT_802_11_MAC_ENTRY, *PRT_802_11_MAC_ENTRY;
+
+typedef struct _RT_802_11_MAC_TABLE {
+    ULONG       Num;
+    RT_802_11_MAC_ENTRY Entry[MAX_NUMBER_OF_MAC];
+} RT_802_11_MAC_TABLE, *PRT_802_11_MAC_TABLE;
+
+// structure for query/set hardware register - MAC, BBP, RF register
+typedef struct _RT_802_11_HARDWARE_REGISTER {
+    ULONG   HardwareType;       // 0:MAC, 1:BBP, 2:RF register, 3:EEPROM
+    ULONG   Offset;             // Q/S register offset addr
+    ULONG   Data;               // R/W data buffer
+} RT_802_11_HARDWARE_REGISTER, *PRT_802_11_HARDWARE_REGISTER;
+
+// structure to tune BBP R17 "RX AGC VGC init"
+//typedef struct _RT_802_11_RX_AGC_VGC_TUNING {
+//    UCHAR   FalseCcaLowerThreshold;  // 0-255, def 10
+//    UCHAR   FalseCcaUpperThreshold;  // 0-255, def 100
+//    UCHAR   VgcDelta;                // R17 +-= VgcDelta whenever flase CCA over UpprThreshold
+//                                     // or lower than LowerThresholdupper threshold
+//    UCHAR   VgcUpperBound;           // max value of R17
+//} RT_802_11_RX_AGC_VGC_TUNING, *PRT_802_11_RX_AGC_VGC_TUNING;
+
+typedef struct _RT_802_11_AP_CONFIG {
+    ULONG   EnableTxBurst;      // 0-disable, 1-enable
+    ULONG   EnableTurboRate;    // 0-disable, 1-enable 72/100mbps turbo rate
+    ULONG   IsolateInterStaTraffic;     // 0-disable, 1-enable isolation
+    ULONG   HideSsid;           // 0-disable, 1-enable hiding
+    ULONG   UseBGProtection;    // 0-AUTO, 1-always ON, 2-always OFF
+    ULONG   UseShortSlotTime;   // 0-no use, 1-use 9-us short slot time
+    ULONG   Rsv1;               // must be 0
+    ULONG   SystemErrorBitmap;  // ignore upon SET, return system error upon QUERY
+} RT_802_11_AP_CONFIG, *PRT_802_11_AP_CONFIG;
+
+// structure to query/set STA_CONFIG
+typedef struct _RT_802_11_STA_CONFIG {
+    ULONG   EnableTxBurst;      // 0-disable, 1-enable
+    ULONG   EnableTurboRate;    // 0-disable, 1-enable 72/100mbps turbo rate
+    ULONG   UseBGProtection;    // 0-AUTO, 1-always ON, 2-always OFF
+    ULONG   UseShortSlotTime;   // 0-no use, 1-use 9-us short slot time when applicable
+    ULONG   AdhocMode;                         // 0-11b rates only (WIFI spec), 1 - b/g mixed, 2 - g only
+    ULONG   HwRadioStatus;      // 0-OFF, 1-ON, default is 1, Read-Only
+    ULONG   Rsv1;               // must be 0
+    ULONG   SystemErrorBitmap;  // ignore upon SET, return system error upon QUERY
+} RT_802_11_STA_CONFIG, *PRT_802_11_STA_CONFIG;
+
+//
+//  For OID Query or Set about BA structure
+//
+typedef        struct  _OID_BACAP_STRUC        {
+               UCHAR           RxBAWinLimit;
+               UCHAR           TxBAWinLimit;
+               UCHAR           Policy; // 0: DELAY_BA 1:IMMED_BA  (//BA Policy subfiled value in ADDBA frame)   2:BA-not use. other value invalid
+               UCHAR           MpduDensity;    // 0: DELAY_BA 1:IMMED_BA  (//BA Policy subfiled value in ADDBA frame)   2:BA-not use. other value invalid
+               UCHAR           AmsduEnable;    //Enable AMSDU transmisstion
+               UCHAR           AmsduSize;      // 0:3839, 1:7935 bytes. UINT  MSDUSizeToBytes[]        = { 3839, 7935};
+               UCHAR           MMPSmode;       // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable
+               BOOLEAN         AutoBA; // Auto BA will automatically
+} OID_BACAP_STRUC, *POID_BACAP_STRUC;
+
+typedef struct _RT_802_11_ACL_ENTRY {
+    UCHAR   Addr[MAC_ADDR_LENGTH];
+    USHORT  Rsv;
+} RT_802_11_ACL_ENTRY, *PRT_802_11_ACL_ENTRY;
+
+typedef struct PACKED _RT_802_11_ACL {
+    ULONG   Policy;             // 0-disable, 1-positive list, 2-negative list
+    ULONG   Num;
+    RT_802_11_ACL_ENTRY Entry[MAX_NUMBER_OF_ACL];
+} RT_802_11_ACL, *PRT_802_11_ACL;
+
+typedef struct _RT_802_11_WDS {
+    ULONG                                              Num;
+    NDIS_802_11_MAC_ADDRESS            Entry[24/*MAX_NUM_OF_WDS_LINK*/];
+       ULONG                                           KeyLength;
+       UCHAR                                           KeyMaterial[32];
+} RT_802_11_WDS, *PRT_802_11_WDS;
+
+typedef struct _RT_802_11_TX_RATES_ {
+    UCHAR       SupRateLen;
+    UCHAR       SupRate[MAX_LENGTH_OF_SUPPORT_RATES];
+    UCHAR       ExtRateLen;
+    UCHAR       ExtRate[MAX_LENGTH_OF_SUPPORT_RATES];
+} RT_802_11_TX_RATES, *PRT_802_11_TX_RATES;
+
+
+// Definition of extra information code
+#define        GENERAL_LINK_UP                 0x0                     // Link is Up
+#define        GENERAL_LINK_DOWN               0x1                     // Link is Down
+#define        HW_RADIO_OFF                    0x2                     // Hardware radio off
+#define        SW_RADIO_OFF                    0x3                     // Software radio off
+#define        AUTH_FAIL                               0x4                     // Open authentication fail
+#define        AUTH_FAIL_KEYS                  0x5                     // Shared authentication fail
+#define        ASSOC_FAIL                              0x6                     // Association failed
+#define        EAP_MIC_FAILURE                 0x7                     // Deauthencation because MIC failure
+#define        EAP_4WAY_TIMEOUT                0x8                     // Deauthencation on 4-way handshake timeout
+#define        EAP_GROUP_KEY_TIMEOUT   0x9                     // Deauthencation on group key handshake timeout
+#define        EAP_SUCCESS                             0xa                     // EAP succeed
+#define        DETECT_RADAR_SIGNAL             0xb         // Radar signal occur in current channel
+#define EXTRA_INFO_MAX                 0xb                     // Indicate Last OID
+
+#define EXTRA_INFO_CLEAR               0xffffffff
+
+// This is OID setting structure. So only GF or MM as Mode. This is valid when our wirelss mode has 802.11n in use.
+typedef struct {
+       RT_802_11_PHY_MODE              PhyMode;        //
+       UCHAR           TransmitNo;
+       UCHAR           HtMode;         //HTMODE_GF or HTMODE_MM
+       UCHAR           ExtOffset;      //extension channel above or below
+       UCHAR           MCS;
+       UCHAR           BW;
+       UCHAR           STBC;
+       UCHAR           SHORTGI;
+       UCHAR           rsv;
+} OID_SET_HT_PHYMODE, *POID_SET_HT_PHYMODE;
+
+#ifdef NINTENDO_AP
+#define NINTENDO_MAX_ENTRY 16
+#define NINTENDO_SSID_NAME_LN 8
+#define NINTENDO_SSID_NAME "NWCUSBAP"
+#define NINTENDO_PROBE_REQ_FLAG_MASK 0x03
+#define NINTENDO_PROBE_REQ_ON 0x01
+#define NINTENDO_PROBE_REQ_SIGNAL 0x02
+#define NINTENDO_PROBE_RSP_ON 0x01
+#define NINTENDO_SSID_NICKNAME_LN 20
+
+#define NINTENDO_WEPKEY_LN 13
+
+typedef struct _NINTENDO_SSID
+{
+       UCHAR   NINTENDOFixChar[NINTENDO_SSID_NAME_LN];
+       UCHAR   zero1;
+       UCHAR   registe;
+       UCHAR   ID;
+       UCHAR   zero2;
+       UCHAR   NICKname[NINTENDO_SSID_NICKNAME_LN];
+} RT_NINTENDO_SSID, *PRT_NINTENDO_SSID;
+
+typedef struct _NINTENDO_ENTRY
+{
+       UCHAR   NICKname[NINTENDO_SSID_NICKNAME_LN];
+    UCHAR   DS_Addr[ETH_LENGTH_OF_ADDRESS];
+       UCHAR   registe;
+       UCHAR   UserSpaceAck;
+} RT_NINTENDO_ENTRY, *PRT_NINTENDO_ENTRY;
+
+//RTPRIV_IOCTL_NINTENDO_GET_TABLE
+//RTPRIV_IOCTL_NINTENDO_SET_TABLE
+typedef struct _NINTENDO_TABLE
+{
+       UINT                            number;
+       RT_NINTENDO_ENTRY       entry[NINTENDO_MAX_ENTRY];
+} RT_NINTENDO_TABLE, *PRT_NINTENDO_TABLE;
+
+//RTPRIV_IOCTL_NINTENDO_SEED_WEPKEY
+typedef struct _NINTENDO_SEED_WEPKEY
+{
+       UCHAR   seed[NINTENDO_SSID_NICKNAME_LN];
+       UCHAR   wepkey[16];//use 13 for 104 bits wep key
+} RT_NINTENDO_SEED_WEPKEY, *PRT_NINTENDO_SEED_WEPKEY;
+#endif // NINTENDO_AP //
+
+#ifdef LLTD_SUPPORT
+typedef struct _RT_LLTD_ASSOICATION_ENTRY {
+    UCHAR           Addr[ETH_LENGTH_OF_ADDRESS];
+    unsigned short  MOR;        // maximum operational rate
+    UCHAR           phyMode;
+} RT_LLTD_ASSOICATION_ENTRY, *PRT_LLTD_ASSOICATION_ENTRY;
+
+typedef struct _RT_LLTD_ASSOICATION_TABLE {
+    unsigned int                Num;
+    RT_LLTD_ASSOICATION_ENTRY   Entry[MAX_NUMBER_OF_MAC];
+} RT_LLTD_ASSOICATION_TABLE, *PRT_LLTD_ASSOICATION_TABLE;
+#endif // LLTD_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+//rt2860, kathy 2007-0118
+// structure for DLS
+typedef struct _RT_802_11_DLS_UI {
+       USHORT                                          TimeOut;                // unit: second , set by UI
+       USHORT                                          CountDownTimer; // unit: second , used by driver only
+       NDIS_802_11_MAC_ADDRESS         MacAddr;                // set by UI
+       UCHAR                                           Status;                 // 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only
+       BOOLEAN                                         Valid;                  // 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link
+} RT_802_11_DLS_UI, *PRT_802_11_DLS_UI;
+
+typedef struct _RT_802_11_DLS_INFO {
+       RT_802_11_DLS_UI        Entry[MAX_NUMBER_OF_DLS_ENTRY];
+       UCHAR                           num;
+} RT_802_11_DLS_INFO, *PRT_802_11_DLS_INFO;
+
+typedef enum _RT_802_11_DLS_MODE {
+    DLS_NONE,
+    DLS_WAIT_KEY,
+    DLS_FINISH
+} RT_802_11_DLS_MODE;
+#endif // QOS_DLS_SUPPORT //
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+#define        RT_ASSOC_EVENT_FLAG                         0x0101
+#define        RT_DISASSOC_EVENT_FLAG                      0x0102
+#define        RT_REQIE_EVENT_FLAG                         0x0103
+#define        RT_RESPIE_EVENT_FLAG                        0x0104
+#define        RT_ASSOCINFO_EVENT_FLAG                     0x0105
+#define RT_PMKIDCAND_FLAG                           0x0106
+#define RT_INTERFACE_DOWN                           0x0107
+#define RT_INTERFACE_UP                             0x0108
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+
+#define MAX_CUSTOM_LEN 128
+
+#ifdef CONFIG_STA_SUPPORT
+typedef enum _RT_802_11_D_CLIENT_MODE
+{
+   Rt802_11_D_None,
+   Rt802_11_D_Flexible,
+   Rt802_11_D_Strict,
+} RT_802_11_D_CLIENT_MODE, *PRT_802_11_D_CLIENT_MODE;
+#endif // CONFIG_STA_SUPPORT //
+
+typedef struct _RT_CHANNEL_LIST_INFO
+{
+       UCHAR ChannelList[MAX_NUM_OF_CHS];   // list all supported channels for site survey
+       UCHAR ChannelListNum; // number of channel in ChannelList[]
+} RT_CHANNEL_LIST_INFO, *PRT_CHANNEL_LIST_INFO;
+
+// WSC configured credential
+typedef        struct  _WSC_CREDENTIAL
+{
+       NDIS_802_11_SSID        SSID;                           // mandatory
+       USHORT                          AuthType;                       // mandatory, 1: open, 2: wpa-psk, 4: shared, 8:wpa, 0x10: wpa2, 0x20: wpa2-psk
+       USHORT                          EncrType;                       // mandatory, 1: none, 2: wep, 4: tkip, 8: aes
+       UCHAR                           Key[64];                        // mandatory, Maximum 64 byte
+       USHORT                          KeyLength;
+       UCHAR                           MacAddr[6];                     // mandatory, AP MAC address
+       UCHAR                           KeyIndex;                       // optional, default is 1
+       UCHAR                           Rsvd[3];                        // Make alignment
+}      WSC_CREDENTIAL, *PWSC_CREDENTIAL;
+
+// WSC configured profiles
+typedef        struct  _WSC_PROFILE
+{
+       UINT                    ProfileCnt;
+       WSC_CREDENTIAL  Profile[8];                             // Support up to 8 profiles
+}      WSC_PROFILE, *PWSC_PROFILE;
+
+
+#endif // _OID_H_
+
diff --git a/drivers/staging/rt2870/rt2870.h b/drivers/staging/rt2870/rt2870.h
new file mode 100644 (file)
index 0000000..30af4b5
--- /dev/null
@@ -0,0 +1,761 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#ifndef __RT2870_H__
+#define __RT2870_H__
+
+//usb header files
+#include <linux/usb.h>
+
+/* rtmp_def.h */
+//
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define BULKAGGRE_ZISE          100
+#define RT28XX_DRVDATA_SET(_a)                                             usb_set_intfdata(_a, pAd);
+#define RT28XX_PUT_DEVICE                                                  usb_put_dev
+#define RTUSB_ALLOC_URB(iso)                                               usb_alloc_urb(iso, GFP_ATOMIC)
+#define RTUSB_SUBMIT_URB(pUrb)                                             usb_submit_urb(pUrb, GFP_ATOMIC)
+#define        RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr)               usb_buffer_alloc(pUsb_Dev, BufSize, GFP_ATOMIC, pDma_addr)
+#define        RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr)   usb_buffer_free(pUsb_Dev, BufSize, pTransferBuf, Dma_addr)
+#else
+#define BULKAGGRE_ZISE          60
+#define RT28XX_DRVDATA_SET(_a)
+#define RT28XX_PUT_DEVICE(dev_p)
+#define RTUSB_ALLOC_URB(iso)                                               usb_alloc_urb(iso)
+#define RTUSB_SUBMIT_URB(pUrb)                                             usb_submit_urb(pUrb)
+#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr)               kmalloc(BufSize, GFP_ATOMIC)
+#define        RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr)   kfree(pTransferBuf)
+#endif
+
+#define RXBULKAGGRE_ZISE        12
+#define MAX_TXBULK_LIMIT        (LOCAL_TXBUF_SIZE*(BULKAGGRE_ZISE-1))
+#define MAX_TXBULK_SIZE         (LOCAL_TXBUF_SIZE*BULKAGGRE_ZISE)
+#define MAX_RXBULK_SIZE         (LOCAL_TXBUF_SIZE*RXBULKAGGRE_ZISE)
+#define MAX_MLME_HANDLER_MEMORY 20
+#define        RETRY_LIMIT             10
+#define BUFFER_SIZE                            2400    //2048
+#define        TX_RING                                 0xa
+#define        PRIO_RING                               0xc
+
+
+// Flags for Bulkflags control for bulk out data
+//
+#define        fRTUSB_BULK_OUT_DATA_NULL                               0x00000001
+#define fRTUSB_BULK_OUT_RTS                                            0x00000002
+#define        fRTUSB_BULK_OUT_MLME                                    0x00000004
+
+#define        fRTUSB_BULK_OUT_DATA_NORMAL                             0x00010000
+#define        fRTUSB_BULK_OUT_DATA_NORMAL_2                   0x00020000
+#define        fRTUSB_BULK_OUT_DATA_NORMAL_3                   0x00040000
+#define        fRTUSB_BULK_OUT_DATA_NORMAL_4                   0x00080000
+
+#define        fRTUSB_BULK_OUT_PSPOLL                                  0x00000020
+#define        fRTUSB_BULK_OUT_DATA_FRAG                               0x00000040
+#define        fRTUSB_BULK_OUT_DATA_FRAG_2                             0x00000080
+#define        fRTUSB_BULK_OUT_DATA_FRAG_3                             0x00000100
+#define        fRTUSB_BULK_OUT_DATA_FRAG_4                             0x00000200
+
+#ifdef RALINK_ATE
+#define        fRTUSB_BULK_OUT_DATA_ATE                                0x00100000
+#endif // RALINK_ATE //
+
+#define RT2870_USB_DEVICES     \
+{      \
+       {USB_DEVICE(0x148F,0x2770)}, /* Ralink */               \
+       {USB_DEVICE(0x148F,0x2870)}, /* Ralink */               \
+       {USB_DEVICE(0x148F,0x3070)}, /* Ralink */               \
+       {USB_DEVICE(0x0B05,0x1731)}, /* Asus */                 \
+       {USB_DEVICE(0x0B05,0x1732)}, /* Asus */                 \
+       {USB_DEVICE(0x0B05,0x1742)}, /* Asus */                 \
+       {USB_DEVICE(0x0DF6,0x0017)}, /* Sitecom */              \
+       {USB_DEVICE(0x0DF6,0x002B)}, /* Sitecom */              \
+       {USB_DEVICE(0x0DF6,0x002C)}, /* Sitecom */              \
+       {USB_DEVICE(0x0DF6,0x002D)}, /* Sitecom */              \
+       {USB_DEVICE(0x14B2,0x3C06)}, /* Conceptronic */         \
+       {USB_DEVICE(0x14B2,0x3C28)}, /* Conceptronic */         \
+       {USB_DEVICE(0x2019,0xED06)}, /* Planex Communications, Inc. */          \
+       {USB_DEVICE(0x2019,0xAB25)}, /* Planex Communications, Inc. RT3070 */           \
+       {USB_DEVICE(0x07D1,0x3C09)}, /* D-Link */               \
+       {USB_DEVICE(0x07D1,0x3C11)}, /* D-Link */               \
+       {USB_DEVICE(0x14B2,0x3C07)}, /* AL */                   \
+       {USB_DEVICE(0x14B2,0x3C12)}, /* AL */           \
+       {USB_DEVICE(0x050D,0x8053)}, /* Belkin */               \
+       {USB_DEVICE(0x14B2,0x3C23)}, /* Airlink */              \
+       {USB_DEVICE(0x14B2,0x3C27)}, /* Airlink */              \
+       {USB_DEVICE(0x07AA,0x002F)}, /* Corega */               \
+       {USB_DEVICE(0x07AA,0x003C)}, /* Corega */               \
+       {USB_DEVICE(0x07AA,0x003F)}, /* Corega */               \
+       {USB_DEVICE(0x18C5,0x0012)}, /* Corega */               \
+       {USB_DEVICE(0x1044,0x800B)}, /* Gigabyte */             \
+       {USB_DEVICE(0x15A9,0x0006)}, /* Sparklan */             \
+       {USB_DEVICE(0x083A,0xB522)}, /* SMC */                  \
+       {USB_DEVICE(0x083A,0xA618)}, /* SMC */                  \
+       {USB_DEVICE(0x083A,0x7522)}, /* Arcadyan */             \
+       {USB_DEVICE(0x0CDE,0x0022)}, /* ZCOM */                 \
+       {USB_DEVICE(0x0586,0x3416)}, /* Zyxel */                \
+       {USB_DEVICE(0x0CDE,0x0025)}, /* Zyxel */                \
+       {USB_DEVICE(0x1740,0x9701)}, /* EnGenius */             \
+       {USB_DEVICE(0x1740,0x9702)}, /* EnGenius */             \
+       {USB_DEVICE(0x0471,0x200f)}, /* Philips */              \
+       {USB_DEVICE(0x14B2,0x3C25)}, /* Draytek */              \
+       {USB_DEVICE(0x13D3,0x3247)}, /* AzureWave */    \
+       {USB_DEVICE(0x083A,0x6618)}, /* Accton */               \
+       {USB_DEVICE(0x15c5,0x0008)}, /* Amit */                 \
+       {USB_DEVICE(0x0E66,0x0001)}, /* Hawking */              \
+       {USB_DEVICE(0x0E66,0x0003)}, /* Hawking */              \
+       {USB_DEVICE(0x129B,0x1828)}, /* Siemens */              \
+       {USB_DEVICE(0x157E,0x300E)},    /* U-Media */   \
+       {USB_DEVICE(0x050d,0x805c)},                                    \
+       {USB_DEVICE(0x1482,0x3C09)}, /* Abocom*/                \
+       {USB_DEVICE(0x14B2,0x3C09)}, /* Alpha */                \
+       {USB_DEVICE(0x04E8,0x2018)}, /* samsung */      \
+       {USB_DEVICE(0x07B8,0x3070)}, /* AboCom */               \
+       {USB_DEVICE(0x07B8,0x3071)}, /* AboCom */               \
+       {USB_DEVICE(0x07B8,0x2870)}, /* AboCom */               \
+       {USB_DEVICE(0x07B8,0x2770)}, /* AboCom */               \
+       {USB_DEVICE(0x7392,0x7711)}, /* Edimax */               \
+       {USB_DEVICE(0x5A57,0x0280)}, /* Zinwell */              \
+       {USB_DEVICE(0x5A57,0x0282)}, /* Zinwell */              \
+       {USB_DEVICE(0x0789,0x0162)}, /* Logitec */              \
+       {USB_DEVICE(0x0789,0x0163)}, /* Logitec */              \
+       {USB_DEVICE(0x0789,0x0164)}, /* Logitec */              \
+       { }/* Terminating entry */                      \
+}
+
+#define        FREE_HTTX_RING(_p, _b, _t)                      \
+{                                                                              \
+       if ((_t)->ENextBulkOutPosition == (_t)->CurWritePosition)                               \
+       {                                                                                                                                       \
+               (_t)->bRingEmpty = TRUE;                        \
+       }                                                                                                                                       \
+       /*NdisInterlockedDecrement(&(_p)->TxCount); */\
+}
+
+//
+// RXINFO appends at the end of each rx packet.
+//
+#ifdef RT_BIG_ENDIAN
+typedef        struct  PACKED _RXINFO_STRUC {
+       UINT32          PlcpSignal:12;
+       UINT32          LastAMSDU:1;
+       UINT32          CipherAlg:1;
+       UINT32          PlcpRssil:1;
+       UINT32          Decrypted:1;
+       UINT32          AMPDU:1;                // To be moved
+       UINT32          L2PAD:1;
+       UINT32          RSSI:1;
+       UINT32          HTC:1;
+       UINT32          AMSDU:1;                // rx with 802.3 header, not 802.11 header.
+       UINT32          CipherErr:2;        // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid
+       UINT32          Crc:1;              // 1: CRC error
+       UINT32          MyBss:1;        // 1: this frame belongs to the same BSSID
+       UINT32          Bcast:1;            // 1: this is a broadcast frame
+       UINT32          Mcast:1;            // 1: this is a multicast frame
+       UINT32          U2M:1;              // 1: this RX frame is unicast to me
+       UINT32          FRAG:1;
+       UINT32          NULLDATA:1;
+       UINT32          DATA:1;
+       UINT32          BA:1;
+}      RXINFO_STRUC, *PRXINFO_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC;
+#else
+typedef        struct  PACKED _RXINFO_STRUC {
+       UINT32          BA:1;
+       UINT32          DATA:1;
+       UINT32          NULLDATA:1;
+       UINT32          FRAG:1;
+       UINT32          U2M:1;              // 1: this RX frame is unicast to me
+       UINT32          Mcast:1;            // 1: this is a multicast frame
+       UINT32          Bcast:1;            // 1: this is a broadcast frame
+       UINT32          MyBss:1;        // 1: this frame belongs to the same BSSID
+       UINT32          Crc:1;              // 1: CRC error
+       UINT32          CipherErr:2;        // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid
+       UINT32          AMSDU:1;                // rx with 802.3 header, not 802.11 header.
+       UINT32          HTC:1;
+       UINT32          RSSI:1;
+       UINT32          L2PAD:1;
+       UINT32          AMPDU:1;                // To be moved
+       UINT32          Decrypted:1;
+       UINT32          PlcpRssil:1;
+       UINT32          CipherAlg:1;
+       UINT32          LastAMSDU:1;
+       UINT32          PlcpSignal:12;
+}      RXINFO_STRUC, *PRXINFO_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC;
+#endif
+
+
+//
+// TXINFO
+//
+#ifdef RT_BIG_ENDIAN
+typedef        struct  _TXINFO_STRUC {
+       // Word 0
+       UINT32          USBDMATxburst:1;//used ONLY in USB bulk Aggre. Force USB DMA transmit frame from current selected endpoint
+       UINT32          USBDMANextVLD:1;        //used ONLY in USB bulk Aggregation, NextValid
+       UINT32          rsv2:2;  // Software use.
+       UINT32          SwUseLastRound:1; // Software use.
+       UINT32          QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA
+       UINT32          WIV:1;  // Wireless Info Valid. 1 if Driver already fill WI,  o if DMA needs to copy WI to correctposition
+       UINT32          rsv:8;
+       UINT32          USBDMATxPktLen:16;      //used ONLY in USB bulk Aggregation,  Total byte counts of all sub-frame.
+}      TXINFO_STRUC, *PTXINFO_STRUC;
+#else
+typedef        struct  _TXINFO_STRUC {
+       // Word 0
+       UINT32          USBDMATxPktLen:16;      //used ONLY in USB bulk Aggregation,  Total byte counts of all sub-frame.
+       UINT32          rsv:8;
+       UINT32          WIV:1;  // Wireless Info Valid. 1 if Driver already fill WI,  o if DMA needs to copy WI to correctposition
+       UINT32          QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA
+       UINT32          SwUseLastRound:1; // Software use.
+       UINT32          rsv2:2;  // Software use.
+       UINT32          USBDMANextVLD:1;        //used ONLY in USB bulk Aggregation, NextValid
+       UINT32          USBDMATxburst:1;//used ONLY in USB bulk Aggre. Force USB DMA transmit frame from current selected endpoint
+}      TXINFO_STRUC, *PTXINFO_STRUC;
+#endif
+
+#define TXINFO_SIZE                            4
+#define RXINFO_SIZE                            4
+#define TXPADDING_SIZE                 11
+
+//
+// Management ring buffer format
+//
+typedef        struct  _MGMT_STRUC     {
+       BOOLEAN         Valid;
+       PUCHAR          pBuffer;
+       ULONG           Length;
+}      MGMT_STRUC, *PMGMT_STRUC;
+
+
+/* ----------------- EEPROM Related MACRO ----------------- */
+#define RT28xx_EEPROM_READ16(pAd, offset, var)                                 \
+       do {                                                                                                            \
+               RTUSBReadEEPROM(pAd, offset, (PUCHAR)&(var), 2);                \
+               var = le2cpu16(var);                                                                    \
+       }while(0)
+
+#define RT28xx_EEPROM_WRITE16(pAd, offset, var)                                        \
+       do{                                                                                                                     \
+               USHORT _tmpVar;                                                                                 \
+               _tmpVar = cpu2le16(var);                                                                \
+               RTUSBWriteEEPROM(pAd, offset, (PUCHAR)&(_tmpVar), 2);   \
+       }while(0)
+
+/* ----------------- TASK/THREAD Related MACRO ----------------- */
+#define RT28XX_TASK_THREAD_INIT(pAd, Status)           \
+       Status = CreateThreads(net_dev);
+
+
+/* ----------------- Frimware Related MACRO ----------------- */
+#if 0
+#define RT28XX_FIRMUD_INIT(pAd)                \
+       {       UINT32  MacReg;                         \
+               RTUSBReadMACRegister(pAd, MAC_CSR0, &MacReg); }
+
+#define RT28XX_FIRMUD_END(pAd) \
+       RTUSBWriteMACRegister(pAd, 0x7014, 0xffffffff); \
+       RTUSBWriteMACRegister(pAd, 0x701c, 0xffffffff); \
+       RTUSBFirmwareRun(pAd);
+#else
+#define RT28XX_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen)         \
+       RTUSBFirmwareWrite(_pAd, _pFwImage, _FwLen)
+#endif
+
+/* ----------------- TX Related MACRO ----------------- */
+#define RT28XX_START_DEQUEUE(pAd, QueIdx, irqFlags)                            \
+                       {                                                                                                       \
+                               RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags);             \
+                               if (pAd->DeQueueRunning[QueIdx])                                                \
+                               {                                                                                                               \
+                                       RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\
+                                       printk("DeQueueRunning[%d]= TRUE!\n", QueIdx);          \
+                                       continue;                                                                                       \
+                               }                                                                                                               \
+                               else                                                                                                    \
+                               {                                                                                                               \
+                                       pAd->DeQueueRunning[QueIdx] = TRUE;                                     \
+                                       RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\
+                               }                                                                                                               \
+                       }
+#define RT28XX_STOP_DEQUEUE(pAd, QueIdx, irqFlags)                                             \
+                       do{                                                                                                                     \
+                               RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags);             \
+                               pAd->DeQueueRunning[QueIdx] = FALSE;                                    \
+                               RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);   \
+                       }while(0)
+
+
+#define        RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \
+               (RTUSBFreeDescriptorRequest(pAd, pTxBlk->QueIdx, (pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))) == NDIS_STATUS_SUCCESS)
+
+#define RT28XX_RELEASE_DESC_RESOURCE(pAd, QueIdx)                      \
+               do{}while(0)
+
+#define NEED_QUEUE_BACK_FOR_AGG(_pAd, _QueIdx, _freeNum, _TxFrameType)                 \
+               ((_TxFrameType == TX_RALINK_FRAME) && (RTUSBNeedQueueBackForAgg(_pAd, _QueIdx)))
+
+
+
+#define fRTMP_ADAPTER_NEED_STOP_TX             \
+               (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \
+                fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_BULKOUT_RESET | \
+                fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_REMOVE_IN_PROGRESS)
+
+
+#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber)      \
+                       RtmpUSB_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber)
+
+#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber)  \
+                       RtmpUSB_WriteSingleTxResource(pAd, pTxBlk,bIsLast, pFreeNumber)
+
+#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \
+                       RtmpUSB_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber)
+
+#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber)    \
+                       RtmpUSB_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber)
+
+#define HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx)    \
+                       RtmpUSB_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx)
+
+#define HAL_LastTxIdx(pAd, QueIdx,TxIdx) \
+                       /*RtmpUSBDataLastTxIdx(pAd, QueIdx,TxIdx)*/
+
+#define HAL_KickOutTx(pAd, pTxBlk, QueIdx)     \
+                       RtmpUSBDataKickOut(pAd, pTxBlk, QueIdx)
+
+
+#define HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen)  \
+                       RtmpUSBMgmtKickOut(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen)
+
+#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen)  \
+                       RtmpUSBNullFrameKickOut(_pAd, _QueIdx, _pNullFrame, _frameLen)
+
+#define RTMP_PKT_TAIL_PADDING  11 // 3(max 4 byte padding) + 4 (last packet padding) + 4 (MaxBulkOutsize align padding)
+
+extern UCHAR EpToQueue[6];
+
+
+#ifdef RT2870
+#define GET_TXRING_FREENO(_pAd, _QueIdx)       (_QueIdx) //(_pAd->TxRing[_QueIdx].TxSwFreeIdx)
+#define GET_MGMTRING_FREENO(_pAd)                      (_pAd->MgmtRing.TxSwFreeIdx)
+#endif // RT2870 //
+
+
+/* ----------------- RX Related MACRO ----------------- */
+//#define RT28XX_RX_ERROR_CHECK                                RTMPCheckRxWI
+
+#if 0
+#define RT28XX_RCV_INIT(pAd)                                   \
+       pAd->TransferBufferLength = 0;                          \
+       pAd->ReadPosition = 0;                                          \
+       pAd->pCurrRxContext = NULL;
+#endif
+
+#define RT28XX_RV_ALL_BUF_END(bBulkReceive)            \
+       /* We return STATUS_MORE_PROCESSING_REQUIRED so that the completion */  \
+       /* routine (IofCompleteRequest) will stop working on the irp. */                \
+       if (bBulkReceive == TRUE)       RTUSBBulkReceive(pAd);
+
+
+/* ----------------- ASIC Related MACRO ----------------- */
+#if 0
+#define RT28XX_DMA_WRITE_INIT(GloCfg)                  \
+       {       GloCfg.field.EnTXWriteBackDDONE = 1;    \
+               GloCfg.field.EnableRxDMA = 1;                   \
+               GloCfg.field.EnableTxDMA = 1; }
+
+#define RT28XX_DMA_POST_WRITE(_pAd)                            \
+       do{     USB_DMA_CFG_STRUC       UsbCfg;                         \
+               UsbCfg.word = 0;                                                \
+               /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */ \
+               UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE /1024)-3;  \
+               UsbCfg.field.phyclear = 0;                                                              \
+               /* usb version is 1.1,do not use bulk in aggregation */ \
+               if (_pAd->BulkInMaxPacketSize == 512)                                   \
+                       UsbCfg.field.RxBulkAggEn = 1;                                           \
+               UsbCfg.field.RxBulkEn = 1;                                                              \
+               UsbCfg.field.TxBulkEn = 1;                                                              \
+               UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */             \
+               RTUSBWriteMACRegister(_pAd, USB_DMA_CFG, UsbCfg.word);  \
+       }while(0)
+#endif
+
+// reset MAC of a station entry to 0xFFFFFFFFFFFF
+#define RT28XX_STA_ENTRY_MAC_RESET(pAd, Wcid)                                  \
+       {       RT_SET_ASIC_WCID        SetAsicWcid;                                            \
+               SetAsicWcid.WCID = Wcid;                                                                \
+               SetAsicWcid.SetTid = 0xffffffff;                                                \
+               SetAsicWcid.DeleteTid = 0xffffffff;                                             \
+               RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_ASIC_WCID,   \
+                               &SetAsicWcid, sizeof(RT_SET_ASIC_WCID));        }
+
+// add this entry into ASIC RX WCID search table
+#define RT28XX_STA_ENTRY_ADD(pAd, pEntry)                                                      \
+       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_CLIENT_MAC_ENTRY,    \
+                                                       pEntry, sizeof(MAC_TABLE_ENTRY));
+
+// remove Pair-wise key material from ASIC
+// yet implement
+#define RT28XX_STA_ENTRY_KEY_DEL(pAd, BssIdx, Wcid)
+
+// add Client security information into ASIC WCID table and IVEIV table
+#define RT28XX_STA_SECURITY_INFO_ADD(pAd, apidx, KeyID, pEntry)                                                \
+       {       RT28XX_STA_ENTRY_MAC_RESET(pAd, pEntry->Aid);                                                           \
+               if (pEntry->Aid >= 1) {                                                                                                         \
+                       RT_SET_ASIC_WCID_ATTRI  SetAsicWcidAttri;                                                               \
+                       SetAsicWcidAttri.WCID = pEntry->Aid;                                                                    \
+                       if ((pEntry->AuthMode <= Ndis802_11AuthModeAutoSwitch) &&                               \
+                               (pEntry->WepStatus == Ndis802_11Encryption1Enabled))                            \
+                       {                                                                                                                                               \
+                               SetAsicWcidAttri.Cipher = pAd->SharedKey[apidx][KeyID].CipherAlg;       \
+                       }                                                                                                                                               \
+                       else if (pEntry->AuthMode == Ndis802_11AuthModeWPANone)                                 \
+                       {                                                                                                                                               \
+                               SetAsicWcidAttri.Cipher = pAd->SharedKey[apidx][KeyID].CipherAlg;       \
+                       }                                                                                                                                               \
+                       else SetAsicWcidAttri.Cipher = 0;                                                                               \
+            DBGPRINT(RT_DEBUG_TRACE, ("aid cipher = %ld\n",SetAsicWcidAttri.Cipher));       \
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_ASIC_WCID_CIPHER,                    \
+                                                       &SetAsicWcidAttri, sizeof(RT_SET_ASIC_WCID_ATTRI)); } }
+
+// Insert the BA bitmap to ASIC for the Wcid entry
+#define RT28XX_ADD_BA_SESSION_TO_ASIC(_pAd, _Aid, _TID)                                        \
+               do{                                                                                                                             \
+                       RT_SET_ASIC_WCID        SetAsicWcid;                                                    \
+                       SetAsicWcid.WCID = (_Aid);                                                                      \
+                       SetAsicWcid.SetTid = (0x10000<<(_TID));                                         \
+                       SetAsicWcid.DeleteTid = 0xffffffff;                                                     \
+                       RTUSBEnqueueInternalCmd((_pAd), CMDTHREAD_SET_ASIC_WCID, &SetAsicWcid, sizeof(RT_SET_ASIC_WCID));       \
+               }while(0)
+
+// Remove the BA bitmap from ASIC for the Wcid entry
+#define RT28XX_DEL_BA_SESSION_FROM_ASIC(_pAd, _Wcid, _TID)                             \
+               do{                                                                                                                             \
+                       RT_SET_ASIC_WCID        SetAsicWcid;                                                    \
+                       SetAsicWcid.WCID = (_Wcid);                                                                     \
+                       SetAsicWcid.SetTid = (0xffffffff);                                                      \
+                       SetAsicWcid.DeleteTid = (0x10000<<(_TID) );                                     \
+                       RTUSBEnqueueInternalCmd((_pAd), CMDTHREAD_SET_ASIC_WCID, &SetAsicWcid, sizeof(RT_SET_ASIC_WCID));       \
+               }while(0)
+
+
+/* ----------------- PCI/USB Related MACRO ----------------- */
+#define RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p)                        \
+       ((POS_COOKIE)handle)->pUsb_Dev = dev_p;
+
+// no use
+#define RT28XX_UNMAP()
+#define RT28XX_IRQ_REQUEST(net_dev)
+#define RT28XX_IRQ_RELEASE(net_dev)
+#define RT28XX_IRQ_INIT(pAd)
+#define RT28XX_IRQ_ENABLE(pAd)
+
+
+/* ----------------- MLME Related MACRO ----------------- */
+#define RT28XX_MLME_HANDLER(pAd)                       RTUSBMlmeUp(pAd)
+
+#define RT28XX_MLME_PRE_SANITY_CHECK(pAd)                                                              \
+       {       if ((pAd->CommonCfg.bHardwareRadio == TRUE) &&                                  \
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&          \
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) {       \
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_CHECK_GPIO, NULL, 0); } }
+
+#define RT28XX_MLME_STA_QUICK_RSP_WAKE_UP(pAd) \
+       {       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_QKERIODIC_EXECUT, NULL, 0);      \
+               RTUSBMlmeUp(pAd); }
+
+#define RT28XX_MLME_RESET_STATE_MACHINE(pAd)   \
+                       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_RESET_CONF, 0, NULL);     \
+                       RTUSBMlmeUp(pAd);
+
+#define RT28XX_HANDLE_COUNTER_MEASURE(_pAd, _pEntry)           \
+       {       RTUSBEnqueueInternalCmd(_pAd, CMDTHREAD_802_11_COUNTER_MEASURE, _pEntry, sizeof(MAC_TABLE_ENTRY));      \
+               RTUSBMlmeUp(_pAd);                                                                      \
+       }
+
+
+/* ----------------- Power Save Related MACRO ----------------- */
+#define RT28XX_PS_POLL_ENQUEUE(pAd)                                            \
+       {       RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL);       \
+               RTUSBKickBulkOut(pAd); }
+
+#define RT28xx_CHIP_NAME            "RT2870"
+#define USB_CYC_CFG                 0x02a4
+#define STATUS_SUCCESS                         0x00
+#define STATUS_UNSUCCESSFUL            0x01
+#define NT_SUCCESS(status)                     (((status) > 0) ? (1):(0))
+#define InterlockedIncrement           atomic_inc
+#define NdisInterlockedIncrement       atomic_inc
+#define InterlockedDecrement           atomic_dec
+#define NdisInterlockedDecrement       atomic_dec
+#define InterlockedExchange                    atomic_set
+//#define NdisMSendComplete                    RTMP_SendComplete
+#define NdisMCancelTimer                       RTMPCancelTimer
+#define NdisAllocMemory(_ptr, _size, _flag)    \
+                                                                       do{_ptr = kmalloc((_size),(_flag));}while(0)
+#define NdisFreeMemory(a, b, c)        kfree((a))
+#define NdisMSleep                                     RTMPusecDelay           /* unit: microsecond */
+
+
+#define USBD_TRANSFER_DIRECTION_OUT            0
+#define USBD_TRANSFER_DIRECTION_IN             0
+#define USBD_SHORT_TRANSFER_OK                 0
+#define PURB                   purbb_t
+
+#define RTUSB_FREE_URB(pUrb)   usb_free_urb(pUrb)
+
+//#undef MlmeAllocateMemory
+//#undef MlmeFreeMemory
+
+typedef int                            NTSTATUS;
+typedef struct usb_device      * PUSB_DEV;
+
+/* MACRO for linux usb */
+typedef struct urb *purbb_t;
+typedef struct usb_ctrlrequest devctrlrequest;
+#define PIRP           PVOID
+#define PMDL           PVOID
+#define NDIS_OID       UINT
+#ifndef USB_ST_NOERROR
+#define USB_ST_NOERROR     0
+#endif
+
+// vendor-specific control operations
+#define CONTROL_TIMEOUT_JIFFIES ( (100 * HZ) / 1000)
+#define UNLINK_TIMEOUT_MS              3
+
+/* unlink urb  */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7)
+#define RTUSB_UNLINK_URB(pUrb)         usb_kill_urb(pUrb)
+#else
+#define RTUSB_UNLINK_URB(pUrb)         usb_unlink_urb(pUrb)
+#endif
+
+// Prototypes of completion funuc.
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#define RTUSBBulkOutDataPacketComplete(purb, pt_regs)    RTUSBBulkOutDataPacketComplete(purb)
+#define RTUSBBulkOutMLMEPacketComplete(pUrb, pt_regs)    RTUSBBulkOutMLMEPacketComplete(pUrb)
+#define RTUSBBulkOutNullFrameComplete(pUrb, pt_regs)     RTUSBBulkOutNullFrameComplete(pUrb)
+#define RTUSBBulkOutRTSFrameComplete(pUrb, pt_regs)      RTUSBBulkOutRTSFrameComplete(pUrb)
+#define RTUSBBulkOutPsPollComplete(pUrb, pt_regs)        RTUSBBulkOutPsPollComplete(pUrb)
+#define RTUSBBulkRxComplete(pUrb, pt_regs)               RTUSBBulkRxComplete(pUrb)
+#endif
+
+
+VOID RTUSBBulkOutDataPacketComplete(purbb_t purb, struct pt_regs *pt_regs);
+VOID RTUSBBulkOutMLMEPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs);
+VOID RTUSBBulkOutNullFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs);
+VOID RTUSBBulkOutRTSFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs);
+VOID RTUSBBulkOutPsPollComplete(purbb_t pUrb, struct pt_regs *pt_regs);
+VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs);
+
+
+#define RTUSBMlmeUp(pAd)               \
+{                                                                  \
+       POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;  \
+       CHECK_PID_LEGALITY(pObj->MLMEThr_pid)               \
+        up(&(pAd->mlme_semaphore)); \
+}
+
+#define RTUSBCMDUp(pAd)                        \
+{                                                                          \
+       POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;  \
+       CHECK_PID_LEGALITY(pObj->RTUSBCmdThr_pid)           \
+           up(&(pAd->RTUSBCmd_semaphore)); \
+}
+
+
+static inline NDIS_STATUS RTMPAllocateMemory(
+       OUT PVOID *ptr,
+       IN size_t size)
+{
+       *ptr = kmalloc(size, GFP_ATOMIC);
+       if(*ptr)
+               return NDIS_STATUS_SUCCESS;
+       else
+               return NDIS_STATUS_RESOURCES;
+}
+
+/* rtmp.h */
+#define        BEACON_RING_SIZE                2
+#define DEVICE_VENDOR_REQUEST_OUT       0x40
+#define DEVICE_VENDOR_REQUEST_IN        0xc0
+#define INTERFACE_VENDOR_REQUEST_OUT    0x41
+#define INTERFACE_VENDOR_REQUEST_IN     0xc1
+#define MGMTPIPEIDX                                            0       // EP6 is highest priority
+
+#define BULKOUT_MGMT_RESET_FLAG                                0x80
+
+#define RTUSB_SET_BULK_FLAG(_M, _F)                            ((_M)->BulkFlags |= (_F))
+#define RTUSB_CLEAR_BULK_FLAG(_M, _F)                  ((_M)->BulkFlags &= ~(_F))
+#define RTUSB_TEST_BULK_FLAG(_M, _F)                   (((_M)->BulkFlags & (_F)) != 0)
+
+#define EnqueueCmd(cmdq, cmdqelmt)             \
+{                                                                              \
+       if (cmdq->size == 0)                            \
+               cmdq->head = cmdqelmt;                  \
+       else                                                            \
+               cmdq->tail->next = cmdqelmt;    \
+       cmdq->tail = cmdqelmt;                          \
+       cmdqelmt->next = NULL;                          \
+       cmdq->size++;                                           \
+}
+
+typedef struct   _RT_SET_ASIC_WCID {
+       ULONG WCID;          // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based
+       ULONG SetTid;        // time-based: seconds, packet-based: kilo-packets
+       ULONG DeleteTid;        // time-based: seconds, packet-based: kilo-packets
+       UCHAR Addr[MAC_ADDR_LEN];       // avoid in interrupt when write key
+} RT_SET_ASIC_WCID,*PRT_SET_ASIC_WCID;
+
+typedef struct   _RT_SET_ASIC_WCID_ATTRI {
+       ULONG   WCID;          // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based
+       ULONG   Cipher;        // ASIC Cipher definition
+       UCHAR   Addr[ETH_LENGTH_OF_ADDRESS];
+} RT_SET_ASIC_WCID_ATTRI,*PRT_SET_ASIC_WCID_ATTRI;
+
+typedef struct _MLME_MEMORY_STRUCT {
+       PVOID                           AllocVa;    //Pointer to the base virtual address of the allocated memory
+       struct _MLME_MEMORY_STRUCT      *Next;      //Pointer to the next virtual address of the allocated memory
+}   MLME_MEMORY_STRUCT, *PMLME_MEMORY_STRUCT;
+
+typedef struct  _MLME_MEMORY_HANDLER {
+       BOOLEAN                 MemRunning;         //The flag of the Mlme memory handler's status
+       UINT                    MemoryCount;        //Total nonpaged system-space memory not size
+       UINT                    InUseCount;         //Nonpaged system-space memory in used counts
+       UINT                    UnUseCount;         //Nonpaged system-space memory available counts
+       INT                    PendingCount;       //Nonpaged system-space memory for free counts
+       PMLME_MEMORY_STRUCT     pInUseHead;         //Pointer to the first nonpaed memory not used
+       PMLME_MEMORY_STRUCT     pInUseTail;         //Pointer to the last nonpaged memory not used
+       PMLME_MEMORY_STRUCT     pUnUseHead;         //Pointer to the first nonpaged memory in used
+       PMLME_MEMORY_STRUCT     pUnUseTail;         //Pointer to the last nonpaged memory in used
+       PULONG                  MemFreePending[MAX_MLME_HANDLER_MEMORY];   //an array to keep pending free-memory's pointer (32bits)
+}   MLME_MEMORY_HANDLER, *PMLME_MEMORY_HANDLER;
+
+typedef        struct _CmdQElmt        {
+       UINT                            command;
+       PVOID                           buffer;
+       ULONG                           bufferlength;
+       BOOLEAN                         CmdFromNdis;
+       BOOLEAN                         SetOperation;
+       struct _CmdQElmt        *next;
+}      CmdQElmt, *PCmdQElmt;
+
+typedef        struct  _CmdQ   {
+       UINT            size;
+       CmdQElmt        *head;
+       CmdQElmt        *tail;
+       UINT32          CmdQState;
+}CmdQ, *PCmdQ;
+
+//
+// For WPA SUPPLICANT: WIRELESS EXT support wireless events: v14 or newer
+//
+#if WIRELESS_EXT >= 14
+//#define WPA_SUPPLICANT_SUPPORT  1
+#endif
+
+/* oid.h */
+// Cipher suite type for mixed mode group cipher, P802.11i-2004
+typedef enum _RT_802_11_CIPHER_SUITE_TYPE {
+       Cipher_Type_NONE,
+       Cipher_Type_WEP40,
+       Cipher_Type_TKIP,
+       Cipher_Type_RSVD,
+       Cipher_Type_CCMP,
+       Cipher_Type_WEP104
+} RT_802_11_CIPHER_SUITE_TYPE, *PRT_802_11_CIPHER_SUITE_TYPE;
+
+//CMDTHREAD_MULTI_READ_MAC
+//CMDTHREAD_MULTI_WRITE_MAC
+//CMDTHREAD_VENDOR_EEPROM_READ
+//CMDTHREAD_VENDOR_EEPROM_WRITE
+typedef        struct  _CMDHandler_TLV {
+       USHORT          Offset;
+       USHORT          Length;
+       UCHAR           DataFirst;
+}      CMDHandler_TLV, *PCMDHandler_TLV;
+
+// New for MeetingHouse Api support
+#define CMDTHREAD_VENDOR_RESET                      0x0D730101 // cmd
+#define CMDTHREAD_VENDOR_UNPLUG                     0x0D730102 // cmd
+#define CMDTHREAD_VENDOR_SWITCH_FUNCTION            0x0D730103 // cmd
+#define CMDTHREAD_MULTI_WRITE_MAC                   0x0D730107 // cmd
+#define CMDTHREAD_MULTI_READ_MAC                    0x0D730108 // cmd
+#define CMDTHREAD_VENDOR_EEPROM_WRITE               0x0D73010A // cmd
+#define CMDTHREAD_VENDOR_EEPROM_READ                0x0D73010B // cmd
+#define CMDTHREAD_VENDOR_ENTER_TESTMODE             0x0D73010C // cmd
+#define CMDTHREAD_VENDOR_EXIT_TESTMODE              0x0D73010D // cmd
+#define CMDTHREAD_VENDOR_WRITE_BBP                  0x0D730119 // cmd
+#define CMDTHREAD_VENDOR_READ_BBP                   0x0D730118 // cmd
+#define CMDTHREAD_VENDOR_WRITE_RF                   0x0D73011A // cmd
+#define CMDTHREAD_VENDOR_FLIP_IQ                    0x0D73011D // cmd
+#define CMDTHREAD_RESET_BULK_OUT                    0x0D730210 // cmd
+#define CMDTHREAD_RESET_BULK_IN                     0x0D730211 // cmd
+#define CMDTHREAD_SET_PSM_BIT_SAVE                  0x0D730212 // cmd
+#define CMDTHREAD_SET_RADIO                         0x0D730214 // cmd
+#define CMDTHREAD_UPDATE_TX_RATE                    0x0D730216 // cmd
+#define CMDTHREAD_802_11_ADD_KEY_WEP                0x0D730218 // cmd
+#define CMDTHREAD_RESET_FROM_ERROR                  0x0D73021A // cmd
+#define CMDTHREAD_LINK_DOWN                         0x0D73021B // cmd
+#define CMDTHREAD_RESET_FROM_NDIS                   0x0D73021C // cmd
+#define CMDTHREAD_CHECK_GPIO                        0x0D730215 // cmd
+#define CMDTHREAD_FORCE_WAKE_UP                     0x0D730222 // cmd
+#define CMDTHREAD_SET_BW                            0x0D730225 // cmd
+#define CMDTHREAD_SET_ASIC_WCID                     0x0D730226 // cmd
+#define CMDTHREAD_SET_ASIC_WCID_CIPHER              0x0D730227 // cmd
+#define CMDTHREAD_QKERIODIC_EXECUT                  0x0D73023D // cmd
+#define RT_CMD_SET_KEY_TABLE                        0x0D730228  // cmd
+#define RT_CMD_SET_RX_WCID_TABLE                    0x0D730229  // cmd
+#define CMDTHREAD_SET_CLIENT_MAC_ENTRY              0x0D73023E // cmd
+#define CMDTHREAD_802_11_QUERY_HARDWARE_REGISTER    0x0D710105 // cmd
+#define CMDTHREAD_802_11_SET_PHY_MODE               0x0D79010C // cmd
+#define CMDTHREAD_802_11_SET_STA_CONFIG             0x0D790111 // cmd
+#define CMDTHREAD_802_11_SET_PREAMBLE               0x0D790101 // cmd
+#define CMDTHREAD_802_11_COUNTER_MEASURE                       0x0D790102      // cmd
+
+
+#define WPA1AKMBIT         0x01
+#define WPA2AKMBIT         0x02
+#define WPA1PSKAKMBIT   0x04
+#define WPA2PSKAKMBIT   0x08
+#define TKIPBIT         0x01
+#define CCMPBIT         0x02
+
+
+#define RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx) \
+    RT28xxUsbStaAsicForceWakeup(pAd, bFromTx);
+
+#define RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp) \
+    RT28xxUsbStaAsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
+
+#define RT28XX_MLME_RADIO_ON(pAd) \
+    RT28xxUsbMlmeRadioOn(pAd);
+
+#define RT28XX_MLME_RADIO_OFF(pAd) \
+    RT28xxUsbMlmeRadioOFF(pAd);
+
+#endif //__RT2870_H__
diff --git a/drivers/staging/rt2870/rt28xx.h b/drivers/staging/rt2870/rt28xx.h
new file mode 100644 (file)
index 0000000..3927d22
--- /dev/null
@@ -0,0 +1,2689 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       rt28xx.h
+
+       Abstract:
+       RT28xx ASIC related definition & structures
+
+       Revision History:
+       Who                     When              What
+       --------        ----------        ----------------------------------------------
+       Jan Lee           Jan-3-2006     created for RT2860c
+*/
+
+#ifndef        __RT28XX_H__
+#define        __RT28XX_H__
+
+
+//
+// PCI registers - base address 0x0000
+//
+#define PCI_CFG                        0x0000
+#define PCI_EECTRL                     0x0004
+#define PCI_MCUCTRL                    0x0008
+
+//
+// SCH/DMA registers - base address 0x0200
+//
+// INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit
+//
+#define DMA_CSR0      0x200
+#define INT_SOURCE_CSR      0x200
+#ifdef RT_BIG_ENDIAN
+typedef        union   _INT_SOURCE_CSR_STRUC   {
+       struct  {
+               UINT32          :14;
+               UINT32          TxCoherent:1;
+               UINT32          RxCoherent:1;
+               UINT32          GPTimer:1;
+               UINT32          AutoWakeup:1;//bit14
+               UINT32          TXFifoStatusInt:1;//FIFO Statistics is full, sw should read 0x171c
+               UINT32          PreTBTT:1;
+               UINT32          TBTTInt:1;
+               UINT32          RxTxCoherent:1;
+               UINT32          MCUCommandINT:1;
+               UINT32          MgmtDmaDone:1;
+               UINT32          HccaDmaDone:1;
+               UINT32          Ac3DmaDone:1;
+               UINT32          Ac2DmaDone:1;
+               UINT32          Ac1DmaDone:1;
+               UINT32          Ac0DmaDone:1;
+               UINT32          RxDone:1;
+               UINT32          TxDelayINT:1;   //delayed interrupt, not interrupt until several int or time limit hit
+               UINT32          RxDelayINT:1; //dealyed interrupt
+       }       field;
+       UINT32                  word;
+}      INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC;
+#else
+typedef        union   _INT_SOURCE_CSR_STRUC   {
+       struct  {
+               UINT32          RxDelayINT:1;
+               UINT32          TxDelayINT:1;
+               UINT32          RxDone:1;
+               UINT32          Ac0DmaDone:1;//4
+               UINT32          Ac1DmaDone:1;
+               UINT32          Ac2DmaDone:1;
+               UINT32          Ac3DmaDone:1;
+               UINT32          HccaDmaDone:1; // bit7
+               UINT32          MgmtDmaDone:1;
+               UINT32          MCUCommandINT:1;//bit 9
+               UINT32          RxTxCoherent:1;
+               UINT32          TBTTInt:1;
+               UINT32          PreTBTT:1;
+               UINT32          TXFifoStatusInt:1;//FIFO Statistics is full, sw should read 0x171c
+               UINT32          AutoWakeup:1;//bit14
+               UINT32          GPTimer:1;
+               UINT32          RxCoherent:1;//bit16
+               UINT32          TxCoherent:1;
+               UINT32          :14;
+       }       field;
+       UINT32                  word;
+} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC;
+#endif
+
+//
+// INT_MASK_CSR:   Interrupt MASK register.   1: the interrupt is mask OFF
+//
+#define INT_MASK_CSR        0x204
+#ifdef RT_BIG_ENDIAN
+typedef        union   _INT_MASK_CSR_STRUC     {
+       struct  {
+               UINT32          TxCoherent:1;
+               UINT32          RxCoherent:1;
+               UINT32          :20;
+               UINT32          MCUCommandINT:1;
+               UINT32          MgmtDmaDone:1;
+               UINT32          HccaDmaDone:1;
+               UINT32          Ac3DmaDone:1;
+               UINT32          Ac2DmaDone:1;
+               UINT32          Ac1DmaDone:1;
+               UINT32          Ac0DmaDone:1;
+               UINT32          RxDone:1;
+               UINT32          TxDelay:1;
+               UINT32          RXDelay_INT_MSK:1;
+       }       field;
+       UINT32                  word;
+}INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC;
+#else
+typedef        union   _INT_MASK_CSR_STRUC     {
+       struct  {
+               UINT32          RXDelay_INT_MSK:1;
+               UINT32          TxDelay:1;
+               UINT32          RxDone:1;
+               UINT32          Ac0DmaDone:1;
+               UINT32          Ac1DmaDone:1;
+               UINT32          Ac2DmaDone:1;
+               UINT32          Ac3DmaDone:1;
+               UINT32          HccaDmaDone:1;
+               UINT32          MgmtDmaDone:1;
+               UINT32          MCUCommandINT:1;
+               UINT32          :20;
+               UINT32          RxCoherent:1;
+               UINT32          TxCoherent:1;
+       }       field;
+       UINT32                  word;
+} INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC;
+#endif
+#define WPDMA_GLO_CFG  0x208
+#ifdef RT_BIG_ENDIAN
+typedef        union   _WPDMA_GLO_CFG_STRUC    {
+       struct  {
+               UINT32          HDR_SEG_LEN:16;
+               UINT32          RXHdrScater:8;
+               UINT32          BigEndian:1;
+               UINT32          EnTXWriteBackDDONE:1;
+               UINT32          WPDMABurstSIZE:2;
+               UINT32          RxDMABusy:1;
+               UINT32          EnableRxDMA:1;
+               UINT32          TxDMABusy:1;
+               UINT32          EnableTxDMA:1;
+       }       field;
+       UINT32                  word;
+}WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC;
+#else
+typedef        union   _WPDMA_GLO_CFG_STRUC    {
+       struct  {
+               UINT32          EnableTxDMA:1;
+               UINT32          TxDMABusy:1;
+               UINT32          EnableRxDMA:1;
+               UINT32          RxDMABusy:1;
+               UINT32          WPDMABurstSIZE:2;
+               UINT32          EnTXWriteBackDDONE:1;
+               UINT32          BigEndian:1;
+               UINT32          RXHdrScater:8;
+               UINT32          HDR_SEG_LEN:16;
+       }       field;
+       UINT32                  word;
+} WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC;
+#endif
+#define WPDMA_RST_IDX  0x20c
+#ifdef RT_BIG_ENDIAN
+typedef        union   _WPDMA_RST_IDX_STRUC    {
+       struct  {
+               UINT32          :15;
+               UINT32          RST_DRX_IDX0:1;
+               UINT32          rsv:10;
+               UINT32          RST_DTX_IDX5:1;
+               UINT32          RST_DTX_IDX4:1;
+               UINT32          RST_DTX_IDX3:1;
+               UINT32          RST_DTX_IDX2:1;
+               UINT32          RST_DTX_IDX1:1;
+               UINT32          RST_DTX_IDX0:1;
+       }       field;
+       UINT32                  word;
+}WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC;
+#else
+typedef        union   _WPDMA_RST_IDX_STRUC    {
+       struct  {
+               UINT32          RST_DTX_IDX0:1;
+               UINT32          RST_DTX_IDX1:1;
+               UINT32          RST_DTX_IDX2:1;
+               UINT32          RST_DTX_IDX3:1;
+               UINT32          RST_DTX_IDX4:1;
+               UINT32          RST_DTX_IDX5:1;
+               UINT32          rsv:10;
+               UINT32          RST_DRX_IDX0:1;
+               UINT32          :15;
+       }       field;
+       UINT32                  word;
+} WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC;
+#endif
+#define DELAY_INT_CFG  0x0210
+#ifdef RT_BIG_ENDIAN
+typedef        union   _DELAY_INT_CFG_STRUC    {
+       struct  {
+               UINT32          TXDLY_INT_EN:1;
+               UINT32          TXMAX_PINT:7;
+               UINT32          TXMAX_PTIME:8;
+               UINT32          RXDLY_INT_EN:1;
+               UINT32          RXMAX_PINT:7;
+               UINT32          RXMAX_PTIME:8;
+       }       field;
+       UINT32                  word;
+}DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC;
+#else
+typedef        union   _DELAY_INT_CFG_STRUC    {
+       struct  {
+               UINT32          RXMAX_PTIME:8;
+               UINT32          RXMAX_PINT:7;
+               UINT32          RXDLY_INT_EN:1;
+               UINT32          TXMAX_PTIME:8;
+               UINT32          TXMAX_PINT:7;
+               UINT32          TXDLY_INT_EN:1;
+       }       field;
+       UINT32                  word;
+} DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC;
+#endif
+#define WMM_AIFSN_CFG   0x0214
+#ifdef RT_BIG_ENDIAN
+typedef        union   _AIFSN_CSR_STRUC        {
+       struct  {
+           UINT32   Rsv:16;
+           UINT32   Aifsn3:4;       // for AC_VO
+           UINT32   Aifsn2:4;       // for AC_VI
+           UINT32   Aifsn1:4;       // for AC_BK
+           UINT32   Aifsn0:4;       // for AC_BE
+       }       field;
+       UINT32                  word;
+}      AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC;
+#else
+typedef        union   _AIFSN_CSR_STRUC        {
+       struct  {
+           UINT32   Aifsn0:4;       // for AC_BE
+           UINT32   Aifsn1:4;       // for AC_BK
+           UINT32   Aifsn2:4;       // for AC_VI
+           UINT32   Aifsn3:4;       // for AC_VO
+           UINT32   Rsv:16;
+       }       field;
+       UINT32                  word;
+}      AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC;
+#endif
+//
+// CWMIN_CSR: CWmin for each EDCA AC
+//
+#define WMM_CWMIN_CFG   0x0218
+#ifdef RT_BIG_ENDIAN
+typedef        union   _CWMIN_CSR_STRUC        {
+       struct  {
+           UINT32   Rsv:16;
+           UINT32   Cwmin3:4;       // for AC_VO
+           UINT32   Cwmin2:4;       // for AC_VI
+           UINT32   Cwmin1:4;       // for AC_BK
+           UINT32   Cwmin0:4;       // for AC_BE
+       }       field;
+       UINT32                  word;
+}      CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC;
+#else
+typedef        union   _CWMIN_CSR_STRUC        {
+       struct  {
+           UINT32   Cwmin0:4;       // for AC_BE
+           UINT32   Cwmin1:4;       // for AC_BK
+           UINT32   Cwmin2:4;       // for AC_VI
+           UINT32   Cwmin3:4;       // for AC_VO
+           UINT32   Rsv:16;
+       }       field;
+       UINT32                  word;
+}      CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC;
+#endif
+
+//
+// CWMAX_CSR: CWmin for each EDCA AC
+//
+#define WMM_CWMAX_CFG   0x021c
+#ifdef RT_BIG_ENDIAN
+typedef        union   _CWMAX_CSR_STRUC        {
+       struct  {
+           UINT32   Rsv:16;
+           UINT32   Cwmax3:4;       // for AC_VO
+           UINT32   Cwmax2:4;       // for AC_VI
+           UINT32   Cwmax1:4;       // for AC_BK
+           UINT32   Cwmax0:4;       // for AC_BE
+       }       field;
+       UINT32                  word;
+}      CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC;
+#else
+typedef        union   _CWMAX_CSR_STRUC        {
+       struct  {
+           UINT32   Cwmax0:4;       // for AC_BE
+           UINT32   Cwmax1:4;       // for AC_BK
+           UINT32   Cwmax2:4;       // for AC_VI
+           UINT32   Cwmax3:4;       // for AC_VO
+           UINT32   Rsv:16;
+       }       field;
+       UINT32                  word;
+}      CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC;
+#endif
+
+
+//
+// AC_TXOP_CSR0: AC_BK/AC_BE TXOP register
+//
+#define WMM_TXOP0_CFG    0x0220
+#ifdef RT_BIG_ENDIAN
+typedef        union   _AC_TXOP_CSR0_STRUC     {
+       struct  {
+           USHORT  Ac1Txop;        // for AC_BE, in unit of 32us
+           USHORT  Ac0Txop;        // for AC_BK, in unit of 32us
+       }       field;
+       UINT32                  word;
+}      AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC;
+#else
+typedef        union   _AC_TXOP_CSR0_STRUC     {
+       struct  {
+           USHORT  Ac0Txop;        // for AC_BK, in unit of 32us
+           USHORT  Ac1Txop;        // for AC_BE, in unit of 32us
+       }       field;
+       UINT32                  word;
+}      AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC;
+#endif
+
+//
+// AC_TXOP_CSR1: AC_VO/AC_VI TXOP register
+//
+#define WMM_TXOP1_CFG    0x0224
+#ifdef RT_BIG_ENDIAN
+typedef        union   _AC_TXOP_CSR1_STRUC     {
+       struct  {
+           USHORT  Ac3Txop;        // for AC_VO, in unit of 32us
+           USHORT  Ac2Txop;        // for AC_VI, in unit of 32us
+       }       field;
+       UINT32                  word;
+}      AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC;
+#else
+typedef        union   _AC_TXOP_CSR1_STRUC     {
+       struct  {
+           USHORT  Ac2Txop;        // for AC_VI, in unit of 32us
+           USHORT  Ac3Txop;        // for AC_VO, in unit of 32us
+       }       field;
+       UINT32                  word;
+}      AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC;
+#endif
+#define RINGREG_DIFF                   0x10
+#define GPIO_CTRL_CFG    0x0228        //MAC_CSR13
+#define MCU_CMD_CFG    0x022c
+#define TX_BASE_PTR0     0x0230        //AC_BK base address
+#define TX_MAX_CNT0      0x0234
+#define TX_CTX_IDX0       0x0238
+#define TX_DTX_IDX0      0x023c
+#define TX_BASE_PTR1     0x0240        //AC_BE base address
+#define TX_MAX_CNT1      0x0244
+#define TX_CTX_IDX1       0x0248
+#define TX_DTX_IDX1      0x024c
+#define TX_BASE_PTR2     0x0250        //AC_VI base address
+#define TX_MAX_CNT2      0x0254
+#define TX_CTX_IDX2       0x0258
+#define TX_DTX_IDX2      0x025c
+#define TX_BASE_PTR3     0x0260        //AC_VO base address
+#define TX_MAX_CNT3      0x0264
+#define TX_CTX_IDX3       0x0268
+#define TX_DTX_IDX3      0x026c
+#define TX_BASE_PTR4     0x0270        //HCCA base address
+#define TX_MAX_CNT4      0x0274
+#define TX_CTX_IDX4       0x0278
+#define TX_DTX_IDX4      0x027c
+#define TX_BASE_PTR5     0x0280        //MGMT base address
+#define  TX_MAX_CNT5     0x0284
+#define TX_CTX_IDX5       0x0288
+#define TX_DTX_IDX5      0x028c
+#define TX_MGMTMAX_CNT      TX_MAX_CNT5
+#define TX_MGMTCTX_IDX       TX_CTX_IDX5
+#define TX_MGMTDTX_IDX      TX_DTX_IDX5
+#define RX_BASE_PTR     0x0290         //RX base address
+#define RX_MAX_CNT      0x0294
+#define RX_CRX_IDX       0x0298
+#define RX_DRX_IDX      0x029c
+#define USB_DMA_CFG      0x02a0
+#ifdef RT_BIG_ENDIAN
+typedef        union   _USB_DMA_CFG_STRUC      {
+       struct  {
+           UINT32  TxBusy:1;           //USB DMA TX FSM busy . debug only
+           UINT32  RxBusy:1;        //USB DMA RX FSM busy . debug only
+           UINT32  EpoutValid:6;        //OUT endpoint data valid. debug only
+           UINT32  TxBulkEn:1;        //Enable USB DMA Tx
+           UINT32  RxBulkEn:1;        //Enable USB DMA Rx
+           UINT32  RxBulkAggEn:1;        //Enable Rx Bulk Aggregation
+           UINT32  TxopHalt:1;        //Halt TXOP count down when TX buffer is full.
+           UINT32  TxClear:1;        //Clear USB DMA TX path
+           UINT32  rsv:2;
+           UINT32  phyclear:1;                 //phy watch dog enable. write 1
+           UINT32  RxBulkAggLmt:8;        //Rx Bulk Aggregation Limit  in unit of 1024 bytes
+           UINT32  RxBulkAggTOut:8;        //Rx Bulk Aggregation TimeOut  in unit of 33ns
+       }       field;
+       UINT32                  word;
+}      USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC;
+#else
+typedef        union   _USB_DMA_CFG_STRUC      {
+       struct  {
+           UINT32  RxBulkAggTOut:8;        //Rx Bulk Aggregation TimeOut  in unit of 33ns
+           UINT32  RxBulkAggLmt:8;        //Rx Bulk Aggregation Limit  in unit of 256 bytes
+           UINT32  phyclear:1;                 //phy watch dog enable. write 1
+           UINT32  rsv:2;
+           UINT32  TxClear:1;        //Clear USB DMA TX path
+           UINT32  TxopHalt:1;        //Halt TXOP count down when TX buffer is full.
+           UINT32  RxBulkAggEn:1;        //Enable Rx Bulk Aggregation
+           UINT32  RxBulkEn:1;        //Enable USB DMA Rx
+           UINT32  TxBulkEn:1;        //Enable USB DMA Tx
+           UINT32  EpoutValid:6;        //OUT endpoint data valid
+           UINT32  RxBusy:1;        //USB DMA RX FSM busy
+           UINT32  TxBusy:1;           //USB DMA TX FSM busy
+       }       field;
+       UINT32                  word;
+}      USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC;
+#endif
+
+//
+//  3  PBF  registers
+//
+//
+// Most are for debug. Driver doesn't touch PBF register.
+#define        PBF_SYS_CTRL     0x0400
+#define     PBF_CFG                 0x0408
+#define        PBF_MAX_PCNT     0x040C
+#define        PBF_CTRL                0x0410
+#define        PBF_INT_STA      0x0414
+#define        PBF_INT_ENA      0x0418
+#define        TXRXQ_PCNT       0x0438
+#define        PBF_DBG                  0x043c
+#define     PBF_CAP_CTRL     0x0440
+
+//
+//  4  MAC  registers
+//
+//
+//  4.1 MAC SYSTEM  configuration registers (offset:0x1000)
+//
+#define MAC_CSR0            0x1000
+#ifdef RT_BIG_ENDIAN
+typedef        union   _ASIC_VER_ID_STRUC      {
+       struct  {
+           USHORT  ASICVer;        // version : 2860
+           USHORT  ASICRev;        // reversion  : 0
+       }       field;
+       UINT32                  word;
+}      ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC;
+#else
+typedef        union   _ASIC_VER_ID_STRUC      {
+       struct  {
+           USHORT  ASICRev;        // reversion  : 0
+           USHORT  ASICVer;        // version : 2860
+       }       field;
+       UINT32                  word;
+}      ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC;
+#endif
+#define MAC_SYS_CTRL            0x1004         //MAC_CSR1
+#define MAC_ADDR_DW0                           0x1008          // MAC ADDR DW0
+#define MAC_ADDR_DW1                            0x100c         // MAC ADDR DW1
+//
+// MAC_CSR2: STA MAC register 0
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _MAC_DW0_STRUC  {
+       struct  {
+               UCHAR           Byte3;          // MAC address byte 3
+               UCHAR           Byte2;          // MAC address byte 2
+               UCHAR           Byte1;          // MAC address byte 1
+               UCHAR           Byte0;          // MAC address byte 0
+       }       field;
+       UINT32                  word;
+}      MAC_DW0_STRUC, *PMAC_DW0_STRUC;
+#else
+typedef        union   _MAC_DW0_STRUC  {
+       struct  {
+               UCHAR           Byte0;          // MAC address byte 0
+               UCHAR           Byte1;          // MAC address byte 1
+               UCHAR           Byte2;          // MAC address byte 2
+               UCHAR           Byte3;          // MAC address byte 3
+       }       field;
+       UINT32                  word;
+}      MAC_DW0_STRUC, *PMAC_DW0_STRUC;
+#endif
+
+//
+// MAC_CSR3: STA MAC register 1
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _MAC_DW1_STRUC  {
+       struct  {
+               UCHAR           Rsvd1;
+               UCHAR           U2MeMask;
+               UCHAR           Byte5;          // MAC address byte 5
+               UCHAR           Byte4;          // MAC address byte 4
+       }       field;
+       UINT32                  word;
+}      MAC_DW1_STRUC, *PMAC_DW1_STRUC;
+#else
+typedef        union   _MAC_DW1_STRUC  {
+       struct  {
+               UCHAR           Byte4;          // MAC address byte 4
+               UCHAR           Byte5;          // MAC address byte 5
+               UCHAR           U2MeMask;
+               UCHAR           Rsvd1;
+       }       field;
+       UINT32                  word;
+}      MAC_DW1_STRUC, *PMAC_DW1_STRUC;
+#endif
+
+#define MAC_BSSID_DW0                          0x1010          // MAC BSSID DW0
+#define MAC_BSSID_DW1                          0x1014          // MAC BSSID DW1
+
+//
+// MAC_CSR5: BSSID register 1
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _MAC_CSR5_STRUC {
+       struct  {
+               USHORT          Rsvd:11;
+               USHORT          MBssBcnNum:3;
+               USHORT          BssIdMode:2; // 0: one BSSID, 10: 4 BSSID,  01: 2 BSSID , 11: 8BSSID
+               UCHAR           Byte5;           // BSSID byte 5
+               UCHAR           Byte4;           // BSSID byte 4
+       }       field;
+       UINT32                  word;
+}      MAC_CSR5_STRUC, *PMAC_CSR5_STRUC;
+#else
+typedef        union   _MAC_CSR5_STRUC {
+       struct  {
+               UCHAR           Byte4;           // BSSID byte 4
+               UCHAR           Byte5;           // BSSID byte 5
+               USHORT          BssIdMask:2; // 0: one BSSID, 10: 4 BSSID,  01: 2 BSSID , 11: 8BSSID
+               USHORT          MBssBcnNum:3;
+               USHORT          Rsvd:11;
+       }       field;
+       UINT32                  word;
+}      MAC_CSR5_STRUC, *PMAC_CSR5_STRUC;
+#endif
+
+#define MAX_LEN_CFG              0x1018                // rt2860b max 16k bytes. bit12:13 Maximum PSDU length (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16
+#define BBP_CSR_CFG                            0x101c          //
+//
+// BBP_CSR_CFG: BBP serial control register
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _BBP_CSR_CFG_STRUC      {
+       struct  {
+               UINT32          :12;
+               UINT32          BBP_RW_MODE:1;          // 0: use serial mode  1:parallel
+               UINT32          BBP_PAR_DUR:1;              // 0: 4 MAC clock cycles  1: 8 MAC clock cycles
+               UINT32          Busy:1;                         // 1: ASIC is busy execute BBP programming.
+               UINT32          fRead:1;                    // 0: Write BBP, 1: Read BBP
+               UINT32          RegNum:8;                       // Selected     BBP     register
+               UINT32          Value:8;                        // Register     value to program into BBP
+       }       field;
+       UINT32                  word;
+}      BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC;
+#else
+typedef        union   _BBP_CSR_CFG_STRUC      {
+       struct  {
+               UINT32          Value:8;                        // Register     value to program into BBP
+               UINT32          RegNum:8;                       // Selected     BBP     register
+               UINT32          fRead:1;                    // 0: Write BBP, 1: Read BBP
+               UINT32          Busy:1;                         // 1: ASIC is busy execute BBP programming.
+               UINT32          BBP_PAR_DUR:1;               // 0: 4 MAC clock cycles  1: 8 MAC clock cycles
+               UINT32          BBP_RW_MODE:1;          // 0: use serial mode  1:parallel
+               UINT32          :12;
+       }       field;
+       UINT32                  word;
+}      BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC;
+#endif
+#define RF_CSR_CFG0                            0x1020
+//
+// RF_CSR_CFG: RF control register
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _RF_CSR_CFG0_STRUC      {
+       struct  {
+               UINT32          Busy:1;             // 0: idle 1: 8busy
+               UINT32          Sel:1;                          // 0:RF_LE0 activate  1:RF_LE1 activate
+               UINT32          StandbyMode:1;              // 0: high when stand by 1: low when standby
+               UINT32          bitwidth:5;                     // Selected     BBP     register
+               UINT32          RegIdAndContent:24;                     // Register     value to program into BBP
+       }       field;
+       UINT32                  word;
+}      RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC;
+#else
+typedef        union   _RF_CSR_CFG0_STRUC      {
+       struct  {
+               UINT32          RegIdAndContent:24;                     // Register     value to program into BBP
+               UINT32          bitwidth:5;                     // Selected     BBP     register
+               UINT32          StandbyMode:1;              // 0: high when stand by 1: low when standby
+               UINT32          Sel:1;                          // 0:RF_LE0 activate  1:RF_LE1 activate
+               UINT32          Busy:1;             // 0: idle 1: 8busy
+       }       field;
+       UINT32                  word;
+}      RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC;
+#endif
+#define RF_CSR_CFG1                    0x1024
+#ifdef RT_BIG_ENDIAN
+typedef        union   _RF_CSR_CFG1_STRUC      {
+       struct  {
+               UINT32          rsv:7;              // 0: idle 1: 8busy
+               UINT32          RFGap:5;                        // Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec)
+               UINT32          RegIdAndContent:24;                     // Register     value to program into BBP
+       }       field;
+       UINT32                  word;
+}      RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC;
+#else
+typedef        union   _RF_CSR_CFG1_STRUC      {
+       struct  {
+               UINT32          RegIdAndContent:24;                     // Register     value to program into BBP
+               UINT32          RFGap:5;                        // Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec)
+               UINT32          rsv:7;              // 0: idle 1: 8busy
+       }       field;
+       UINT32                  word;
+}      RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC;
+#endif
+#define RF_CSR_CFG2                    0x1028          //
+#ifdef RT_BIG_ENDIAN
+typedef        union   _RF_CSR_CFG2_STRUC      {
+       struct  {
+               UINT32          rsv:8;              // 0: idle 1: 8busy
+               UINT32          RegIdAndContent:24;                     // Register     value to program into BBP
+       }       field;
+       UINT32                  word;
+}      RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC;
+#else
+typedef        union   _RF_CSR_CFG2_STRUC      {
+       struct  {
+               UINT32          RegIdAndContent:24;                     // Register     value to program into BBP
+               UINT32          rsv:8;              // 0: idle 1: 8busy
+       }       field;
+       UINT32                  word;
+}      RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC;
+#endif
+#define LED_CFG                        0x102c          //  MAC_CSR14
+#ifdef RT_BIG_ENDIAN
+typedef        union   _LED_CFG_STRUC  {
+       struct  {
+               UINT32          :1;
+               UINT32          LedPolar:1;                     // Led Polarity.  0: active low1: active high
+               UINT32          YLedMode:2;                     // yellow Led Mode
+               UINT32          GLedMode:2;                     // green Led Mode
+               UINT32          RLedMode:2;                     // red Led Mode    0: off1: blinking upon TX2: periodic slow blinking3: always on
+               UINT32          rsv:2;
+               UINT32          SlowBlinkPeriod:6;                      // slow blinking period. unit:1ms
+               UINT32          OffPeriod:8;                    // blinking off period unit 1ms
+               UINT32          OnPeriod:8;                     // blinking on period unit 1ms
+       }       field;
+       UINT32                  word;
+}      LED_CFG_STRUC, *PLED_CFG_STRUC;
+#else
+typedef        union   _LED_CFG_STRUC  {
+       struct  {
+               UINT32          OnPeriod:8;                     // blinking on period unit 1ms
+               UINT32          OffPeriod:8;                    // blinking off period unit 1ms
+               UINT32          SlowBlinkPeriod:6;                      // slow blinking period. unit:1ms
+               UINT32          rsv:2;
+               UINT32          RLedMode:2;                     // red Led Mode    0: off1: blinking upon TX2: periodic slow blinking3: always on
+               UINT32          GLedMode:2;                     // green Led Mode
+               UINT32          YLedMode:2;                     // yellow Led Mode
+               UINT32          LedPolar:1;                     // Led Polarity.  0: active low1: active high
+               UINT32          :1;
+       }       field;
+       UINT32                  word;
+}      LED_CFG_STRUC, *PLED_CFG_STRUC;
+#endif
+//
+//  4.2 MAC TIMING  configuration registers (offset:0x1100)
+//
+#define XIFS_TIME_CFG             0x1100                // MAC_CSR8  MAC_CSR9
+#ifdef RT_BIG_ENDIAN
+typedef        union   _IFS_SLOT_CFG_STRUC     {
+       struct  {
+           UINT32  rsv:2;
+           UINT32  BBRxendEnable:1;        //  reference RXEND signal to begin XIFS defer
+           UINT32  EIFS:9;        //  unit 1us
+           UINT32  OfdmXifsTime:4;        //OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND
+           UINT32  OfdmSifsTime:8;        //  unit 1us. Applied after OFDM RX/TX
+           UINT32  CckmSifsTime:8;        //  unit 1us. Applied after CCK RX/TX
+       }       field;
+       UINT32                  word;
+}      IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC;
+#else
+typedef        union   _IFS_SLOT_CFG_STRUC     {
+       struct  {
+           UINT32  CckmSifsTime:8;        //  unit 1us. Applied after CCK RX/TX
+           UINT32  OfdmSifsTime:8;        //  unit 1us. Applied after OFDM RX/TX
+           UINT32  OfdmXifsTime:4;        //OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND
+           UINT32  EIFS:9;        //  unit 1us
+           UINT32  BBRxendEnable:1;        //  reference RXEND signal to begin XIFS defer
+           UINT32  rsv:2;
+       }       field;
+       UINT32                  word;
+}      IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC;
+#endif
+
+#define BKOFF_SLOT_CFG             0x1104               //  mac_csr9 last 8 bits
+#define NAV_TIME_CFG             0x1108                 // NAV  (MAC_CSR15)
+#define CH_TIME_CFG             0x110C                 // Count as channel busy
+#define PBF_LIFE_TIMER             0x1110               //TX/RX MPDU timestamp timer (free run)Unit: 1us
+#define BCN_TIME_CFG             0x1114                 // TXRX_CSR9
+
+#define BCN_OFFSET0                            0x042C
+#define BCN_OFFSET1                            0x0430
+
+//
+// BCN_TIME_CFG : Synchronization control register
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _BCN_TIME_CFG_STRUC     {
+       struct  {
+               UINT32          TxTimestampCompensate:8;
+        UINT32       :3;
+               UINT32          bBeaconGen:1;           // Enable beacon generator
+        UINT32       bTBTTEnable:1;
+               UINT32          TsfSyncMode:2;          // Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode
+               UINT32          bTsfTicking:1;          // Enable TSF auto counting
+               UINT32       BeaconInterval:16;  // in unit of 1/16 TU
+       }       field;
+       UINT32                  word;
+}      BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC;
+#else
+typedef        union   _BCN_TIME_CFG_STRUC     {
+       struct  {
+               UINT32       BeaconInterval:16;  // in unit of 1/16 TU
+               UINT32          bTsfTicking:1;          // Enable TSF auto counting
+               UINT32          TsfSyncMode:2;          // Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode
+        UINT32       bTBTTEnable:1;
+               UINT32          bBeaconGen:1;           // Enable beacon generator
+        UINT32       :3;
+               UINT32          TxTimestampCompensate:8;
+       }       field;
+       UINT32                  word;
+}      BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC;
+#endif
+#define TBTT_SYNC_CFG            0x1118                // txrx_csr10
+#define TSF_TIMER_DW0             0x111C               // Local TSF timer lsb 32 bits. Read-only
+#define TSF_TIMER_DW1             0x1120               // msb 32 bits. Read-only.
+#define TBTT_TIMER                     0x1124                  // TImer remains till next TBTT. Read-only.  TXRX_CSR14
+#define INT_TIMER_CFG                  0x1128                  //
+#define INT_TIMER_EN                   0x112c                  //  GP-timer and pre-tbtt Int enable
+#define CH_IDLE_STA                    0x1130                  //  channel idle time
+#define CH_BUSY_STA                    0x1134                  //  channle busy time
+//
+//  4.2 MAC POWER  configuration registers (offset:0x1200)
+//
+#define MAC_STATUS_CFG             0x1200               // old MAC_CSR12
+#define PWR_PIN_CFG             0x1204          // old MAC_CSR12
+#define AUTO_WAKEUP_CFG             0x1208              // old MAC_CSR10
+//
+// AUTO_WAKEUP_CFG: Manual power control / status register
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _AUTO_WAKEUP_STRUC      {
+       struct  {
+               UINT32          :16;
+               UINT32          EnableAutoWakeup:1;     // 0:sleep, 1:awake
+               UINT32       NumofSleepingTbtt:7;          // ForceWake has high privilege than PutToSleep when both set
+               UINT32       AutoLeadTime:8;
+       }       field;
+       UINT32                  word;
+}      AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC;
+#else
+typedef        union   _AUTO_WAKEUP_STRUC      {
+       struct  {
+               UINT32       AutoLeadTime:8;
+               UINT32       NumofSleepingTbtt:7;          // ForceWake has high privilege than PutToSleep when both set
+               UINT32          EnableAutoWakeup:1;     // 0:sleep, 1:awake
+               UINT32          :16;
+       }       field;
+       UINT32                  word;
+}      AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC;
+#endif
+//
+//  4.3 MAC TX  configuration registers (offset:0x1300)
+//
+
+#define EDCA_AC0_CFG   0x1300          //AC_TXOP_CSR0 0x3474
+#define EDCA_AC1_CFG   0x1304
+#define EDCA_AC2_CFG   0x1308
+#define EDCA_AC3_CFG   0x130c
+#ifdef RT_BIG_ENDIAN
+typedef        union   _EDCA_AC_CFG_STRUC      {
+       struct  {
+           UINT32  :12;        //
+           UINT32  Cwmax:4;        //unit power of 2
+           UINT32  Cwmin:4;        //
+           UINT32  Aifsn:4;        // # of slot time
+           UINT32  AcTxop:8;        //  in unit of 32us
+       }       field;
+       UINT32                  word;
+}      EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC;
+#else
+typedef        union   _EDCA_AC_CFG_STRUC      {
+       struct  {
+           UINT32  AcTxop:8;        //  in unit of 32us
+           UINT32  Aifsn:4;        // # of slot time
+           UINT32  Cwmin:4;        //
+           UINT32  Cwmax:4;        //unit power of 2
+           UINT32  :12;       //
+       }       field;
+       UINT32                  word;
+}      EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC;
+#endif
+
+#define EDCA_TID_AC_MAP        0x1310
+#define TX_PWR_CFG_0   0x1314
+#define TX_PWR_CFG_1   0x1318
+#define TX_PWR_CFG_2   0x131C
+#define TX_PWR_CFG_3   0x1320
+#define TX_PWR_CFG_4   0x1324
+#define TX_PIN_CFG             0x1328
+#define TX_BAND_CFG    0x132c          // 0x1 use upper 20MHz. 0 juse lower 20MHz
+#define TX_SW_CFG0             0x1330
+#define TX_SW_CFG1             0x1334
+#define TX_SW_CFG2             0x1338
+#define TXOP_THRES_CFG         0x133c
+#define TXOP_CTRL_CFG          0x1340
+#define TX_RTS_CFG             0x1344
+
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_RTS_CFG_STRUC       {
+       struct  {
+           UINT32       rsv:7;
+           UINT32       RtsFbkEn:1;    // enable rts rate fallback
+           UINT32       RtsThres:16;    // unit:byte
+           UINT32       AutoRtsRetryLimit:8;
+       }       field;
+       UINT32                  word;
+}      TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC;
+#else
+typedef        union   _TX_RTS_CFG_STRUC       {
+       struct  {
+           UINT32       AutoRtsRetryLimit:8;
+           UINT32       RtsThres:16;    // unit:byte
+           UINT32       RtsFbkEn:1;    // enable rts rate fallback
+           UINT32       rsv:7;     // 1: HT non-STBC control frame enable
+       }       field;
+       UINT32                  word;
+}      TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC;
+#endif
+#define TX_TIMEOUT_CFG 0x1348
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_TIMEOUT_CFG_STRUC   {
+       struct  {
+           UINT32       rsv2:8;
+           UINT32       TxopTimeout:8; //TXOP timeout value for TXOP truncation.  It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT)
+           UINT32       RxAckTimeout:8;        // unit:slot. Used for TX precedure
+           UINT32       MpduLifeTime:4;    //  expiration time = 2^(9+MPDU LIFE TIME)  us
+           UINT32       rsv:4;
+       }       field;
+       UINT32                  word;
+}      TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC;
+#else
+typedef        union   _TX_TIMEOUT_CFG_STRUC   {
+       struct  {
+           UINT32       rsv:4;
+           UINT32       MpduLifeTime:4;    //  expiration time = 2^(9+MPDU LIFE TIME)  us
+           UINT32       RxAckTimeout:8;        // unit:slot. Used for TX precedure
+           UINT32       TxopTimeout:8; //TXOP timeout value for TXOP truncation.  It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT)
+           UINT32       rsv2:8;     // 1: HT non-STBC control frame enable
+       }       field;
+       UINT32                  word;
+}      TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC;
+#endif
+#define TX_RTY_CFG     0x134c
+#ifdef RT_BIG_ENDIAN
+typedef        union PACKED _TX_RTY_CFG_STRUC  {
+       struct  {
+           UINT32       rsv:1;
+           UINT32       TxautoFBEnable:1;    // Tx retry PHY rate auto fallback enable
+           UINT32       AggRtyMode:1;  // Aggregate MPDU retry mode.  0:expired by retry limit, 1: expired by mpdu life timer
+           UINT32       NonAggRtyMode:1;       // Non-Aggregate MPDU retry mode.  0:expired by retry limit, 1: expired by mpdu life timer
+           UINT32       LongRtyThre:12;        // Long retry threshoold
+           UINT32       LongRtyLimit:8;        //long retry limit
+           UINT32       ShortRtyLimit:8;       //  short retry limit
+
+       }       field;
+       UINT32                  word;
+}      TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC;
+#else
+typedef        union PACKED _TX_RTY_CFG_STRUC  {
+       struct  {
+           UINT32       ShortRtyLimit:8;       //  short retry limit
+           UINT32       LongRtyLimit:8;        //long retry limit
+           UINT32       LongRtyThre:12;        // Long retry threshoold
+           UINT32       NonAggRtyMode:1;       // Non-Aggregate MPDU retry mode.  0:expired by retry limit, 1: expired by mpdu life timer
+           UINT32       AggRtyMode:1;  // Aggregate MPDU retry mode.  0:expired by retry limit, 1: expired by mpdu life timer
+           UINT32       TxautoFBEnable:1;    // Tx retry PHY rate auto fallback enable
+           UINT32       rsv:1;     // 1: HT non-STBC control frame enable
+       }       field;
+       UINT32                  word;
+}      TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC;
+#endif
+#define TX_LINK_CFG    0x1350
+#ifdef RT_BIG_ENDIAN
+typedef        union   PACKED _TX_LINK_CFG_STRUC       {
+       struct PACKED {
+           UINT32       RemotMFS:8;    //remote MCS feedback sequence number
+           UINT32       RemotMFB:8;    //  remote MCS feedback
+           UINT32       rsv:3; //
+           UINT32       TxCFAckEn:1;   //   Piggyback CF-ACK enable
+           UINT32       TxRDGEn:1;     // RDG TX enable
+           UINT32       TxMRQEn:1;     //  MCS request TX enable
+           UINT32       RemoteUMFSEnable:1;    //  remote unsolicit  MFB enable.  0: not apply remote remote unsolicit (MFS=7)
+           UINT32       MFBEnable:1;   //  TX apply remote MFB 1:enable
+           UINT32       RemoteMFBLifeTime:8;   //remote MFB life time. unit : 32us
+       }       field;
+       UINT32                  word;
+}      TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC;
+#else
+typedef        union   PACKED _TX_LINK_CFG_STRUC       {
+       struct PACKED {
+           UINT32       RemoteMFBLifeTime:8;   //remote MFB life time. unit : 32us
+           UINT32       MFBEnable:1;   //  TX apply remote MFB 1:enable
+           UINT32       RemoteUMFSEnable:1;    //  remote unsolicit  MFB enable.  0: not apply remote remote unsolicit (MFS=7)
+           UINT32       TxMRQEn:1;     //  MCS request TX enable
+           UINT32       TxRDGEn:1;     // RDG TX enable
+           UINT32       TxCFAckEn:1;   //   Piggyback CF-ACK enable
+           UINT32       rsv:3; //
+           UINT32       RemotMFB:8;    //  remote MCS feedback
+           UINT32       RemotMFS:8;    //remote MCS feedback sequence number
+       }       field;
+       UINT32                  word;
+}      TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC;
+#endif
+#define HT_FBK_CFG0    0x1354
+#ifdef RT_BIG_ENDIAN
+typedef        union PACKED _HT_FBK_CFG0_STRUC {
+       struct  {
+           UINT32       HTMCS7FBK:4;
+           UINT32       HTMCS6FBK:4;
+           UINT32       HTMCS5FBK:4;
+           UINT32       HTMCS4FBK:4;
+           UINT32       HTMCS3FBK:4;
+           UINT32       HTMCS2FBK:4;
+           UINT32       HTMCS1FBK:4;
+           UINT32       HTMCS0FBK:4;
+       }       field;
+       UINT32                  word;
+}      HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC;
+#else
+typedef        union PACKED _HT_FBK_CFG0_STRUC {
+       struct  {
+           UINT32       HTMCS0FBK:4;
+           UINT32       HTMCS1FBK:4;
+           UINT32       HTMCS2FBK:4;
+           UINT32       HTMCS3FBK:4;
+           UINT32       HTMCS4FBK:4;
+           UINT32       HTMCS5FBK:4;
+           UINT32       HTMCS6FBK:4;
+           UINT32       HTMCS7FBK:4;
+       }       field;
+       UINT32                  word;
+}      HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC;
+#endif
+#define HT_FBK_CFG1    0x1358
+#ifdef RT_BIG_ENDIAN
+typedef        union   _HT_FBK_CFG1_STRUC      {
+       struct  {
+           UINT32       HTMCS15FBK:4;
+           UINT32       HTMCS14FBK:4;
+           UINT32       HTMCS13FBK:4;
+           UINT32       HTMCS12FBK:4;
+           UINT32       HTMCS11FBK:4;
+           UINT32       HTMCS10FBK:4;
+           UINT32       HTMCS9FBK:4;
+           UINT32       HTMCS8FBK:4;
+       }       field;
+       UINT32                  word;
+}      HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC;
+#else
+typedef        union   _HT_FBK_CFG1_STRUC      {
+       struct  {
+           UINT32       HTMCS8FBK:4;
+           UINT32       HTMCS9FBK:4;
+           UINT32       HTMCS10FBK:4;
+           UINT32       HTMCS11FBK:4;
+           UINT32       HTMCS12FBK:4;
+           UINT32       HTMCS13FBK:4;
+           UINT32       HTMCS14FBK:4;
+           UINT32       HTMCS15FBK:4;
+       }       field;
+       UINT32                  word;
+}      HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC;
+#endif
+#define LG_FBK_CFG0    0x135c
+#ifdef RT_BIG_ENDIAN
+typedef        union   _LG_FBK_CFG0_STRUC      {
+       struct  {
+           UINT32       OFDMMCS7FBK:4; //initial value is 6
+           UINT32       OFDMMCS6FBK:4; //initial value is 5
+           UINT32       OFDMMCS5FBK:4; //initial value is 4
+           UINT32       OFDMMCS4FBK:4; //initial value is 3
+           UINT32       OFDMMCS3FBK:4; //initial value is 2
+           UINT32       OFDMMCS2FBK:4; //initial value is 1
+           UINT32       OFDMMCS1FBK:4; //initial value is 0
+           UINT32       OFDMMCS0FBK:4; //initial value is 0
+       }       field;
+       UINT32                  word;
+}      LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC;
+#else
+typedef        union   _LG_FBK_CFG0_STRUC      {
+       struct  {
+           UINT32       OFDMMCS0FBK:4; //initial value is 0
+           UINT32       OFDMMCS1FBK:4; //initial value is 0
+           UINT32       OFDMMCS2FBK:4; //initial value is 1
+           UINT32       OFDMMCS3FBK:4; //initial value is 2
+           UINT32       OFDMMCS4FBK:4; //initial value is 3
+           UINT32       OFDMMCS5FBK:4; //initial value is 4
+           UINT32       OFDMMCS6FBK:4; //initial value is 5
+           UINT32       OFDMMCS7FBK:4; //initial value is 6
+       }       field;
+       UINT32                  word;
+}      LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC;
+#endif
+#define LG_FBK_CFG1            0x1360
+#ifdef RT_BIG_ENDIAN
+typedef        union   _LG_FBK_CFG1_STRUC      {
+       struct  {
+           UINT32       rsv:16;
+           UINT32       CCKMCS3FBK:4;  //initial value is 2
+           UINT32       CCKMCS2FBK:4;  //initial value is 1
+           UINT32       CCKMCS1FBK:4;  //initial value is 0
+           UINT32       CCKMCS0FBK:4;  //initial value is 0
+       }       field;
+       UINT32                  word;
+}      LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC;
+#else
+typedef        union   _LG_FBK_CFG1_STRUC      {
+       struct  {
+           UINT32       CCKMCS0FBK:4;  //initial value is 0
+           UINT32       CCKMCS1FBK:4;  //initial value is 0
+           UINT32       CCKMCS2FBK:4;  //initial value is 1
+           UINT32       CCKMCS3FBK:4;  //initial value is 2
+           UINT32       rsv:16;
+       }       field;
+       UINT32                  word;
+}      LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC;
+#endif
+
+//=======================================================
+//================ Protection Paramater================================
+//=======================================================
+#define CCK_PROT_CFG   0x1364          //CCK Protection
+#define ASIC_SHORTNAV          1
+#define ASIC_LONGNAV           2
+#define ASIC_RTS               1
+#define ASIC_CTS               2
+#ifdef RT_BIG_ENDIAN
+typedef        union   _PROT_CFG_STRUC {
+       struct  {
+           UINT32       rsv:5;
+           UINT32       RTSThEn:1;     //RTS threshold enable on CCK TX
+           UINT32       TxopAllowGF40:1;       //CCK TXOP allowance.0:disallow.
+           UINT32       TxopAllowGF20:1;       //CCK TXOP allowance.0:disallow.
+           UINT32       TxopAllowMM40:1;       //CCK TXOP allowance.0:disallow.
+           UINT32       TxopAllowMM20:1;       //CCK TXOP allowance. 0:disallow.
+           UINT32       TxopAllowOfdm:1;       //CCK TXOP allowance.0:disallow.
+           UINT32       TxopAllowCck:1;        //CCK TXOP allowance.0:disallow.
+           UINT32       ProtectNav:2;  //TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect,  2:LongNAVProtect, 3:rsv
+           UINT32       ProtectCtrl:2; //Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv
+           UINT32       ProtectRate:16;        //Protection control frame rate for CCK TX(RTS/CTS/CFEnd).
+       }       field;
+       UINT32                  word;
+}      PROT_CFG_STRUC, *PPROT_CFG_STRUC;
+#else
+typedef        union   _PROT_CFG_STRUC {
+       struct  {
+           UINT32       ProtectRate:16;        //Protection control frame rate for CCK TX(RTS/CTS/CFEnd).
+           UINT32       ProtectCtrl:2; //Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv
+           UINT32       ProtectNav:2;  //TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect,  2:LongNAVProtect, 3:rsv
+           UINT32       TxopAllowCck:1;        //CCK TXOP allowance.0:disallow.
+           UINT32       TxopAllowOfdm:1;       //CCK TXOP allowance.0:disallow.
+           UINT32       TxopAllowMM20:1;       //CCK TXOP allowance. 0:disallow.
+           UINT32       TxopAllowMM40:1;       //CCK TXOP allowance.0:disallow.
+           UINT32       TxopAllowGF20:1;       //CCK TXOP allowance.0:disallow.
+           UINT32       TxopAllowGF40:1;       //CCK TXOP allowance.0:disallow.
+           UINT32       RTSThEn:1;     //RTS threshold enable on CCK TX
+           UINT32       rsv:5;
+       }       field;
+       UINT32                  word;
+}      PROT_CFG_STRUC, *PPROT_CFG_STRUC;
+#endif
+
+#define OFDM_PROT_CFG  0x1368          //OFDM Protection
+#define MM20_PROT_CFG  0x136C          //MM20 Protection
+#define MM40_PROT_CFG  0x1370          //MM40 Protection
+#define GF20_PROT_CFG  0x1374          //GF20 Protection
+#define GF40_PROT_CFG  0x1378          //GR40 Protection
+#define EXP_CTS_TIME   0x137C          //
+#define EXP_ACK_TIME   0x1380          //
+
+//
+//  4.4 MAC RX configuration registers (offset:0x1400)
+//
+#define RX_FILTR_CFG   0x1400                  //TXRX_CSR0
+#define AUTO_RSP_CFG   0x1404                  //TXRX_CSR4
+//
+// TXRX_CSR4: Auto-Responder/
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _AUTO_RSP_CFG_STRUC {
+ struct {
+     UINT32        :24;
+     UINT32       AckCtsPsmBit:1;   // Power bit value in conrtrol frame
+     UINT32       DualCTSEn:1;   // Power bit value in conrtrol frame
+     UINT32       rsv:1;   // Power bit value in conrtrol frame
+     UINT32       AutoResponderPreamble:1;    // 0:long, 1:short preamble
+     UINT32       CTS40MRef:1;  // Response CTS 40MHz duplicate mode
+     UINT32       CTS40MMode:1;  // Response CTS 40MHz duplicate mode
+     UINT32       BACAckPolicyEnable:1;    // 0:long, 1:short preamble
+     UINT32       AutoResponderEnable:1;
+ } field;
+ UINT32   word;
+} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC;
+#else
+typedef union _AUTO_RSP_CFG_STRUC {
+ struct {
+     UINT32       AutoResponderEnable:1;
+     UINT32       BACAckPolicyEnable:1;    // 0:long, 1:short preamble
+     UINT32       CTS40MMode:1;  // Response CTS 40MHz duplicate mode
+     UINT32       CTS40MRef:1;  // Response CTS 40MHz duplicate mode
+     UINT32       AutoResponderPreamble:1;    // 0:long, 1:short preamble
+     UINT32       rsv:1;   // Power bit value in conrtrol frame
+     UINT32       DualCTSEn:1;   // Power bit value in conrtrol frame
+     UINT32       AckCtsPsmBit:1;   // Power bit value in conrtrol frame
+     UINT32        :24;
+ } field;
+ UINT32   word;
+} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC;
+#endif
+
+#define LEGACY_BASIC_RATE      0x1408  //  TXRX_CSR5           0x3054
+#define HT_BASIC_RATE          0x140c
+#define HT_CTRL_CFG            0x1410
+#define SIFS_COST_CFG          0x1414
+#define RX_PARSER_CFG          0x1418  //Set NAV for all received frames
+
+//
+//  4.5 MAC Security configuration (offset:0x1500)
+//
+#define TX_SEC_CNT0            0x1500          //
+#define RX_SEC_CNT0            0x1504          //
+#define CCMP_FC_MUTE           0x1508          //
+//
+//  4.6 HCCA/PSMP (offset:0x1600)
+//
+#define TXOP_HLDR_ADDR0                0x1600
+#define TXOP_HLDR_ADDR1                0x1604
+#define TXOP_HLDR_ET           0x1608
+#define QOS_CFPOLL_RA_DW0              0x160c
+#define QOS_CFPOLL_A1_DW1              0x1610
+#define QOS_CFPOLL_QC          0x1614
+//
+//  4.7 MAC Statistis registers (offset:0x1700)
+//
+#define RX_STA_CNT0            0x1700          //
+#define RX_STA_CNT1            0x1704          //
+#define RX_STA_CNT2            0x1708          //
+
+//
+// RX_STA_CNT0_STRUC: RX PLCP error count & RX CRC error count
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _RX_STA_CNT0_STRUC      {
+       struct  {
+           USHORT  PhyErr;
+           USHORT  CrcErr;
+       }       field;
+       UINT32                  word;
+}      RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC;
+#else
+typedef        union   _RX_STA_CNT0_STRUC      {
+       struct  {
+           USHORT  CrcErr;
+           USHORT  PhyErr;
+       }       field;
+       UINT32                  word;
+}      RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC;
+#endif
+
+//
+// RX_STA_CNT1_STRUC: RX False CCA count & RX LONG frame count
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _RX_STA_CNT1_STRUC      {
+       struct  {
+           USHORT  PlcpErr;
+           USHORT  FalseCca;
+       }       field;
+       UINT32                  word;
+}      RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC;
+#else
+typedef        union   _RX_STA_CNT1_STRUC      {
+       struct  {
+           USHORT  FalseCca;
+           USHORT  PlcpErr;
+       }       field;
+       UINT32                  word;
+}      RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC;
+#endif
+
+//
+// RX_STA_CNT2_STRUC:
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _RX_STA_CNT2_STRUC      {
+       struct  {
+           USHORT  RxFifoOverflowCount;
+           USHORT  RxDupliCount;
+       }       field;
+       UINT32                  word;
+}      RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC;
+#else
+typedef        union   _RX_STA_CNT2_STRUC      {
+       struct  {
+           USHORT  RxDupliCount;
+           USHORT  RxFifoOverflowCount;
+       }       field;
+       UINT32                  word;
+}      RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC;
+#endif
+#define TX_STA_CNT0            0x170C          //
+//
+// STA_CSR3: TX Beacon count
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_STA_CNT0_STRUC      {
+       struct  {
+           USHORT  TxBeaconCount;
+           USHORT  TxFailCount;
+       }       field;
+       UINT32                  word;
+}      TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC;
+#else
+typedef        union   _TX_STA_CNT0_STRUC      {
+       struct  {
+           USHORT  TxFailCount;
+           USHORT  TxBeaconCount;
+       }       field;
+       UINT32                  word;
+}      TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC;
+#endif
+#define TX_STA_CNT1            0x1710          //
+//
+// TX_STA_CNT1: TX tx count
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_STA_CNT1_STRUC      {
+       struct  {
+           USHORT  TxRetransmit;
+           USHORT  TxSuccess;
+       }       field;
+       UINT32                  word;
+}      TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC;
+#else
+typedef        union   _TX_STA_CNT1_STRUC      {
+       struct  {
+           USHORT  TxSuccess;
+           USHORT  TxRetransmit;
+       }       field;
+       UINT32                  word;
+}      TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC;
+#endif
+#define TX_STA_CNT2            0x1714          //
+//
+// TX_STA_CNT2: TX tx count
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_STA_CNT2_STRUC      {
+       struct  {
+           USHORT  TxUnderFlowCount;
+           USHORT  TxZeroLenCount;
+       }       field;
+       UINT32                  word;
+}      TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC;
+#else
+typedef        union   _TX_STA_CNT2_STRUC      {
+       struct  {
+           USHORT  TxZeroLenCount;
+           USHORT  TxUnderFlowCount;
+       }       field;
+       UINT32                  word;
+}      TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC;
+#endif
+#define TX_STA_FIFO            0x1718          //
+//
+// TX_STA_FIFO_STRUC: TX Result for specific PID status fifo register
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union PACKED _TX_STA_FIFO_STRUC {
+       struct  {
+               UINT32          Reserve:2;
+               UINT32          TxBF:1; // 3*3
+               UINT32          SuccessRate:13; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16.
+//             UINT32          SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16.
+               UINT32          wcid:8;         //wireless client index
+               UINT32          TxAckRequired:1;    // ack required
+               UINT32          TxAggre:1;    // Tx is aggregated
+               UINT32          TxSuccess:1;   // Tx success. whether success or not
+               UINT32          PidType:4;
+               UINT32          bValid:1;   // 1:This register contains a valid TX result
+       }       field;
+       UINT32                  word;
+}      TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC;
+#else
+typedef        union PACKED _TX_STA_FIFO_STRUC {
+       struct  {
+               UINT32          bValid:1;   // 1:This register contains a valid TX result
+               UINT32          PidType:4;
+               UINT32          TxSuccess:1;   // Tx No retry success
+               UINT32          TxAggre:1;    // Tx Retry Success
+               UINT32          TxAckRequired:1;    // Tx fail
+               UINT32          wcid:8;         //wireless client index
+//             UINT32          SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16.
+               UINT32          SuccessRate:13; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16.
+               UINT32          TxBF:1;
+               UINT32          Reserve:2;
+       }       field;
+       UINT32                  word;
+}      TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC;
+#endif
+// Debug counter
+#define TX_AGG_CNT     0x171c
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_AGG_CNT_STRUC       {
+       struct  {
+           USHORT  AggTxCount;
+           USHORT  NonAggTxCount;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC;
+#else
+typedef        union   _TX_AGG_CNT_STRUC       {
+       struct  {
+           USHORT  NonAggTxCount;
+           USHORT  AggTxCount;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC;
+#endif
+// Debug counter
+#define TX_AGG_CNT0    0x1720
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_AGG_CNT0_STRUC      {
+       struct  {
+           USHORT  AggSize2Count;
+           USHORT  AggSize1Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC;
+#else
+typedef        union   _TX_AGG_CNT0_STRUC      {
+       struct  {
+           USHORT  AggSize1Count;
+           USHORT  AggSize2Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC;
+#endif
+// Debug counter
+#define TX_AGG_CNT1    0x1724
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_AGG_CNT1_STRUC      {
+       struct  {
+           USHORT  AggSize4Count;
+           USHORT  AggSize3Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC;
+#else
+typedef        union   _TX_AGG_CNT1_STRUC      {
+       struct  {
+           USHORT  AggSize3Count;
+           USHORT  AggSize4Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC;
+#endif
+#define TX_AGG_CNT2    0x1728
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_AGG_CNT2_STRUC      {
+       struct  {
+           USHORT  AggSize6Count;
+           USHORT  AggSize5Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC;
+#else
+typedef        union   _TX_AGG_CNT2_STRUC      {
+       struct  {
+           USHORT  AggSize5Count;
+           USHORT  AggSize6Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC;
+#endif
+// Debug counter
+#define TX_AGG_CNT3    0x172c
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_AGG_CNT3_STRUC      {
+       struct  {
+           USHORT  AggSize8Count;
+           USHORT  AggSize7Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC;
+#else
+typedef        union   _TX_AGG_CNT3_STRUC      {
+       struct  {
+           USHORT  AggSize7Count;
+           USHORT  AggSize8Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC;
+#endif
+// Debug counter
+#define TX_AGG_CNT4    0x1730
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_AGG_CNT4_STRUC      {
+       struct  {
+           USHORT  AggSize10Count;
+           USHORT  AggSize9Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC;
+#else
+typedef        union   _TX_AGG_CNT4_STRUC      {
+       struct  {
+           USHORT  AggSize9Count;
+           USHORT  AggSize10Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC;
+#endif
+#define TX_AGG_CNT5    0x1734
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_AGG_CNT5_STRUC      {
+       struct  {
+           USHORT  AggSize12Count;
+           USHORT  AggSize11Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC;
+#else
+typedef        union   _TX_AGG_CNT5_STRUC      {
+       struct  {
+           USHORT  AggSize11Count;
+           USHORT  AggSize12Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC;
+#endif
+#define TX_AGG_CNT6            0x1738
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_AGG_CNT6_STRUC      {
+       struct  {
+           USHORT  AggSize14Count;
+           USHORT  AggSize13Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC;
+#else
+typedef        union   _TX_AGG_CNT6_STRUC      {
+       struct  {
+           USHORT  AggSize13Count;
+           USHORT  AggSize14Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC;
+#endif
+#define TX_AGG_CNT7            0x173c
+#ifdef RT_BIG_ENDIAN
+typedef        union   _TX_AGG_CNT7_STRUC      {
+       struct  {
+           USHORT  AggSize16Count;
+           USHORT  AggSize15Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC;
+#else
+typedef        union   _TX_AGG_CNT7_STRUC      {
+       struct  {
+           USHORT  AggSize15Count;
+           USHORT  AggSize16Count;
+       }       field;
+       UINT32                  word;
+}      TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC;
+#endif
+#define MPDU_DENSITY_CNT               0x1740
+#ifdef RT_BIG_ENDIAN
+typedef        union   _MPDU_DEN_CNT_STRUC     {
+       struct  {
+           USHORT  RXZeroDelCount;     //RX zero length delimiter count
+           USHORT  TXZeroDelCount;     //TX zero length delimiter count
+       }       field;
+       UINT32                  word;
+}      MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC;
+#else
+typedef        union   _MPDU_DEN_CNT_STRUC     {
+       struct  {
+           USHORT  TXZeroDelCount;     //TX zero length delimiter count
+           USHORT  RXZeroDelCount;     //RX zero length delimiter count
+       }       field;
+       UINT32                  word;
+}      MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC;
+#endif
+//
+// TXRX control registers - base address 0x3000
+//
+// rt2860b  UNKNOWN reg use R/O Reg Addr 0x77d0 first..
+#define TXRX_CSR1           0x77d0
+
+//
+// Security key table memory, base address = 0x1000
+//
+#define MAC_WCID_BASE          0x1800 //8-bytes(use only 6-bytes) * 256 entry =
+#define HW_WCID_ENTRY_SIZE   8
+#define PAIRWISE_KEY_TABLE_BASE     0x4000      // 32-byte * 256-entry =  -byte
+#define HW_KEY_ENTRY_SIZE           0x20
+#define PAIRWISE_IVEIV_TABLE_BASE     0x6000      // 8-byte * 256-entry =  -byte
+#define MAC_IVEIV_TABLE_BASE     0x6000      // 8-byte * 256-entry =  -byte
+#define HW_IVEIV_ENTRY_SIZE   8
+#define MAC_WCID_ATTRIBUTE_BASE     0x6800      // 4-byte * 256-entry =  -byte
+#define HW_WCID_ATTRI_SIZE   4
+#define WCID_RESERVED                          0x6bfc
+#define SHARED_KEY_TABLE_BASE       0x6c00      // 32-byte * 16-entry = 512-byte
+#define SHARED_KEY_MODE_BASE       0x7000      // 32-byte * 16-entry = 512-byte
+#define HW_SHARED_KEY_MODE_SIZE   4
+#define SHAREDKEYTABLE                 0
+#define PAIRWISEKEYTABLE                       1
+
+
+#ifdef RT_BIG_ENDIAN
+typedef        union   _SHAREDKEY_MODE_STRUC   {
+       struct  {
+               UINT32       :1;
+               UINT32       Bss1Key3CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss1Key2CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss1Key1CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss1Key0CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss0Key3CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss0Key2CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss0Key1CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss0Key0CipherAlg:3;
+       }       field;
+       UINT32                  word;
+}      SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC;
+#else
+typedef        union   _SHAREDKEY_MODE_STRUC   {
+       struct  {
+               UINT32       Bss0Key0CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss0Key1CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss0Key2CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss0Key3CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss1Key0CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss1Key1CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss1Key2CipherAlg:3;
+               UINT32       :1;
+               UINT32       Bss1Key3CipherAlg:3;
+               UINT32       :1;
+       }       field;
+       UINT32                  word;
+}      SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC;
+#endif
+// 64-entry for pairwise key table
+typedef struct _HW_WCID_ENTRY {  // 8-byte per entry
+    UCHAR   Address[6];
+    UCHAR   Rsv[2];
+} HW_WCID_ENTRY, PHW_WCID_ENTRY;
+
+
+
+//
+// Other on-chip shared memory space, base = 0x2000
+//
+
+// CIS space - base address = 0x2000
+#define HW_CIS_BASE             0x2000
+
+// Carrier-sense CTS frame base address. It's where mac stores carrier-sense frame for carrier-sense function.
+#define HW_CS_CTS_BASE                 0x7700
+// DFS CTS frame base address. It's where mac stores CTS frame for DFS.
+#define HW_DFS_CTS_BASE                        0x7780
+#define HW_CTS_FRAME_SIZE              0x80
+
+// 2004-11-08 john - since NULL frame won't be that long (256 byte). We steal 16 tail bytes
+// to save debugging settings
+#define HW_DEBUG_SETTING_BASE   0x77f0  // 0x77f0~0x77ff total 16 bytes
+#define HW_DEBUG_SETTING_BASE2   0x7770  // 0x77f0~0x77ff total 16 bytes
+
+#if 0
+// on-chip BEACON frame space - base address = 0x7800
+#define HW_BEACON_MAX_SIZE      0x0800 /* unit: byte */
+#define HW_BEACON_BASE0         0x7800
+#define HW_BEACON_BASE1         0x7900
+#define HW_BEACON_BASE2         0x7a00
+#define HW_BEACON_BASE3         0x7b00
+#define HW_BEACON_BASE4         0x7c00
+#define HW_BEACON_BASE5         0x7d00
+#define HW_BEACON_BASE6         0x7e00
+#define HW_BEACON_BASE7         0x7f00
+/* 1. HW_BEACON_OFFSET/64B must be 0;
+   2. BCN_OFFSET0 must also be changed in NICInitializeAsic();
+   3. max 0x0800 for 8 beacon frames; */
+#else
+// In order to support maximum 8 MBSS and its maximum length is 512 for each beacon
+// Three section discontinue memory segments will be used.
+// 1. The original region for BCN 0~3
+// 2. Extract memory from FCE table for BCN 4~5
+// 3. Extract memory from Pair-wise key table for BCN 6~7
+//       It occupied those memory of wcid 238~253 for BCN 6
+//                                                   and wcid 222~237 for BCN 7
+#define HW_BEACON_MAX_SIZE      0x1000 /* unit: byte */
+#define HW_BEACON_BASE0         0x7800
+#define HW_BEACON_BASE1         0x7A00
+#define HW_BEACON_BASE2         0x7C00
+#define HW_BEACON_BASE3         0x7E00
+#define HW_BEACON_BASE4         0x7200
+#define HW_BEACON_BASE5         0x7400
+#define HW_BEACON_BASE6         0x5DC0
+#define HW_BEACON_BASE7         0x5BC0
+#endif
+
+#define HW_BEACON_MAX_COUNT     8
+#define HW_BEACON_OFFSET               0x0200
+#define HW_BEACON_CONTENT_LEN  (HW_BEACON_OFFSET - TXWI_SIZE)
+
+// HOST-MCU shared memory - base address = 0x2100
+#define HOST_CMD_CSR           0x404
+#define H2M_MAILBOX_CSR         0x7010
+#define H2M_MAILBOX_CID         0x7014
+#define H2M_MAILBOX_STATUS      0x701c
+#define H2M_INT_SRC             0x7024
+#define H2M_BBP_AGENT           0x7028
+#define M2H_CMD_DONE_CSR        0x000c
+#define MCU_TXOP_ARRAY_BASE     0x000c   // TODO: to be provided by Albert
+#define MCU_TXOP_ENTRY_SIZE     32       // TODO: to be provided by Albert
+#define MAX_NUM_OF_TXOP_ENTRY   16       // TODO: must be same with 8051 firmware
+#define MCU_MBOX_VERSION        0x01     // TODO: to be confirmed by Albert
+#define MCU_MBOX_VERSION_OFFSET 5        // TODO: to be provided by Albert
+
+//
+// Host DMA registers - base address 0x200 .  TX0-3=EDCAQid0-3, TX4=HCCA, TX5=MGMT,
+//
+//
+//  DMA RING DESCRIPTOR
+//
+#define E2PROM_CSR          0x0004
+#define IO_CNTL_CSR         0x77d0
+
+#ifdef RT2870
+// 8051 firmware image for usb - use last-half base address = 0x3000
+#define FIRMWARE_IMAGE_BASE     0x3000
+#define MAX_FIRMWARE_IMAGE_SIZE 0x1000    // 4kbyte
+#endif // RT2870 //
+
+// TODO: ????? old RT2560 registers. to keep them or remove them?
+//#define MCAST0                  0x0178  // multicast filter register 0
+//#define MCAST1                  0x017c  // multicast filter register 1
+
+
+// ================================================================
+// Tx /        Rx / Mgmt ring descriptor definition
+// ================================================================
+
+// the following PID values are used to mark outgoing frame type in TXD->PID so that
+// proper TX statistics can be collected based on these categories
+// b3-2 of PID field -
+#define PID_MGMT                       0x05
+#define PID_BEACON                     0x0c
+#define PID_DATA_NORMALUCAST           0x02
+#define PID_DATA_AMPDU         0x04
+#define PID_DATA_NO_ACK        0x08
+#define PID_DATA_NOT_NORM_ACK          0x03
+#if 0
+#define PTYPE_DATA_REQUIRE_ACK  0x00 // b7-6:00, b5-0: 0~59 is MAC table index (AID?), 60~63 is WDS index
+#define PTYPE_NULL_AT_HIGH_RATE 0x04 // b7-6:01, b5-0: 0~59 is MAC table index (AID?), 60~63 is WDS index
+#define PTYPE_RESERVED          0x08 // b7-6:10
+#define PTYPE_SPECIAL           0x0c // b7-6:11
+
+// when b3-2=11 (PTYPE_SPECIAL), b1-0 coube be ...
+#define PSUBTYPE_DATA_NO_ACK    0x00
+#define PSUBTYPE_MGMT           0x01
+#define PSUBTYPE_OTHER_CNTL     0x02
+#define PSUBTYPE_RTS            0x03
+#endif
+// value domain of pTxD->HostQId (4-bit: 0~15)
+#define QID_AC_BK               1   // meet ACI definition in 802.11e
+#define QID_AC_BE               0   // meet ACI definition in 802.11e
+#define QID_AC_VI               2
+#define QID_AC_VO               3
+#define QID_HCCA                4
+#define NUM_OF_TX_RING          5
+#define QID_MGMT                13
+#define QID_RX                  14
+#define QID_OTHER               15
+
+
+// ------------------------------------------------------
+// BBP & RF    definition
+// ------------------------------------------------------
+#define        BUSY                            1
+#define        IDLE                            0
+
+#define        RF_R00                                      0
+#define        RF_R01                                      1
+#define        RF_R02                                      2
+#define        RF_R03                                      3
+#define        RF_R04                                      4
+#define        RF_R05                                      5
+#define        RF_R06                                      6
+#define        RF_R07                                      7
+#define        RF_R08                                      8
+#define        RF_R09                                      9
+#define        RF_R10                                      10
+#define        RF_R11                                      11
+#define        RF_R12                                      12
+#define        RF_R13                                      13
+#define        RF_R14                                      14
+#define        RF_R15                                      15
+#define        RF_R16                                      16
+#define        RF_R17                                      17
+#define        RF_R18                                      18
+#define        RF_R19                                      19
+#define        RF_R20                                      20
+#define        RF_R21                                      21
+#define        RF_R22                                      22
+#define        RF_R23                                      23
+#define        RF_R24                                      24
+#define        RF_R25                                      25
+#define        RF_R26                                      26
+#define        RF_R27                                      27
+#define        RF_R28                                      28
+#define        RF_R29                                      29
+#define        RF_R30                                      30
+#define        RF_R31                                      31
+
+#define        BBP_R0                                      0  // version
+#define        BBP_R1                                  1  // TSSI
+#define        BBP_R2                                  2  // TX configure
+#define BBP_R3                      3
+#define BBP_R4                      4
+#define BBP_R5                      5
+#define BBP_R6                      6
+#define        BBP_R14                             14 // RX configure
+#define BBP_R16                     16
+#define BBP_R17                     17 // RX sensibility
+#define BBP_R18                     18
+#define BBP_R21                     21
+#define BBP_R22                     22
+#define BBP_R24                     24
+#define BBP_R25                     25
+#define BBP_R49                     49 //TSSI
+#define BBP_R50                     50
+#define BBP_R51                     51
+#define BBP_R52                     52
+#define BBP_R55                     55
+#define BBP_R62                     62 // Rx SQ0 Threshold HIGH
+#define BBP_R63                     63
+#define BBP_R64                     64
+#define BBP_R65                     65
+#define BBP_R66                     66
+#define BBP_R67                     67
+#define BBP_R68                     68
+#define BBP_R69                     69
+#define BBP_R70                     70 // Rx AGC SQ CCK Xcorr threshold
+#define BBP_R73                     73
+#define BBP_R75                                                75
+#define BBP_R77                     77
+#define BBP_R81                     81
+#define BBP_R82                     82
+#define BBP_R83                     83
+#define BBP_R84                     84
+#define BBP_R86                                                86
+#define BBP_R91                                                91
+#define BBP_R92                                                92
+#define BBP_R94                     94 // Tx Gain Control
+#define BBP_R103                    103
+#define BBP_R105                    105
+#define BBP_R113                    113
+#define BBP_R114                    114
+#define BBP_R115                    115
+#define BBP_R116                    116
+#define BBP_R117                    117
+#define BBP_R118                    118
+#define BBP_R119                    119
+#define BBP_R120                    120
+#define BBP_R121                    121
+#define BBP_R122                    122
+#define BBP_R123                    123
+
+
+#define BBPR94_DEFAULT              0x06 // Add 1 value will gain 1db
+
+//#define PHY_TR_SWITCH_TIME          5  // usec
+
+//#define BBP_R17_LOW_SENSIBILITY     0x50
+//#define BBP_R17_MID_SENSIBILITY     0x41
+//#define BBP_R17_DYNAMIC_UP_BOUND    0x40
+#define RSSI_FOR_VERY_LOW_SENSIBILITY -35
+#define RSSI_FOR_LOW_SENSIBILITY      -58
+#define RSSI_FOR_MID_LOW_SENSIBILITY  -80
+#define RSSI_FOR_MID_SENSIBILITY      -90
+
+//-------------------------------------------------------------------------
+// EEPROM definition
+//-------------------------------------------------------------------------
+#define EEDO                        0x08
+#define EEDI                        0x04
+#define EECS                        0x02
+#define EESK                        0x01
+#define EERL                        0x80
+
+#define EEPROM_WRITE_OPCODE         0x05
+#define EEPROM_READ_OPCODE          0x06
+#define EEPROM_EWDS_OPCODE          0x10
+#define EEPROM_EWEN_OPCODE          0x13
+
+#define        NUM_EEPROM_BBP_PARMS            19                      // Include NIC Config 0, 1, CR, TX ALC step, BBPs
+#define        NUM_EEPROM_TX_G_PARMS           7
+#define        EEPROM_NIC1_OFFSET          0x34                // The address is from NIC config 0, not BBP register ID
+#define        EEPROM_NIC2_OFFSET          0x36                // The address is from NIC config 0, not BBP register ID
+#define        EEPROM_BBP_BASE_OFFSET          0xf0            // The address is from NIC config 0, not BBP register ID
+#define        EEPROM_G_TX_PWR_OFFSET          0x52
+#define        EEPROM_G_TX2_PWR_OFFSET         0x60
+#define EEPROM_LED1_OFFSET                     0x3c
+#define EEPROM_LED2_OFFSET                     0x3e
+#define EEPROM_LED3_OFFSET                     0x40
+#define EEPROM_LNA_OFFSET                      0x44
+#define EEPROM_RSSI_BG_OFFSET          0x46
+#define EEPROM_RSSI_A_OFFSET           0x4a
+#define EEPROM_DEFINE_MAX_TXPWR                0x4e
+#define EEPROM_TXPOWER_BYRATE_20MHZ_2_4G       0xde    // 20MHZ 2.4G tx power.
+#define EEPROM_TXPOWER_BYRATE_40MHZ_2_4G       0xee    // 40MHZ 2.4G tx power.
+#define EEPROM_TXPOWER_BYRATE_20MHZ_5G         0xfa    // 20MHZ 5G tx power.
+#define EEPROM_TXPOWER_BYRATE_40MHZ_5G         0x10a   // 40MHZ 5G tx power.
+#define EEPROM_A_TX_PWR_OFFSET      0x78
+#define EEPROM_A_TX2_PWR_OFFSET      0xa6
+//#define EEPROM_Japan_TX_PWR_OFFSET      0x90 // 802.11j
+//#define EEPROM_Japan_TX2_PWR_OFFSET      0xbe
+//#define EEPROM_TSSI_REF_OFFSET       0x54
+//#define EEPROM_TSSI_DELTA_OFFSET     0x24
+//#define EEPROM_CCK_TX_PWR_OFFSET  0x62
+//#define EEPROM_CALIBRATE_OFFSET      0x7c
+#define EEPROM_VERSION_OFFSET       0x02
+#define        EEPROM_FREQ_OFFSET                      0x3a
+#define EEPROM_TXPOWER_BYRATE  0xde    // 20MHZ power.
+#define EEPROM_TXPOWER_DELTA           0x50    // 20MHZ AND 40 MHZ use different power. This is delta in 40MHZ.
+#define VALID_EEPROM_VERSION        1
+
+// PairKeyMode definition
+#define PKMODE_NONE                 0
+#define PKMODE_WEP64                1
+#define PKMODE_WEP128               2
+#define PKMODE_TKIP                 3
+#define PKMODE_AES                  4
+#define PKMODE_CKIP64               5
+#define PKMODE_CKIP128              6
+#define PKMODE_TKIP_NO_MIC          7       // MIC appended by driver: not a valid value in hardware key table
+
+// =================================================================================
+// WCID  format
+// =================================================================================
+//7.1  WCID  ENTRY  format  : 8bytes
+typedef        struct  _WCID_ENTRY_STRUC {
+       UCHAR           RXBABitmap7;    // bit0 for TID8, bit7 for TID 15
+       UCHAR           RXBABitmap0;    // bit0 for TID0, bit7 for TID 7
+       UCHAR           MAC[6]; // 0 for shared key table.  1 for pairwise key table
+}      WCID_ENTRY_STRUC, *PWCID_ENTRY_STRUC;
+
+//8.1.1        SECURITY  KEY  format  : 8DW
+// 32-byte per entry, total 16-entry for shared key table, 64-entry for pairwise key table
+typedef struct _HW_KEY_ENTRY {          // 32-byte per entry
+    UCHAR   Key[16];
+    UCHAR   TxMic[8];
+    UCHAR   RxMic[8];
+} HW_KEY_ENTRY, *PHW_KEY_ENTRY;
+
+//8.1.2        IV/EIV  format  : 2DW
+
+//8.1.3        RX attribute entry format  : 1DW
+#ifdef RT_BIG_ENDIAN
+typedef        struct  _MAC_ATTRIBUTE_STRUC {
+       UINT32          rsv:22;
+       UINT32          RXWIUDF:3;
+       UINT32          BSSIDIdx:3; //multipleBSS index for the WCID
+       UINT32          PairKeyMode:3;
+       UINT32          KeyTab:1;       // 0 for shared key table.  1 for pairwise key table
+}      MAC_ATTRIBUTE_STRUC, *PMAC_ATTRIBUTE_STRUC;
+#else
+typedef        struct  _MAC_ATTRIBUTE_STRUC {
+       UINT32          KeyTab:1;       // 0 for shared key table.  1 for pairwise key table
+       UINT32          PairKeyMode:3;
+       UINT32          BSSIDIdx:3; //multipleBSS index for the WCID
+       UINT32          RXWIUDF:3;
+       UINT32          rsv:22;
+}      MAC_ATTRIBUTE_STRUC, *PMAC_ATTRIBUTE_STRUC;
+#endif
+
+
+// =================================================================================
+// TX / RX ring descriptor format
+// =================================================================================
+
+// the first 24-byte in TXD is called TXINFO and will be DMAed to MAC block through TXFIFO.
+// MAC block use this TXINFO to control the transmission behavior of this frame.
+#define FIFO_MGMT                 0
+#define FIFO_HCCA                 1
+#define FIFO_EDCA                 2
+
+//
+// TX descriptor format, Tx    ring, Mgmt Ring
+//
+#ifdef RT_BIG_ENDIAN
+typedef        struct  PACKED _TXD_STRUC {
+       // Word 0
+       UINT32          SDPtr0;
+       // Word 1
+       UINT32          DMADONE:1;
+       UINT32          LastSec0:1;
+       UINT32          SDLen0:14;
+       UINT32          Burst:1;
+       UINT32          LastSec1:1;
+       UINT32          SDLen1:14;
+       // Word 2
+       UINT32          SDPtr1;
+       // Word 3
+       UINT32          ICO:1;
+       UINT32          UCO:1;
+       UINT32          TCO:1;
+       UINT32          rsv:2;
+       UINT32          QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA
+       UINT32          WIV:1;  // Wireless Info Valid. 1 if Driver already fill WI,  o if DMA needs to copy WI to correctposition
+       UINT32          rsv2:24;
+}      TXD_STRUC, *PTXD_STRUC;
+#else
+typedef        struct  PACKED _TXD_STRUC {
+       // Word 0
+       UINT32          SDPtr0;
+       // Word 1
+       UINT32          SDLen1:14;
+       UINT32          LastSec1:1;
+       UINT32          Burst:1;
+       UINT32          SDLen0:14;
+       UINT32          LastSec0:1;
+       UINT32          DMADONE:1;
+       //Word2
+       UINT32          SDPtr1;
+       //Word3
+       UINT32          rsv2:24;
+       UINT32          WIV:1;  // Wireless Info Valid. 1 if Driver already fill WI,  o if DMA needs to copy WI to correctposition
+       UINT32          QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA
+       UINT32          rsv:2;
+       UINT32          TCO:1;  //
+       UINT32          UCO:1;  //
+       UINT32          ICO:1;  //
+}      TXD_STRUC, *PTXD_STRUC;
+#endif
+
+
+//
+// TXD Wireless Information format for Tx ring and Mgmt Ring
+//
+//txop : for txop mode
+// 0:txop for the MPDU frame will be handles by ASIC by register
+// 1/2/3:the MPDU frame is send after PIFS/backoff/SIFS
+#ifdef RT_BIG_ENDIAN
+typedef        struct  PACKED _TXWI_STRUC {
+       // Word 0
+       UINT32          PHYMODE:2;
+       UINT32          TxBF:1; // 3*3
+       UINT32          rsv2:1;
+//     UINT32          rsv2:2;
+       UINT32          Ifs:1;  //
+       UINT32          STBC:2; //channel bandwidth 20MHz or 40 MHz
+       UINT32          ShortGI:1;
+       UINT32          BW:1;   //channel bandwidth 20MHz or 40 MHz
+       UINT32          MCS:7;
+
+       UINT32          rsv:6;
+       UINT32          txop:2; //tx back off mode 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful.
+       UINT32          MpduDensity:3;
+       UINT32          AMPDU:1;
+
+       UINT32          TS:1;
+       UINT32          CFACK:1;
+       UINT32          MIMOps:1;       // the remote peer is in dynamic MIMO-PS mode
+       UINT32          FRAG:1;         // 1 to inform TKIP engine this is a fragment.
+       // Word 1
+       UINT32          PacketId:4;
+       UINT32          MPDUtotalByteCount:12;
+       UINT32          WirelessCliID:8;
+       UINT32          BAWinSize:6;
+       UINT32          NSEQ:1;
+       UINT32          ACK:1;
+       // Word 2
+       UINT32          IV;
+       // Word 3
+       UINT32          EIV;
+}      TXWI_STRUC, *PTXWI_STRUC;
+#else
+typedef        struct  PACKED _TXWI_STRUC {
+       // Word 0
+       UINT32          FRAG:1;         // 1 to inform TKIP engine this is a fragment.
+       UINT32          MIMOps:1;       // the remote peer is in dynamic MIMO-PS mode
+       UINT32          CFACK:1;
+       UINT32          TS:1;
+
+       UINT32          AMPDU:1;
+       UINT32          MpduDensity:3;
+       UINT32          txop:2; //FOR "THIS" frame. 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful.
+       UINT32          rsv:6;
+
+       UINT32          MCS:7;
+       UINT32          BW:1;   //channel bandwidth 20MHz or 40 MHz
+       UINT32          ShortGI:1;
+       UINT32          STBC:2; // 1: STBC support MCS =0-7,   2,3 : RESERVE
+       UINT32          Ifs:1;  //
+//     UINT32          rsv2:2; //channel bandwidth 20MHz or 40 MHz
+       UINT32          rsv2:1;
+       UINT32          TxBF:1; // 3*3
+       UINT32          PHYMODE:2;
+       // Word 1
+       UINT32          ACK:1;
+       UINT32          NSEQ:1;
+       UINT32          BAWinSize:6;
+       UINT32          WirelessCliID:8;
+       UINT32          MPDUtotalByteCount:12;
+       UINT32          PacketId:4;
+       //Word2
+       UINT32          IV;
+       //Word3
+       UINT32          EIV;
+}      TXWI_STRUC, *PTXWI_STRUC;
+#endif
+//
+// Rx descriptor format, Rx    Ring
+//
+//
+// RXWI wireless information format, in PBF. invisible in driver.
+//
+#ifdef RT_BIG_ENDIAN
+typedef        struct  PACKED _RXWI_STRUC {
+       // Word 0
+       UINT32          TID:4;
+       UINT32          MPDUtotalByteCount:12;
+       UINT32          UDF:3;
+       UINT32          BSSID:3;
+       UINT32          KeyIndex:2;
+       UINT32          WirelessCliID:8;
+       // Word 1
+       UINT32          PHYMODE:2;              // 1: this RX frame is unicast to me
+       UINT32          rsv:3;
+       UINT32          STBC:2;
+       UINT32          ShortGI:1;
+       UINT32          BW:1;
+       UINT32          MCS:7;
+       UINT32          SEQUENCE:12;
+       UINT32          FRAG:4;
+       // Word 2
+       UINT32          rsv1:8;
+       UINT32          RSSI2:8;
+       UINT32          RSSI1:8;
+       UINT32          RSSI0:8;
+       // Word 3
+       UINT32          rsv2:16;
+       UINT32          SNR1:8;
+       UINT32          SNR0:8;
+}      RXWI_STRUC, *PRXWI_STRUC;
+#else
+typedef        struct  PACKED _RXWI_STRUC {
+       // Word 0
+       UINT32          WirelessCliID:8;
+       UINT32          KeyIndex:2;
+       UINT32          BSSID:3;
+       UINT32          UDF:3;
+       UINT32          MPDUtotalByteCount:12;
+       UINT32          TID:4;
+       // Word 1
+       UINT32          FRAG:4;
+       UINT32          SEQUENCE:12;
+       UINT32          MCS:7;
+       UINT32          BW:1;
+       UINT32          ShortGI:1;
+       UINT32          STBC:2;
+       UINT32          rsv:3;
+       UINT32          PHYMODE:2;              // 1: this RX frame is unicast to me
+       //Word2
+       UINT32          RSSI0:8;
+       UINT32          RSSI1:8;
+       UINT32          RSSI2:8;
+       UINT32          rsv1:8;
+       //Word3
+       UINT32          SNR0:8;
+       UINT32          SNR1:8;
+       UINT32          rsv2:16;
+}      RXWI_STRUC, *PRXWI_STRUC;
+#endif
+
+
+// =================================================================================
+// HOST-MCU communication data structure
+// =================================================================================
+
+//
+// H2M_MAILBOX_CSR: Host-to-MCU Mailbox
+//
+#ifdef RT_BIG_ENDIAN
+typedef union  _H2M_MAILBOX_STRUC {
+    struct {
+        UINT32       Owner:8;
+        UINT32       CmdToken:8;    // 0xff tells MCU not to report CmdDoneInt after excuting the command
+        UINT32       HighByte:8;
+        UINT32       LowByte:8;
+    }   field;
+    UINT32           word;
+} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC;
+#else
+typedef union  _H2M_MAILBOX_STRUC {
+    struct {
+        UINT32       LowByte:8;
+        UINT32       HighByte:8;
+        UINT32       CmdToken:8;
+        UINT32       Owner:8;
+    }   field;
+    UINT32           word;
+} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC;
+#endif
+
+//
+// M2H_CMD_DONE_CSR: MCU-to-Host command complete indication
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _M2H_CMD_DONE_STRUC {
+    struct  {
+        UINT32       CmdToken3;
+        UINT32       CmdToken2;
+        UINT32       CmdToken1;
+        UINT32       CmdToken0;
+    } field;
+    UINT32           word;
+} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC;
+#else
+typedef union _M2H_CMD_DONE_STRUC {
+    struct  {
+        UINT32       CmdToken0;
+        UINT32       CmdToken1;
+        UINT32       CmdToken2;
+        UINT32       CmdToken3;
+    } field;
+    UINT32           word;
+} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC;
+#endif
+
+
+
+//
+// MCU_LEDCS: MCU LED Control Setting.
+//
+#ifdef RT_BIG_ENDIAN
+typedef union  _MCU_LEDCS_STRUC {
+       struct  {
+               UCHAR           Polarity:1;
+               UCHAR           LedMode:7;
+       } field;
+       UCHAR                           word;
+} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC;
+#else
+typedef union  _MCU_LEDCS_STRUC {
+       struct  {
+               UCHAR           LedMode:7;
+               UCHAR           Polarity:1;
+       } field;
+       UCHAR                   word;
+} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC;
+#endif
+// =================================================================================
+// Register format
+// =================================================================================
+
+
+
+//NAV_TIME_CFG :NAV
+#ifdef RT_BIG_ENDIAN
+typedef        union   _NAV_TIME_CFG_STRUC     {
+       struct  {
+               USHORT          rsv:6;
+               USHORT          ZeroSifs:1;               // Applied zero SIFS timer after OFDM RX 0: disable
+               USHORT          Eifs:9;               // in unit of 1-us
+               UCHAR       SlotTime;    // in unit of 1-us
+               UCHAR           Sifs;               // in unit of 1-us
+       }       field;
+       UINT32                  word;
+}      NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC;
+#else
+typedef        union   _NAV_TIME_CFG_STRUC     {
+       struct  {
+               UCHAR           Sifs;               // in unit of 1-us
+               UCHAR       SlotTime;    // in unit of 1-us
+               USHORT          Eifs:9;               // in unit of 1-us
+               USHORT          ZeroSifs:1;               // Applied zero SIFS timer after OFDM RX 0: disable
+               USHORT          rsv:6;
+       }       field;
+       UINT32                  word;
+}      NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC;
+#endif
+
+
+
+
+
+//
+// RX_FILTR_CFG:  /RX configuration register
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   RX_FILTR_CFG_STRUC      {
+       struct  {
+               UINT32          :15;
+               UINT32       DropRsvCntlType:1;
+
+               UINT32          DropBAR:1;       //
+               UINT32          DropBA:1;               //
+               UINT32          DropPsPoll:1;           // Drop Ps-Poll
+               UINT32          DropRts:1;              // Drop Ps-Poll
+
+               UINT32          DropCts:1;              // Drop Ps-Poll
+               UINT32          DropAck:1;              // Drop Ps-Poll
+               UINT32          DropCFEnd:1;            // Drop Ps-Poll
+               UINT32          DropCFEndAck:1;         // Drop Ps-Poll
+
+               UINT32          DropDuplicate:1;                // Drop duplicate frame
+               UINT32          DropBcast:1;            // Drop broadcast frames
+               UINT32          DropMcast:1;            // Drop multicast frames
+               UINT32          DropVerErr:1;       // Drop version error frame
+
+               UINT32          DropNotMyBSSID:1;                       // Drop fram ToDs bit is true
+               UINT32          DropNotToMe:1;          // Drop not to me unicast frame
+               UINT32          DropPhyErr:1;           // Drop physical error
+               UINT32          DropCRCErr:1;           // Drop CRC error
+       }       field;
+       UINT32                  word;
+}      RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC;
+#else
+typedef        union   _RX_FILTR_CFG_STRUC     {
+       struct  {
+               UINT32          DropCRCErr:1;           // Drop CRC error
+               UINT32          DropPhyErr:1;           // Drop physical error
+               UINT32          DropNotToMe:1;          // Drop not to me unicast frame
+               UINT32          DropNotMyBSSID:1;                       // Drop fram ToDs bit is true
+
+               UINT32          DropVerErr:1;       // Drop version error frame
+               UINT32          DropMcast:1;            // Drop multicast frames
+               UINT32          DropBcast:1;            // Drop broadcast frames
+               UINT32          DropDuplicate:1;                // Drop duplicate frame
+
+               UINT32          DropCFEndAck:1;         // Drop Ps-Poll
+               UINT32          DropCFEnd:1;            // Drop Ps-Poll
+               UINT32          DropAck:1;              // Drop Ps-Poll
+               UINT32          DropCts:1;              // Drop Ps-Poll
+
+               UINT32          DropRts:1;              // Drop Ps-Poll
+               UINT32          DropPsPoll:1;           // Drop Ps-Poll
+               UINT32          DropBA:1;               //
+               UINT32          DropBAR:1;       //
+
+               UINT32          DropRsvCntlType:1;
+               UINT32          :15;
+       }       field;
+       UINT32                  word;
+}      RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC;
+#endif
+
+
+
+
+//
+// PHY_CSR4: RF serial control register
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _PHY_CSR4_STRUC {
+       struct  {
+               UINT32          Busy:1;                         // 1: ASIC is busy execute RF programming.
+               UINT32          PLL_LD:1;                       // RF PLL_LD status
+               UINT32          IFSelect:1;                     // 1: select IF to program,     0: select RF to program
+               UINT32          NumberOfBits:5;         // Number of bits used in RFRegValue (I:20,     RFMD:22)
+               UINT32          RFRegValue:24;          // Register     value (include register id)     serial out to RF/IF     chip.
+       }       field;
+       UINT32                  word;
+}      PHY_CSR4_STRUC, *PPHY_CSR4_STRUC;
+#else
+typedef        union   _PHY_CSR4_STRUC {
+       struct  {
+               UINT32          RFRegValue:24;          // Register     value (include register id)     serial out to RF/IF     chip.
+               UINT32          NumberOfBits:5;         // Number of bits used in RFRegValue (I:20,     RFMD:22)
+               UINT32          IFSelect:1;                     // 1: select IF to program,     0: select RF to program
+               UINT32          PLL_LD:1;                       // RF PLL_LD status
+               UINT32          Busy:1;                         // 1: ASIC is busy execute RF programming.
+       }       field;
+       UINT32                  word;
+}      PHY_CSR4_STRUC, *PPHY_CSR4_STRUC;
+#endif
+
+
+//
+// SEC_CSR5: shared key table security mode register
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _SEC_CSR5_STRUC {
+       struct  {
+        UINT32       :1;
+        UINT32       Bss3Key3CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss3Key2CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss3Key1CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss3Key0CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss2Key3CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss2Key2CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss2Key1CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss2Key0CipherAlg:3;
+       }       field;
+       UINT32                  word;
+}      SEC_CSR5_STRUC, *PSEC_CSR5_STRUC;
+#else
+typedef        union   _SEC_CSR5_STRUC {
+       struct  {
+        UINT32       Bss2Key0CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss2Key1CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss2Key2CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss2Key3CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss3Key0CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss3Key1CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss3Key2CipherAlg:3;
+        UINT32       :1;
+        UINT32       Bss3Key3CipherAlg:3;
+        UINT32       :1;
+       }       field;
+       UINT32                  word;
+}      SEC_CSR5_STRUC, *PSEC_CSR5_STRUC;
+#endif
+
+
+//
+// HOST_CMD_CSR: For HOST to interrupt embedded processor
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _HOST_CMD_CSR_STRUC     {
+       struct  {
+           UINT32   Rsv:24;
+           UINT32   HostCommand:8;
+       }       field;
+       UINT32                  word;
+}      HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC;
+#else
+typedef        union   _HOST_CMD_CSR_STRUC     {
+       struct  {
+           UINT32   HostCommand:8;
+           UINT32   Rsv:24;
+       }       field;
+       UINT32                  word;
+}      HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC;
+#endif
+
+
+//
+// AIFSN_CSR: AIFSN for each EDCA AC
+//
+
+
+
+//
+// E2PROM_CSR: EEPROM control register
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _E2PROM_CSR_STRUC       {
+       struct  {
+               UINT32          Rsvd:25;
+               UINT32       LoadStatus:1;   // 1:loading, 0:done
+               UINT32          Type:1;                 // 1: 93C46, 0:93C66
+               UINT32          EepromDO:1;
+               UINT32          EepromDI:1;
+               UINT32          EepromCS:1;
+               UINT32          EepromSK:1;
+               UINT32          Reload:1;               // Reload EEPROM content, write one to reload, self-cleared.
+       }       field;
+       UINT32                  word;
+}      E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC;
+#else
+typedef        union   _E2PROM_CSR_STRUC       {
+       struct  {
+               UINT32          Reload:1;               // Reload EEPROM content, write one to reload, self-cleared.
+               UINT32          EepromSK:1;
+               UINT32          EepromCS:1;
+               UINT32          EepromDI:1;
+               UINT32          EepromDO:1;
+               UINT32          Type:1;                 // 1: 93C46, 0:93C66
+               UINT32       LoadStatus:1;   // 1:loading, 0:done
+               UINT32          Rsvd:25;
+       }       field;
+       UINT32                  word;
+}      E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC;
+#endif
+
+
+// -------------------------------------------------------------------
+//  E2PROM data layout
+// -------------------------------------------------------------------
+
+//
+// EEPROM antenna select format
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _EEPROM_ANTENNA_STRUC   {
+       struct  {
+               USHORT      Rsv:4;
+               USHORT      RfIcType:4;             // see E2PROM document
+               USHORT          TxPath:4;       // 1: 1T, 2: 2T
+               USHORT          RxPath:4;       // 1: 1R, 2: 2R, 3: 3R
+       }       field;
+       USHORT                  word;
+}      EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC;
+#else
+typedef        union   _EEPROM_ANTENNA_STRUC   {
+       struct  {
+               USHORT          RxPath:4;       // 1: 1R, 2: 2R, 3: 3R
+               USHORT          TxPath:4;       // 1: 1T, 2: 2T
+               USHORT      RfIcType:4;             // see E2PROM document
+               USHORT      Rsv:4;
+       }       field;
+       USHORT                  word;
+}      EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC;
+#endif
+
+#ifdef RT_BIG_ENDIAN
+typedef        union _EEPROM_NIC_CINFIG2_STRUC {
+       struct  {
+        USHORT         Rsv2:6;                                 // must be 0
+               USHORT          BW40MAvailForA:1;                       // 0:enable, 1:disable
+               USHORT          BW40MAvailForG:1;                       // 0:enable, 1:disable
+               USHORT          EnableWPSPBC:1;                 // WPS PBC Control bit
+               USHORT          BW40MSidebandForA:1;
+               USHORT          BW40MSidebandForG:1;
+               USHORT          CardbusAcceleration:1;  // !!! NOTE: 0 - enable, 1 - disable
+               USHORT          ExternalLNAForA:1;                      // external LNA enable for 5G
+               USHORT          ExternalLNAForG:1;                      // external LNA enable for 2.4G
+               USHORT          DynamicTxAgcControl:1;                  //
+               USHORT          HardwareRadioControl:1; // Whether RF is controlled by driver or HW. 1:enable hw control, 0:disable
+       }       field;
+       USHORT                  word;
+}      EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC;
+#else
+typedef        union _EEPROM_NIC_CINFIG2_STRUC {
+       struct {
+               USHORT          HardwareRadioControl:1; // 1:enable, 0:disable
+               USHORT          DynamicTxAgcControl:1;                  //
+               USHORT          ExternalLNAForG:1;                              //
+               USHORT          ExternalLNAForA:1;                      // external LNA enable for 2.4G
+               USHORT          CardbusAcceleration:1;  // !!! NOTE: 0 - enable, 1 - disable
+               USHORT          BW40MSidebandForG:1;
+               USHORT          BW40MSidebandForA:1;
+               USHORT          EnableWPSPBC:1;                 // WPS PBC Control bit
+               USHORT          BW40MAvailForG:1;                       // 0:enable, 1:disable
+               USHORT          BW40MAvailForA:1;                       // 0:enable, 1:disable
+               USHORT          Rsv2:6;                 // must be 0
+       }       field;
+       USHORT                  word;
+}      EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC;
+#endif
+
+//
+// TX_PWR Value valid range 0xFA(-6) ~ 0x24(36)
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _EEPROM_TX_PWR_STRUC    {
+       struct  {
+               CHAR    Byte1;                          // High Byte
+               CHAR    Byte0;                          // Low Byte
+       }       field;
+       USHORT  word;
+}      EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC;
+#else
+typedef        union   _EEPROM_TX_PWR_STRUC    {
+       struct  {
+               CHAR    Byte0;                          // Low Byte
+               CHAR    Byte1;                          // High Byte
+       }       field;
+       USHORT  word;
+}      EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC;
+#endif
+
+#ifdef RT_BIG_ENDIAN
+typedef        union   _EEPROM_VERSION_STRUC   {
+       struct  {
+               UCHAR   Version;                        // High Byte
+               UCHAR   FaeReleaseNumber;       // Low Byte
+       }       field;
+       USHORT  word;
+}      EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC;
+#else
+typedef        union   _EEPROM_VERSION_STRUC   {
+       struct  {
+               UCHAR   FaeReleaseNumber;       // Low Byte
+               UCHAR   Version;                        // High Byte
+       }       field;
+       USHORT  word;
+}      EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC;
+#endif
+
+#ifdef RT_BIG_ENDIAN
+typedef        union   _EEPROM_LED_STRUC       {
+       struct  {
+               USHORT  Rsvd:3;                         // Reserved
+               USHORT  LedMode:5;                      // Led mode.
+               USHORT  PolarityGPIO_4:1;       // Polarity GPIO#4 setting.
+               USHORT  PolarityGPIO_3:1;       // Polarity GPIO#3 setting.
+               USHORT  PolarityGPIO_2:1;       // Polarity GPIO#2 setting.
+               USHORT  PolarityGPIO_1:1;       // Polarity GPIO#1 setting.
+               USHORT  PolarityGPIO_0:1;       // Polarity GPIO#0 setting.
+               USHORT  PolarityACT:1;          // Polarity ACT setting.
+               USHORT  PolarityRDY_A:1;                // Polarity RDY_A setting.
+               USHORT  PolarityRDY_G:1;                // Polarity RDY_G setting.
+       }       field;
+       USHORT  word;
+}      EEPROM_LED_STRUC, *PEEPROM_LED_STRUC;
+#else
+typedef        union   _EEPROM_LED_STRUC       {
+       struct  {
+               USHORT  PolarityRDY_G:1;                // Polarity RDY_G setting.
+               USHORT  PolarityRDY_A:1;                // Polarity RDY_A setting.
+               USHORT  PolarityACT:1;          // Polarity ACT setting.
+               USHORT  PolarityGPIO_0:1;       // Polarity GPIO#0 setting.
+               USHORT  PolarityGPIO_1:1;       // Polarity GPIO#1 setting.
+               USHORT  PolarityGPIO_2:1;       // Polarity GPIO#2 setting.
+               USHORT  PolarityGPIO_3:1;       // Polarity GPIO#3 setting.
+               USHORT  PolarityGPIO_4:1;       // Polarity GPIO#4 setting.
+               USHORT  LedMode:5;                      // Led mode.
+               USHORT  Rsvd:3;                         // Reserved
+       }       field;
+       USHORT  word;
+}      EEPROM_LED_STRUC, *PEEPROM_LED_STRUC;
+#endif
+
+#ifdef RT_BIG_ENDIAN
+typedef        union   _EEPROM_TXPOWER_DELTA_STRUC     {
+       struct  {
+               UCHAR   TxPowerEnable:1;// Enable
+               UCHAR   Type:1;                 // 1: plus the delta value, 0: minus the delta value
+               UCHAR   DeltaValue:6;   // Tx Power dalta value (MAX=4)
+       }       field;
+       UCHAR   value;
+}      EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC;
+#else
+typedef        union   _EEPROM_TXPOWER_DELTA_STRUC     {
+       struct  {
+               UCHAR   DeltaValue:6;   // Tx Power dalta value (MAX=4)
+               UCHAR   Type:1;                 // 1: plus the delta value, 0: minus the delta value
+               UCHAR   TxPowerEnable:1;// Enable
+       }       field;
+       UCHAR   value;
+}      EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC;
+#endif
+
+//
+// QOS_CSR0: TXOP holder address0 register
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _QOS_CSR0_STRUC {
+       struct  {
+               UCHAR           Byte3;          // MAC address byte 3
+               UCHAR           Byte2;          // MAC address byte 2
+               UCHAR           Byte1;          // MAC address byte 1
+               UCHAR           Byte0;          // MAC address byte 0
+       }       field;
+       UINT32                  word;
+}      QOS_CSR0_STRUC, *PQOS_CSR0_STRUC;
+#else
+typedef        union   _QOS_CSR0_STRUC {
+       struct  {
+               UCHAR           Byte0;          // MAC address byte 0
+               UCHAR           Byte1;          // MAC address byte 1
+               UCHAR           Byte2;          // MAC address byte 2
+               UCHAR           Byte3;          // MAC address byte 3
+       }       field;
+       UINT32                  word;
+}      QOS_CSR0_STRUC, *PQOS_CSR0_STRUC;
+#endif
+
+//
+// QOS_CSR1: TXOP holder address1 register
+//
+#ifdef RT_BIG_ENDIAN
+typedef        union   _QOS_CSR1_STRUC {
+       struct  {
+               UCHAR           Rsvd1;
+               UCHAR           Rsvd0;
+               UCHAR           Byte5;          // MAC address byte 5
+               UCHAR           Byte4;          // MAC address byte 4
+       }       field;
+       UINT32                  word;
+}      QOS_CSR1_STRUC, *PQOS_CSR1_STRUC;
+#else
+typedef        union   _QOS_CSR1_STRUC {
+       struct  {
+               UCHAR           Byte4;          // MAC address byte 4
+               UCHAR           Byte5;          // MAC address byte 5
+               UCHAR           Rsvd0;
+               UCHAR           Rsvd1;
+       }       field;
+       UINT32                  word;
+}      QOS_CSR1_STRUC, *PQOS_CSR1_STRUC;
+#endif
+
+#define        RF_CSR_CFG      0x500
+#ifdef RT_BIG_ENDIAN
+typedef        union   _RF_CSR_CFG_STRUC       {
+       struct  {
+               UINT    Rsvd1:14;                               // Reserved
+               UINT    RF_CSR_KICK:1;                  // kick RF register read/write
+               UINT    RF_CSR_WR:1;                    // 0: read  1: write
+               UINT    Rsvd2:3;                                // Reserved
+               UINT    TESTCSR_RFACC_REGNUM:5; // RF register ID
+               UINT    RF_CSR_DATA:8;                  // DATA
+       }       field;
+       UINT    word;
+}      RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC;
+#else
+typedef        union   _RF_CSR_CFG_STRUC       {
+       struct  {
+               UINT    RF_CSR_DATA:8;                  // DATA
+               UINT    TESTCSR_RFACC_REGNUM:5; // RF register ID
+               UINT    Rsvd2:3;                                // Reserved
+               UINT    RF_CSR_WR:1;                    // 0: read  1: write
+               UINT    RF_CSR_KICK:1;                  // kick RF register read/write
+               UINT    Rsvd1:14;                               // Reserved
+       }       field;
+       UINT    word;
+}      RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC;
+#endif
+
+#endif // __RT28XX_H__
diff --git a/drivers/staging/rt2870/rt_ate.c b/drivers/staging/rt2870/rt_ate.c
new file mode 100644 (file)
index 0000000..e99b3da
--- /dev/null
@@ -0,0 +1,6452 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#include "rt_config.h"
+
+#ifdef UCOS
+INT IoctlResponse(PUCHAR payload, PUCHAR msg, INT len);
+#endif // UCOS //
+
+#ifdef RALINK_ATE
+UCHAR TemplateFrame[24] = {0x08/* Data type */,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xAA,0xBB,0x12,0x34,0x56,0x00,0x11,0x22,0xAA,0xBB,0xCC,0x00,0x00};    // 802.11 MAC Header, Type:Data, Length:24bytes
+extern RTMP_RF_REGS RF2850RegTable[];
+extern UCHAR NUM_OF_2850_CHNL;
+
+#ifdef RT2870
+extern UCHAR EpToQueue[];
+extern VOID    RTUSBRejectPendingPackets(      IN      PRTMP_ADAPTER   pAd);
+#endif // RT2870 //
+
+#ifdef UCOS
+extern INT ConsoleResponse(IN PUCHAR buff);
+extern int (*remote_display)(char *);
+#endif // UCOS //
+
+static CHAR CCKRateTable[] = {0, 1, 2, 3, 8, 9, 10, 11, -1}; /* CCK Mode. */
+static CHAR OFDMRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, -1}; /* OFDM Mode. */
+static CHAR HTMIXRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}; /* HT Mix Mode. */
+
+static INT TxDmaBusy(
+       IN PRTMP_ADAPTER pAd);
+
+static INT RxDmaBusy(
+       IN PRTMP_ADAPTER pAd);
+
+static VOID RtmpDmaEnable(
+       IN PRTMP_ADAPTER pAd,
+       IN INT Enable);
+
+static VOID BbpSoftReset(
+       IN PRTMP_ADAPTER pAd);
+
+static VOID RtmpRfIoWrite(
+       IN PRTMP_ADAPTER pAd);
+
+static INT ATESetUpFrame(
+       IN PRTMP_ADAPTER pAd,
+       IN UINT32 TxIdx);
+
+static INT ATETxPwrHandler(
+       IN PRTMP_ADAPTER pAd,
+       IN char index);
+
+static INT ATECmdHandler(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+static int CheckMCSValid(
+       IN UCHAR Mode,
+       IN UCHAR Mcs);
+
+
+#ifdef RT2870
+static VOID ATEWriteTxInfo(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTXINFO_STRUC   pTxInfo,
+       IN        USHORT                USBDMApktLen,
+       IN        BOOLEAN               bWiv,
+       IN        UCHAR                 QueueSel,
+       IN        UCHAR                 NextValid,
+       IN        UCHAR                 TxBurst);
+
+static VOID ATEWriteTxWI(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTXWI_STRUC     pTxWI,
+       IN      BOOLEAN                 FRAG,
+       IN      BOOLEAN                 InsTimestamp,
+       IN      BOOLEAN                 AMPDU,
+       IN      BOOLEAN                 Ack,
+       IN      BOOLEAN                 NSeq,           // HW new a sequence.
+       IN      UCHAR                   BASize,
+       IN      UCHAR                   WCID,
+       IN      ULONG                   Length,
+       IN      UCHAR                   PID,
+       IN      UCHAR                   MIMOps,
+       IN      UCHAR                   Txopmode,
+       IN      BOOLEAN                 CfAck,
+       IN      HTTRANSMIT_SETTING      Transmit);
+
+#endif // RT2870 //
+
+static VOID SetJapanFilter(
+       IN      PRTMP_ADAPTER   pAd);
+
+/*=========================end of prototype=========================*/
+
+
+#ifdef RT2870
+static INT TxDmaBusy(
+       IN PRTMP_ADAPTER pAd)
+{
+       INT result;
+       USB_DMA_CFG_STRUC UsbCfg;
+
+       RTMP_IO_READ32(pAd, USB_DMA_CFG, &UsbCfg.word); // disable DMA
+       if (UsbCfg.field.TxBusy)
+               result = 1;
+       else
+               result = 0;
+
+       return result;
+}
+
+static INT RxDmaBusy(
+       IN PRTMP_ADAPTER pAd)
+{
+       INT result;
+       USB_DMA_CFG_STRUC UsbCfg;
+
+       RTMP_IO_READ32(pAd, USB_DMA_CFG, &UsbCfg.word); // disable DMA
+       if (UsbCfg.field.RxBusy)
+               result = 1;
+       else
+               result = 0;
+
+       return result;
+}
+
+static VOID RtmpDmaEnable(
+       IN PRTMP_ADAPTER pAd,
+       IN INT Enable)
+{
+       BOOLEAN value;
+       ULONG WaitCnt;
+       USB_DMA_CFG_STRUC UsbCfg;
+
+       value = Enable > 0 ? 1 : 0;
+
+       // check DMA is in busy mode.
+       WaitCnt = 0;
+       while (TxDmaBusy(pAd) || RxDmaBusy(pAd))
+       {
+               RTMPusecDelay(10);
+               if (WaitCnt++ > 100)
+                       break;
+       }
+
+       //Why not to clear USB DMA TX path first ???
+       RTMP_IO_READ32(pAd, USB_DMA_CFG, &UsbCfg.word); // disable DMA
+       UsbCfg.field.TxBulkEn = value;
+       UsbCfg.field.RxBulkEn = value;
+       RTMP_IO_WRITE32(pAd, USB_DMA_CFG, UsbCfg.word); // abort all TX rings
+       RTMPusecDelay(5000);
+
+       return;
+}
+#endif // RT2870 //
+
+static VOID BbpSoftReset(
+       IN PRTMP_ADAPTER pAd)
+{
+       UCHAR BbpData = 0;
+
+       // Soft reset, set BBP R21 bit0=1->0
+       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData);
+       BbpData |= 0x00000001; //set bit0=1
+       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData);
+
+       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData);
+       BbpData &= ~(0x00000001); //set bit0=0
+       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData);
+
+       return;
+}
+
+static VOID RtmpRfIoWrite(
+       IN PRTMP_ADAPTER pAd)
+{
+       // Set RF value 1's set R3[bit2] = [0]
+       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+       RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
+       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+       RTMPusecDelay(200);
+
+       // Set RF value 2's set R3[bit2] = [1]
+       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+       RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
+       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+       RTMPusecDelay(200);
+
+       // Set RF value 3's set R3[bit2] = [0]
+       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+       RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
+       RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+       return;
+}
+
+static int CheckMCSValid(
+       UCHAR Mode,
+       UCHAR Mcs)
+{
+       int i;
+       PCHAR pRateTab;
+
+       switch(Mode)
+       {
+               case 0:
+                       pRateTab = CCKRateTable;
+                       break;
+               case 1:
+                       pRateTab = OFDMRateTable;
+                       break;
+               case 2:
+               case 3:
+                       pRateTab = HTMIXRateTable;
+                       break;
+               default:
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("unrecognizable Tx Mode %d\n", Mode));
+                       return -1;
+                       break;
+       }
+
+       i = 0;
+       while(pRateTab[i] != -1)
+       {
+               if (pRateTab[i] == Mcs)
+                       return 0;
+               i++;
+       }
+
+       return -1;
+}
+
+#if 1
+static INT ATETxPwrHandler(
+       IN PRTMP_ADAPTER pAd,
+       IN char index)
+{
+       ULONG R;
+       CHAR TxPower;
+       UCHAR Bbp94 = 0;
+       BOOLEAN bPowerReduce = FALSE;
+
+#ifdef RALINK_28xx_QA
+       if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE))
+       {
+               /* When QA is used for Tx, pAd->ate.TxPower0/1 and real tx power
+               ** are not synchronized.
+               */
+/*
+               pAd->ate.TxPower0 = pAd->LatchRfRegs.xxx;
+               pAd->ate.TxPower1 = pAd->LatchRfRegs.xxx;
+*/
+               return 0;
+       }
+       else
+#endif // RALINK_28xx_QA //
+       {
+               TxPower = index == 0 ? pAd->ate.TxPower0 : pAd->ate.TxPower1;
+
+               if (pAd->ate.Channel <= 14)
+               {
+                       if (TxPower > 31)
+                       {
+                               //
+                               // R3, R4 can't large than 31 (0x24), 31 ~ 36 used by BBP 94
+                               //
+                               R = 31;
+                               if (TxPower <= 36)
+                                       Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31);
+                       }
+                       else if (TxPower < 0)
+                       {
+                               //
+                               // R3, R4 can't less than 0, -1 ~ -6 used by BBP 94
+                               //
+                               R = 0;
+                               if (TxPower >= -6)
+                                       Bbp94 = BBPR94_DEFAULT + TxPower;
+                       }
+                       else
+                       {
+                               // 0 ~ 31
+                               R = (ULONG) TxPower;
+                               Bbp94 = BBPR94_DEFAULT;
+                       }
+
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%ld, BBP_R94=%d)\n", __FUNCTION__, TxPower, R, Bbp94));
+               }
+               else// 5.5 GHz
+               {
+                       if (TxPower > 15)
+                       {
+                               //
+                               // R3, R4 can't large than 15 (0x0F)
+                               //
+                               R = 15;
+                       }
+                       else if (TxPower < 0)
+                       {
+                               //
+                               // R3, R4 can't less than 0
+                               //
+                               // -1 ~ -7
+                               ASSERT((TxPower >= -7));
+                               R = (ULONG)(TxPower + 7);
+                               bPowerReduce = TRUE;
+                       }
+                       else
+                       {
+                               // 0 ~ 15
+                               R = (ULONG) TxPower;
+                       }
+
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%lu)\n", __FUNCTION__, TxPower, R));
+               }
+
+               if (pAd->ate.Channel <= 14)
+               {
+                       if (index == 0)
+                       {
+                               R = R << 9;             // shift TX power control to correct RF(R3) register bit position
+                               R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff);
+                               pAd->LatchRfRegs.R3 = R;
+                       }
+                       else
+                       {
+                               R = R << 6;             // shift TX power control to correct RF(R4) register bit position
+                               R |= (pAd->LatchRfRegs.R4 & 0xfffff83f);
+                               pAd->LatchRfRegs.R4 = R;
+                       }
+               }
+               else// 5.5GHz
+               {
+                       if (bPowerReduce == FALSE)
+                       {
+                               if (index == 0)
+                               {
+                                       R = (R << 10) | (1 << 9);               // shift TX power control to correct RF(R3) register bit position
+                                       R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff);
+                                       pAd->LatchRfRegs.R3 = R;
+                               }
+                               else
+                               {
+                                       R = (R << 7) | (1 << 6);                // shift TX power control to correct RF(R4) register bit position
+                                       R |= (pAd->LatchRfRegs.R4 & 0xfffff83f);
+                                       pAd->LatchRfRegs.R4 = R;
+                               }
+                       }
+                       else
+                       {
+                               if (index == 0)
+                               {
+                                       R = (R << 10);          // shift TX power control to correct RF(R3) register bit position
+                                       R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff);
+
+                                       /* Clear bit 9 of R3 to reduce 7dB. */
+                                       pAd->LatchRfRegs.R3 = (R & (~(1 << 9)));
+                               }
+                               else
+                               {
+                                       R = (R << 7);           // shift TX power control to correct RF(R4) register bit position
+                                       R |= (pAd->LatchRfRegs.R4 & 0xfffff83f);
+
+                                       /* Clear bit 6 of R4 to reduce 7dB. */
+                                       pAd->LatchRfRegs.R4 = (R & (~(1 << 6)));
+                               }
+                       }
+               }
+
+               RtmpRfIoWrite(pAd);
+
+               return 0;
+       }
+}
+#else// 1 //
+static INT ATETxPwrHandler(
+       IN PRTMP_ADAPTER pAd,
+       IN char index)
+{
+       ULONG R;
+       CHAR TxPower;
+       UCHAR Bbp94 = 0;
+
+#ifdef RALINK_28xx_QA
+       if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE))
+       {
+               // TODO: how to get current TxPower0/1 from pAd->LatchRfRegs ?
+               /* When QA is used for Tx, pAd->ate.TxPower0/1 and real tx power
+               ** are not synchronized.
+               */
+/*
+               pAd->ate.TxPower0 = pAd->LatchRfRegs.xxx;
+               pAd->ate.TxPower1 = pAd->LatchRfRegs.xxx;
+*/
+               return 0;
+       }
+       else
+#endif // RALINK_28xx_QA //
+       {
+               TxPower = index == 0 ? pAd->ate.TxPower0 : pAd->ate.TxPower1;
+
+       if (TxPower > 31)
+       {
+               //
+               // R3, R4 can't large than 36 (0x24), 31 ~ 36 used by BBP 94
+               //
+               R = 31;
+               if (TxPower <= 36)
+                       Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31);
+       }
+       else if (TxPower < 0)
+       {
+               //
+               // R3, R4 can't less than 0, -1 ~ -6 used by BBP 94
+               //
+               R = 0;
+               if (TxPower >= -6)
+                       Bbp94 = BBPR94_DEFAULT + TxPower;
+       }
+       else
+       {
+               // 0 ~ 31
+               R = (ULONG) TxPower;
+               Bbp94 = BBPR94_DEFAULT;
+       }
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R3=%ld, BBP_R94=%d)\n", __FUNCTION__, TxPower, R, Bbp94));
+
+               if (pAd->ate.Channel <= 14)
+               {
+       if (index == 0)
+       {
+               R = R << 9;             // shift TX power control to correct RF(R3) register bit position
+               R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff);
+               pAd->LatchRfRegs.R3 = R;
+       }
+       else
+       {
+               R = R << 6;             // shift TX power control to correct RF(R4) register bit position
+               R |= (pAd->LatchRfRegs.R4 & 0xfffff83f);
+               pAd->LatchRfRegs.R4 = R;
+       }
+               }
+               else
+               {
+                       if (index == 0)
+                       {
+                               R = (R << 10) | (1 << 9);               // shift TX power control to correct RF(R3) register bit position
+                               R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff);
+                               pAd->LatchRfRegs.R3 = R;
+                       }
+                       else
+                       {
+                               R = (R << 7) | (1 << 6);                // shift TX power control to correct RF(R4) register bit position
+                               R |= (pAd->LatchRfRegs.R4 & 0xfffff83f);
+                               pAd->LatchRfRegs.R4 = R;
+                       }
+               }
+
+       RtmpRfIoWrite(pAd);
+
+       return 0;
+       }
+}
+#endif // 1 //
+/*
+    ==========================================================================
+    Description:
+        Set ATE operation mode to
+        0. ATESTART  = Start ATE Mode
+        1. ATESTOP   = Stop ATE Mode
+        2. TXCONT    = Continuous Transmit
+        3. TXCARR    = Transmit Carrier
+        4. TXFRAME   = Transmit Frames
+        5. RXFRAME   = Receive Frames
+#ifdef RALINK_28xx_QA
+        6. TXSTOP    = Stop Any Type of Transmition
+        7. RXSTOP    = Stop Receiving Frames
+#endif // RALINK_28xx_QA //
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+/*                                                           */
+/*                                                           */
+/*=======================End of RT2860=======================*/
+
+
+/*======================Start of RT2870======================*/
+/*                                                           */
+/*                                                           */
+
+#ifdef RT2870
+static INT     ATECmdHandler(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UINT32                  Value;
+       UCHAR                   BbpData;
+       UINT32          MacData;
+       UINT                    i=0, atemode;
+       //NDIS_STATUS           Status = NDIS_STATUS_SUCCESS;
+       //PUCHAR                        pDest;
+       UINT32                  temp;
+       ULONG                   IrqFlags;
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("===> ATECmdHandler()\n"));
+       ATEAsicSwitchChannel(pAd);
+       /* AsicLockChannel() is empty function so far in fact */
+       AsicLockChannel(pAd, pAd->ate.Channel);
+
+       RTMPusecDelay(5000);
+
+       // Default value in BBP R22 is 0x0.
+       BbpData = 0;
+
+       /* Enter ATE mode and set Tx/Rx Idle */
+       if (!strcmp(arg, "ATESTART"))
+       {
+#ifdef CONFIG_STA_SUPPORT
+               BOOLEAN       Cancelled;
+#endif // CONFIG_STA_SUPPORT //
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: ATESTART\n"));
+
+               netif_stop_queue(pAd->net_dev);
+
+               atemode = pAd->ate.Mode;
+               pAd->ate.Mode = ATE_START;
+//             pAd->ate.TxDoneCount = pAd->ate.TxCount;
+               // Disable Rx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 3);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               // Disable auto responder
+               RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &temp);
+               temp = temp & 0xFFFFFFFE;
+               RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, temp);
+
+               // read MAC_SYS_CTRL and backup MAC_SYS_CTRL value.
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);
+               // clean bit4 to stop continuous Tx production test.
+               MacData &= 0xFFFFFFEF;
+               // Stop continuous TX production test.
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);//disable or cancel pending irp first ???
+
+        if (atemode & ATE_TXCARR)
+               {
+                       // No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+                       BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0]
+                   ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+               }
+               else if (atemode & ATE_TXCARRSUPP)
+               {
+                       // No Cont. TX set BBP R22 bit7=0
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+                       BbpData &= ~(1 << 7); //set bit7=0
+                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+
+                       // No Carrier Suppression set BBP R24 bit0=0
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &BbpData);
+                       BbpData &= 0xFFFFFFFE; //clear bit0
+                   ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BbpData);
+               }
+               // We should free some resource which allocate when ATE_TXFRAME , ATE_STOP, and ATE_TXCONT.
+               // TODO:Should we free some resource which was allocated when LoopBack and ATE_STOP ?
+               else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP))
+               {
+                       if (atemode & ATE_TXCONT)
+                       {
+                               // Not Cont. TX anymore, so set BBP R22 bit7=0
+                               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+                               BbpData &= ~(1 << 7); //set bit7=0
+                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+                       }
+                       // Abort Tx, Rx DMA.
+                       RtmpDmaEnable(pAd, 0);
+
+                       {
+                               // It seems nothing to free,
+                               // because we didn't allocate any resource when we entered ATE_TXFRAME mode latestly.
+                       }
+
+                       // Start Tx, RX DMA
+                       RtmpDmaEnable(pAd, 1);
+               }
+
+               RTUSBRejectPendingPackets(pAd);
+               RTUSBCleanUpDataBulkOutQueue(pAd);
+
+#ifdef CONFIG_STA_SUPPORT
+               //
+               // It will be called in MlmeSuspend().
+               //
+               // Cancel pending timers
+               RTMPCancelTimer(&pAd->MlmeAux.AssocTimer,     &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer,   &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer,   &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.AuthTimer,       &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer,     &Cancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.ScanTimer,       &Cancelled);
+#endif // CONFIG_STA_SUPPORT //
+
+               //RTUSBCleanUpMLMEWaitQueue(pAd);       /* not used in RT28xx */
+               RTUSBCleanUpMLMEBulkOutQueue(pAd);
+
+               // Sometimes kernel will hang on, so we avoid calling MlmeSuspend().
+//             MlmeSuspend(pAd, TRUE);
+               //RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
+
+               // Disable Rx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 3);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               // Abort Tx, RX DMA.
+               RtmpDmaEnable(pAd, 0);
+
+               // Disable Tx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 2);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               // Make sure there are no pending bulk in/out IRPs before we go on.
+/*=========================================================================*/
+               /* pAd->PendingRx is not of type atomic_t anymore in 28xx */
+//             while ((atomic_read(&pAd->PendingRx) > 0))      //pAd->BulkFlags != 0 wait bulk out finish
+               while ((pAd->PendingRx > 0))    //pAd->BulkFlags != 0 wait bulk out finish
+               {
+#if 1
+                       ATE_RTUSBCancelPendingBulkInIRP(pAd);
+#else
+                       NdisInterlockedDecrement(&pAd->PendingRx);
+#endif
+                       /* delay 0.5 seconds */
+                       RTMPusecDelay(500000);
+                       pAd->PendingRx = 0;
+               }
+               /* peter : why don't we have to get BulkOutLock first ? */
+               while (((pAd->BulkOutPending[0] == TRUE) ||
+                               (pAd->BulkOutPending[1] == TRUE) ||
+                               (pAd->BulkOutPending[2] == TRUE) ||
+                               (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0))     //pAd->BulkFlags != 0 wait bulk out finish
+               {
+                       do
+                       {
+                               /* pAd->BulkOutPending[y] will be set to FALSE in RTUSBCancelPendingBulkOutIRP(pAd) */
+                               RTUSBCancelPendingBulkOutIRP(pAd);
+                       } while (FALSE);
+
+                       /* we have enough time delay in RTUSBCancelPendingBulkOutIRP(pAd)
+                       ** so this is not necessary
+                       */
+//                     RTMPusecDelay(500000);
+               }
+
+               /* pAd->PendingRx is not of type atomic_t anymore in 28xx */
+//             ASSERT(atomic_read(&pAd->PendingRx) == 0);
+               ASSERT(pAd->PendingRx == 0);
+/*=========================================================================*/
+
+               // reset Rx statistics.
+               pAd->ate.LastSNR0 = 0;
+               pAd->ate.LastSNR1 = 0;
+               pAd->ate.LastRssi0 = 0;
+               pAd->ate.LastRssi1 = 0;
+               pAd->ate.LastRssi2 = 0;
+               pAd->ate.AvgRssi0 = 0;
+               pAd->ate.AvgRssi1 = 0;
+               pAd->ate.AvgRssi2 = 0;
+               pAd->ate.AvgRssi0X8 = 0;
+               pAd->ate.AvgRssi1X8 = 0;
+               pAd->ate.AvgRssi2X8 = 0;
+               pAd->ate.NumOfAvgRssiSample = 0;
+
+#ifdef RALINK_28xx_QA
+               // Tx frame
+               pAd->ate.bQATxStart = FALSE;
+               pAd->ate.bQARxStart = FALSE;
+               pAd->ate.seq = 0;
+
+               // counters
+               pAd->ate.U2M = 0;
+               pAd->ate.OtherData = 0;
+               pAd->ate.Beacon = 0;
+               pAd->ate.OtherCount = 0;
+               pAd->ate.TxAc0 = 0;
+               pAd->ate.TxAc1 = 0;
+               pAd->ate.TxAc2 = 0;
+               pAd->ate.TxAc3 = 0;
+               pAd->ate.TxHCCA = 0;
+               pAd->ate.TxMgmt = 0;
+               pAd->ate.RSSI0 = 0;
+               pAd->ate.RSSI1 = 0;
+               pAd->ate.RSSI2 = 0;
+               pAd->ate.SNR0 = 0;
+               pAd->ate.SNR1 = 0;
+
+               // control
+               pAd->ate.TxDoneCount = 0;
+               pAd->ate.TxStatus = 0; // task Tx status // 0 --> task is idle, 1 --> task is running
+#endif // RALINK_28xx_QA //
+
+               // Soft reset BBP.
+               BbpSoftReset(pAd);
+
+
+#ifdef CONFIG_STA_SUPPORT
+               AsicDisableSync(pAd);
+
+               /*
+               ** If we skip "LinkDown()", we should disable protection
+               ** to prevent from sending out RTS or CTS-to-self.
+               */
+               ATEDisableAsicProtect(pAd);
+               RTMPStationStop(pAd);
+#endif // CONFIG_STA_SUPPORT //
+
+               // Default value in BBP R22 is 0x0.
+               BbpData = 0;
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);
+
+               // Clean bit4 to stop continuous Tx production test.
+               MacData &= 0xFFFFFFEF;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);
+               //Clean ATE Bulk in/out counter and continue setup
+               InterlockedExchange(&pAd->BulkOutRemained, 0);
+
+               /* NdisAcquireSpinLock()/NdisReleaseSpinLock() need only one argument in RT28xx */
+               NdisAcquireSpinLock(&pAd->GenericLock);
+               pAd->ContinBulkOut = FALSE;
+               pAd->ContinBulkIn = FALSE;
+               NdisReleaseSpinLock(&pAd->GenericLock);
+
+               RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE);
+       }
+       else if (!strcmp(arg, "ATESTOP"))
+       {
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE : ATESTOP ===>\n"));
+
+               // Default value in BBP R22 is 0x0.
+               BbpData = 0;
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);//0820
+               // Clean bit4 to stop continuous Tx production test.
+               MacData &= 0xFFFFFFEF;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); // recover the MAC_SYS_CTRL register back.
+
+               // Disable Rx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 3);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               /*
+               ** Abort Tx, RX DMA.
+               ** Q   : How to do the following I/O if Tx, Rx DMA is aborted ?
+               ** Ans : Bulk endpoints are aborted, while the control endpoint is not.
+               */
+               RtmpDmaEnable(pAd, 0);
+
+               // Disable Tx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 2);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               /* Make sure there are no pending bulk in/out IRPs before we go on. */
+/*=========================================================================*/
+//             while ((atomic_read(&pAd->PendingRx) > 0))      //pAd->BulkFlags != 0 wait bulk out finish
+               while (pAd->PendingRx > 0)
+               {
+#if 1
+                       ATE_RTUSBCancelPendingBulkInIRP(pAd);
+#else
+//                     NdisInterlockedDecrement(&pAd->PendingRx);
+                       pAd->PendingRx--;
+#endif
+                       RTMPusecDelay(500000);
+               }
+
+               while (((pAd->BulkOutPending[0] == TRUE) ||
+                               (pAd->BulkOutPending[1] == TRUE) ||
+                               (pAd->BulkOutPending[2] == TRUE) ||
+                               (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0))     //pAd->BulkFlags != 0 wait bulk out finish
+               {
+                       do
+                       {
+                               RTUSBCancelPendingBulkOutIRP(pAd);
+                       } while (FALSE);
+
+                       RTMPusecDelay(500000);
+               }
+
+//             ASSERT(atomic_read(&pAd->PendingRx) == 0);
+               ASSERT(pAd->PendingRx == 0);
+/*=========================================================================*/
+/*      Reset Rx RING                                                      */
+/*=========================================================================*/
+//             InterlockedExchange(&pAd->PendingRx, 0);
+               pAd->PendingRx = 0;
+               pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index
+               pAd->NextRxBulkInIndex = RX_RING_SIZE - 1;      // Rx Bulk pointer
+               pAd->NextRxBulkInPosition = 0;
+               for (i = 0; i < (RX_RING_SIZE); i++)
+               {
+                       PRX_CONTEXT  pRxContext = &(pAd->RxContext[i]);
+                       NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE);
+                       /* peter : why don't we have to get BulkInLock first ? */
+                       pRxContext->pAd = pAd;
+                       pRxContext->pIrp = NULL;
+            /* peter debug ++ */
+                       pRxContext->BulkInOffset = 0;
+                       pRxContext->bRxHandling = FALSE;
+            /* peter debug -- */
+                       pRxContext->InUse               = FALSE;
+                       pRxContext->IRPPending  = FALSE;
+                       pRxContext->Readable    = FALSE;
+//                     pRxContext->ReorderInUse = FALSE;
+//                     pRxContext->ReadPosOffset = 0;
+               }
+
+/*=========================================================================*/
+/*      Reset Tx RING                                                      */
+/*=========================================================================*/
+               do
+               {
+                       RTUSBCancelPendingBulkOutIRP(pAd);
+               } while (FALSE);
+
+/*=========================================================================*/
+               // Enable auto responder.
+               RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &temp);
+               temp = temp | (0x01);
+               RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, temp);
+
+/*================================================*/
+               AsicEnableBssSync(pAd);
+
+               /* Soft reset BBP.*/
+               /* In 2870 chipset, ATE_BBP_IO_READ8_BY_REG_ID() == RTMP_BBP_IO_READ8_BY_REG_ID() */
+               /* Both rt2870ap and rt2870sta use BbpSoftReset(pAd) to do BBP soft reset */
+               BbpSoftReset(pAd);
+/*================================================*/
+               {
+#ifdef CONFIG_STA_SUPPORT
+                       // Set all state machines back IDLE
+                       pAd->Mlme.CntlMachine.CurrState    = CNTL_IDLE;
+                       pAd->Mlme.AssocMachine.CurrState   = ASSOC_IDLE;
+                       pAd->Mlme.AuthMachine.CurrState    = AUTH_REQ_IDLE;
+                       pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
+                       pAd->Mlme.SyncMachine.CurrState    = SYNC_IDLE;
+                       pAd->Mlme.ActMachine.CurrState    = ACT_IDLE;
+#endif // CONFIG_STA_SUPPORT //
+
+                       //
+                       // ===> refer to MlmeRestartStateMachine().
+                       // When we entered ATE_START mode, PeriodicTimer was not cancelled.
+                       // So we don't have to set it here.
+                       //
+                       //RTMPSetTimer(pAd, &pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
+
+                       ASSERT(pAd->CommonCfg.Channel != 0);
+
+                       AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+                       AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+
+
+#ifdef CONFIG_STA_SUPPORT
+                   RTMPStationStart(pAd);
+#endif // CONFIG_STA_SUPPORT //
+               }
+//
+// These two steps have been done when entering ATE_STOP mode.
+//
+#if 0
+           RTUSBWriteBBPRegister(pAd, BBP_R22, BbpData);
+               RTUSBWriteMACRegister(pAd, MAC_SYS_CTRL, MacData);
+#endif
+               // Clean ATE Bulk in/out counter and continue setup.
+               InterlockedExchange(&pAd->BulkOutRemained, 0);
+               NdisAcquireSpinLock(&pAd->GenericLock);
+               pAd->ContinBulkOut = FALSE;
+               pAd->ContinBulkIn = FALSE;
+               NdisReleaseSpinLock(&pAd->GenericLock);
+
+               /* Wait 50ms to prevent next URB to bulkout during HW reset. */
+               /* todo : remove this if not necessary */
+               NdisMSleep(50000);
+
+               pAd->ate.Mode = ATE_STOP;
+
+               // Enable Tx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value |= (1 << 2);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+/*=========================================================================*/
+               /* restore RX_FILTR_CFG */
+#ifdef CONFIG_STA_SUPPORT
+               /* restore RX_FILTR_CFG in order that QA maybe set it to 0x3 */
+               RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL);
+#endif // CONFIG_STA_SUPPORT //
+/*=========================================================================*/
+
+               // Enable Tx, RX DMA.
+               RtmpDmaEnable(pAd, 1);
+
+               // Enable Rx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value |= (1 << 3);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               // Wait 10ms to wait all of the bulk-in URBs to complete.
+               /* todo : remove this if not necessary */
+               NdisMSleep(10000);
+
+               // Everything is ready to start normal Tx/Rx.
+               RTUSBBulkReceive(pAd);
+               netif_start_queue(pAd->net_dev);
+
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== ATE : ATESTOP \n"));
+       }
+       else if (!strcmp(arg, "TXCARR"))        // Tx Carrier
+       {
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCARR\n"));
+               pAd->ate.Mode |= ATE_TXCARR;
+
+               // Disable Rx
+               // May be we need not to do this, because these have been done in ATE_START mode ???
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 3);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               // QA has done the following steps if it is used.
+               if (pAd->ate.bQATxStart == FALSE)
+               {
+                       // Soft reset BBP.
+                       BbpSoftReset(pAd);
+
+                       // Carrier Test set BBP R22 bit7=1, bit6=1, bit[5~0]=0x01
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+                       BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0]
+                       BbpData |= 0x000000C1; //set bit7=1, bit6=1, bit[5~0]=0x01
+                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+
+                       // set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1
+                       RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+                       Value = Value | 0x00000010;
+                       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+               }
+       }
+       else if (!strcmp(arg, "TXCONT"))        // Tx Continue
+       {
+               if (pAd->ate.bQATxStart == TRUE)
+               {
+                       /* set MAC_SYS_CTRL(0x1004) bit4(Continuous Tx Production Test)
+                          and bit2(MAC TX enable) back to zero. */
+                       RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);
+                       MacData &= 0xFFFFFFEB;
+                       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);
+
+                       // set BBP R22 bit7=0
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+                       BbpData &= 0xFFFFFF7F; //set bit7=0
+                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+               }
+
+               /* for TxCont mode.
+               ** Step 1: Send 50 packets first then wait for a moment.
+               ** Step 2: Send more 50 packet then start continue mode.
+               */
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCONT\n"));
+               // Step 1: send 50 packets first.
+               pAd->ate.Mode |= ATE_TXCONT;
+               pAd->ate.TxCount = 50;
+               pAd->ate.TxDoneCount = 0;
+
+               // Soft reset BBP.
+               BbpSoftReset(pAd);
+
+               // Abort Tx, RX DMA.
+               RtmpDmaEnable(pAd, 0);
+
+
+               /* Only needed if we have to send some normal frames. */
+               SetJapanFilter(pAd);
+
+               // Setup frame format.
+               ATESetUpFrame(pAd, 0);
+
+               // Enable Tx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value |= (1 << 2);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               // Disable Rx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 3);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               // Start Tx, RX DMA.
+               RtmpDmaEnable(pAd, 1);
+
+               InterlockedExchange(&pAd->BulkOutRemained, pAd->ate.TxCount);
+
+#ifdef RALINK_28xx_QA
+               if (pAd->ate.bQATxStart == TRUE)
+               {
+                       pAd->ate.TxStatus = 1;
+                       //pAd->ate.Repeat = 0;
+               }
+#endif // RALINK_28xx_QA //
+
+               NdisAcquireSpinLock(&pAd->GenericLock);//0820
+               pAd->ContinBulkOut = FALSE;
+               NdisReleaseSpinLock(&pAd->GenericLock);
+
+               RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE);
+
+               // Kick bulk out
+               RTUSBKickBulkOut(pAd);
+
+               /* To make sure all the 50 frames have been bulk out before executing step 2 */
+               while (atomic_read(&pAd->BulkOutRemained) > 0)
+               {
+                       RTMPusecDelay(5000);
+               }
+
+               // Step 2: send more 50 packets then start continue mode.
+               // Abort Tx, RX DMA.
+               RtmpDmaEnable(pAd, 0);
+
+               // Cont. TX set BBP R22 bit7=1
+               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+               BbpData |= 0x00000080; //set bit7=1
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+
+               pAd->ate.TxCount = 50;
+               pAd->ate.TxDoneCount = 0;
+
+               SetJapanFilter(pAd);
+
+               // Setup frame format.
+               ATESetUpFrame(pAd, 0);
+
+               // Enable Tx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value |= (1 << 2);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               // Disable Rx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 3);
+
+               // Start Tx, RX DMA.
+               RtmpDmaEnable(pAd, 1);
+
+               InterlockedExchange(&pAd->BulkOutRemained, pAd->ate.TxCount);
+
+#ifdef RALINK_28xx_QA
+               if (pAd->ate.bQATxStart == TRUE)
+               {
+                       pAd->ate.TxStatus = 1;
+                       //pAd->ate.Repeat = 0;
+               }
+#endif // RALINK_28xx_QA //
+
+               NdisAcquireSpinLock(&pAd->GenericLock);//0820
+               pAd->ContinBulkOut = FALSE;
+               NdisReleaseSpinLock(&pAd->GenericLock);
+
+               RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE);
+               // Kick bulk out
+               RTUSBKickBulkOut(pAd);
+
+#if 1
+               RTMPusecDelay(500);
+#else
+               while (atomic_read(&pAd->BulkOutRemained) > 0)
+               {
+                       RTMPusecDelay(5000);
+               }
+#endif // 1 //
+
+               // Set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1.
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);
+               MacData |= 0x00000010;
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);
+       }
+       else if (!strcmp(arg, "TXFRAME"))       // Tx Frames
+       {
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXFRAME(Count=0x%08x)\n", pAd->ate.TxCount));
+               pAd->ate.Mode |= ATE_TXFRAME;
+
+               // Soft reset BBP.
+               BbpSoftReset(pAd);
+
+               // Default value in BBP R22 is 0x0.
+               BbpData = 0;
+
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);
+
+               // Clean bit4 to stop continuous Tx production test.
+               MacData &= 0xFFFFFFEF;
+
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);
+
+#ifdef RALINK_28xx_QA
+               // add this for LoopBack mode
+               if (pAd->ate.bQARxStart == FALSE)
+               {
+                       // Disable Rx
+                       RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+                       Value &= ~(1 << 3);
+                       RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+               }
+
+               if (pAd->ate.bQATxStart == TRUE)
+               {
+                       pAd->ate.TxStatus = 1;
+                       //pAd->ate.Repeat = 0;
+               }
+#else
+               // Disable Rx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 3);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+#endif // RALINK_28xx_QA //
+
+               // Enable Tx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value |= (1 << 2);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+        SetJapanFilter(pAd);
+
+               // Abort Tx, RX DMA.
+               RtmpDmaEnable(pAd, 0);
+
+               pAd->ate.TxDoneCount = 0;
+
+        // Setup frame format
+               ATESetUpFrame(pAd, 0);
+
+               // Start Tx, RX DMA.
+               RtmpDmaEnable(pAd, 1);
+
+               // Check count is continuous or not yet.
+               //
+               // Due to the type mismatch between "pAd->BulkOutRemained"(atomic_t) and "pAd->ate.TxCount"(UINT32)
+               //
+               if (pAd->ate.TxCount == 0)
+               {
+                       InterlockedExchange(&pAd->BulkOutRemained, 0);
+               }
+               else
+               {
+                       InterlockedExchange(&pAd->BulkOutRemained, pAd->ate.TxCount);
+               }
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("bulk out count = %d\n", atomic_read(&pAd->BulkOutRemained)));
+               ASSERT((atomic_read(&pAd->BulkOutRemained) >= 0));
+
+               if (atomic_read(&pAd->BulkOutRemained) == 0)
+               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("Send packet countinuously\n"));
+
+                       /* In 28xx, NdisAcquireSpinLock() == spin_lock_bh() */
+                       /* NdisAcquireSpinLock only need one argument in 28xx. */
+                       NdisAcquireSpinLock(&pAd->GenericLock);
+                       pAd->ContinBulkOut = TRUE;
+                       NdisReleaseSpinLock(&pAd->GenericLock);
+
+                       /* In 28xx, BULK_OUT_LOCK() == spin_lock_irqsave() */
+                       BULK_OUT_LOCK(&pAd->BulkOutLock[0], IrqFlags);// peter : NdisAcquireSpinLock ==> BULK_OUT_LOCK
+                       pAd->BulkOutPending[0] = FALSE;
+                       BULK_OUT_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);// peter : NdisAcquireSpinLock ==> BULK_OUT_LOCK
+               }
+               else
+               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("Send packets depend on counter\n"));
+
+                       NdisAcquireSpinLock(&pAd->GenericLock);
+                       pAd->ContinBulkOut = FALSE;
+                       NdisReleaseSpinLock(&pAd->GenericLock);
+
+                       BULK_OUT_LOCK(&pAd->BulkOutLock[0], IrqFlags);
+                       pAd->BulkOutPending[0] = FALSE;
+                       BULK_OUT_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+               }
+
+               RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE);
+
+               // Kick bulk out
+               RTUSBKickBulkOut(pAd);
+       }
+#ifdef RALINK_28xx_QA
+       else if (!strcmp(arg, "TXSTOP"))                //Enter ATE mode and set Tx/Rx Idle
+       {
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXSTOP\n"));
+
+               atemode = pAd->ate.Mode;
+               pAd->ate.Mode &= ATE_TXSTOP;
+               pAd->ate.bQATxStart = FALSE;
+//             pAd->ate.TxDoneCount = pAd->ate.TxCount;
+
+/*=========================================================================*/
+               if (atemode & ATE_TXCARR)
+               {
+                       // No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+                       BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0]
+                   ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+               }
+               else if (atemode & ATE_TXCARRSUPP)
+               {
+                       // No Cont. TX set BBP R22 bit7=0
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+                       BbpData &= ~(1 << 7); //set bit7=0
+                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+
+                       // No Carrier Suppression set BBP R24 bit0=0
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &BbpData);
+                       BbpData &= 0xFFFFFFFE; //clear bit0
+                   ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BbpData);
+               }
+               else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP))
+               {
+                       if (atemode & ATE_TXCONT)
+                       {
+                               // No Cont. TX set BBP R22 bit7=0
+                               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+                               BbpData &= ~(1 << 7); //set bit7=0
+                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+                       }
+               }
+
+/*=========================================================================*/
+               RTUSBRejectPendingPackets(pAd);
+               RTUSBCleanUpDataBulkOutQueue(pAd);
+
+               /* not used in RT28xx */
+               //RTUSBCleanUpMLMEWaitQueue(pAd);
+               /* empty function so far */
+               RTUSBCleanUpMLMEBulkOutQueue(pAd);
+/*=========================================================================*/
+               // Abort Tx, RX DMA.
+               RtmpDmaEnable(pAd, 0);
+/*=========================================================================*/
+
+               /* In 28xx, pAd->PendingRx is not of type atomic_t anymore */
+//             while ((atomic_read(&pAd->PendingRx) > 0))      //pAd->BulkFlags != 0 wait bulk out finish
+               /* peter todo : BulkInLock */
+               while (pAd->PendingRx > 0)
+               {
+#if 1
+                       ATE_RTUSBCancelPendingBulkInIRP(pAd);
+#else
+//                     NdisInterlockedDecrement(&pAd->PendingRx);
+                       pAd->PendingRx--;
+#endif
+                       RTMPusecDelay(500000);
+               }
+
+               while (((pAd->BulkOutPending[0] == TRUE) ||
+                               (pAd->BulkOutPending[1] == TRUE) ||
+                               (pAd->BulkOutPending[2] == TRUE) ||
+                               (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0))     //pAd->BulkFlags != 0 wait bulk out finish
+               {
+                       do
+                       {
+                               RTUSBCancelPendingBulkOutIRP(pAd);
+                       } while (FALSE);
+
+                       RTMPusecDelay(500000);
+               }
+
+               ASSERT(pAd->PendingRx == 0);
+/*=========================================================================*/
+               // Enable Tx, Rx DMA.
+               RtmpDmaEnable(pAd, 1);
+
+               /* task Tx status : 0 --> task is idle, 1 --> task is running */
+               pAd->ate.TxStatus = 0;
+
+               // Soft reset BBP.
+               BbpSoftReset(pAd);
+
+               // Disable Tx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);
+               MacData &= (0xfffffffb);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);
+
+               //Clean ATE Bulk in/out counter and continue setup
+               InterlockedExchange(&pAd->BulkOutRemained, 0);
+
+               pAd->ContinBulkOut = FALSE;
+       }
+       else if (!strcmp(arg, "RXSTOP"))
+       {
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXSTOP\n"));
+               atemode = pAd->ate.Mode;
+
+               // Disable Rx
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 3);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               pAd->ate.Mode &= ATE_RXSTOP;
+               pAd->ate.bQARxStart = FALSE;
+//             pAd->ate.TxDoneCount = pAd->ate.TxCount;
+
+/*=========================================================================*/
+               RTUSBRejectPendingPackets(pAd);
+               RTUSBCleanUpDataBulkOutQueue(pAd);
+
+               /* not used in RT28xx */
+               //RTUSBCleanUpMLMEWaitQueue(pAd);
+               RTUSBCleanUpMLMEBulkOutQueue(pAd);
+/*=========================================================================*/
+
+               // Abort Tx, RX DMA.
+               RtmpDmaEnable(pAd, 0);
+/*=========================================================================*/
+//             while ((atomic_read(&pAd->PendingRx) > 0))
+               while (pAd->PendingRx > 0)
+               {
+#if 1
+                       ATE_RTUSBCancelPendingBulkInIRP(pAd);
+#else
+//                     NdisInterlockedDecrement(&pAd->PendingRx);
+                       pAd->PendingRx--;
+#endif
+                       RTMPusecDelay(500000);
+               }
+
+               while (((pAd->BulkOutPending[0] == TRUE) ||
+                               (pAd->BulkOutPending[1] == TRUE) ||
+                               (pAd->BulkOutPending[2] == TRUE) ||
+                               (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0))     //pAd->BulkFlags != 0 wait bulk out finish
+               {
+                       do
+                       {
+                               RTUSBCancelPendingBulkOutIRP(pAd);
+                       } while (FALSE);
+
+                       RTMPusecDelay(500000);
+               }
+
+               ASSERT(pAd->PendingRx == 0);
+/*=========================================================================*/
+
+               // Soft reset BBP.
+               BbpSoftReset(pAd);
+               pAd->ContinBulkIn = FALSE;
+       }
+#endif // RALINK_28xx_QA //
+       else if (!strcmp(arg, "RXFRAME")) // Rx Frames
+       {
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXFRAME\n"));
+
+               // Disable Rx of MAC block
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 3);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               // Default value in BBP R22 is 0x0.
+               BbpData = 0;
+
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);
+               // Clean bit4 to stop continuous Tx production test.
+               MacData &= 0xFFFFFFEF;
+
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);
+
+               pAd->ate.Mode |= ATE_RXFRAME;
+
+               // Abort Tx, RX DMA.
+               RtmpDmaEnable(pAd, 0);
+
+               // Disable TX of MAC block
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value &= ~(1 << 2);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+        // Reset Rx RING.
+               for ( i = 0; i < (RX_RING_SIZE); i++)
+               {
+                       PRX_CONTEXT  pRxContext = &(pAd->RxContext[i]);
+
+                       pRxContext->InUse = FALSE;
+                       pRxContext->IRPPending = FALSE;
+                       pRxContext->Readable = FALSE;
+
+                       //
+                       // Get the urb from kernel back to driver.
+                       //
+                       RTUSB_UNLINK_URB(pRxContext->pUrb);
+
+                       /* Sleep 200 microsecs to give cancellation time to work. */
+                       NdisMSleep(200);
+                       pAd->BulkInReq = 0;
+
+//                     InterlockedExchange(&pAd->PendingRx, 0);
+                       pAd->PendingRx = 0;
+                       pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index
+                       pAd->NextRxBulkInIndex          = RX_RING_SIZE - 1;     // Rx Bulk pointer
+                       pAd->NextRxBulkInPosition = 0;
+               }
+
+               // read to clear counters
+               RTUSBReadMACRegister(pAd, RX_STA_CNT0, &temp); //RX PHY & RX CRC count
+               RTUSBReadMACRegister(pAd, RX_STA_CNT1, &temp); //RX PLCP error count & CCA false alarm count
+               RTUSBReadMACRegister(pAd, RX_STA_CNT2, &temp); //RX FIFO overflow frame count & RX duplicated filtered frame count
+
+               pAd->ContinBulkIn = TRUE;
+
+               // Enable Tx, RX DMA.
+               RtmpDmaEnable(pAd, 1);
+
+               // Enable RX of MAC block
+               RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+               Value |= (1 << 3);
+               RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+               // Kick bulk in
+               RTUSBBulkReceive(pAd);
+       }
+       else
+       {
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: Invalid arg!\n"));
+               return FALSE;
+       }
+       RTMPusecDelay(5000);
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== ATECmdHandler()\n"));
+
+       return TRUE;
+}
+#endif // RT2870 //
+
+INT    Set_ATE_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       if (ATECmdHandler(pAd, arg))
+       {
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Success\n"));
+
+
+               return TRUE;
+       }
+       else
+       {
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Failed\n"));
+               return FALSE;
+       }
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE ADDR1=DA for TxFrame(AP  : To DS = 0 ; From DS = 1)
+        or
+        Set ATE ADDR3=DA for TxFrame(STA : To DS = 1 ; From DS = 0)
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_DA_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       CHAR                            *value;
+       INT                                     i;
+
+       if(strlen(arg) != 17)  //Mac address acceptable format 01:02:03:04:05:06 length 17
+               return FALSE;
+
+    for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":"))
+       {
+               if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
+                       return FALSE;  //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+               AtoH(value, &pAd->ate.Addr3[i++], 1);
+#endif // CONFIG_STA_SUPPORT //
+       }
+
+       if(i != 6)
+               return FALSE;  //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_DA_Proc (DA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr3[0],
+               pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5]));
+#endif // CONFIG_STA_SUPPORT //
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_DA_Proc Success\n"));
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE ADDR3=SA for TxFrame(AP  : To DS = 0 ; From DS = 1)
+        or
+        Set ATE ADDR2=SA for TxFrame(STA : To DS = 1 ; From DS = 0)
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_SA_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       CHAR                            *value;
+       INT                                     i;
+
+       if(strlen(arg) != 17)  //Mac address acceptable format 01:02:03:04:05:06 length 17
+               return FALSE;
+
+    for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":"))
+       {
+               if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
+                       return FALSE;  //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+               AtoH(value, &pAd->ate.Addr2[i++], 1);
+#endif // CONFIG_STA_SUPPORT //
+       }
+
+       if(i != 6)
+               return FALSE;  //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_SA_Proc (SA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr2[0],
+               pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5]));
+#endif // CONFIG_STA_SUPPORT //
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_SA_Proc Success\n"));
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE ADDR2=BSSID for TxFrame(AP  : To DS = 0 ; From DS = 1)
+        or
+        Set ATE ADDR1=BSSID for TxFrame(STA : To DS = 1 ; From DS = 0)
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_BSSID_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       CHAR                            *value;
+       INT                                     i;
+
+       if(strlen(arg) != 17)  //Mac address acceptable format 01:02:03:04:05:06 length 17
+               return FALSE;
+
+    for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":"))
+       {
+               if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
+                       return FALSE;  //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+               AtoH(value, &pAd->ate.Addr1[i++], 1);
+#endif // CONFIG_STA_SUPPORT //
+       }
+
+       if(i != 6)
+               return FALSE;  //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_BSSID_Proc (BSSID = %2X:%2X:%2X:%2X:%2X:%2X)\n",  pAd->ate.Addr1[0],
+               pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5]));
+#endif // CONFIG_STA_SUPPORT //
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_BSSID_Proc Success\n"));
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE Tx Channel
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_CHANNEL_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UCHAR channel;
+
+       channel = simple_strtol(arg, 0, 10);
+
+       if ((channel < 1) || (channel > 216))// to allow A band channel : ((channel < 1) || (channel > 14))
+       {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_CHANNEL_Proc::Out of range, it should be in range of 1~14.\n"));
+               return FALSE;
+       }
+       pAd->ate.Channel = channel;
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_CHANNEL_Proc (ATE Channel = %d)\n", pAd->ate.Channel));
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_CHANNEL_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE Tx Power0
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_TX_POWER0_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       CHAR TxPower;
+
+       TxPower = simple_strtol(arg, 0, 10);
+
+       if (pAd->ate.Channel <= 14)
+       {
+               if ((TxPower > 31) || (TxPower < 0))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower));
+                       return FALSE;
+               }
+       }
+       else// 5.5GHz
+       {
+               if ((TxPower > 15) || (TxPower < -7))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower));
+                       return FALSE;
+               }
+       }
+
+       pAd->ate.TxPower0 = TxPower;
+       ATETxPwrHandler(pAd, 0);
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER0_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE Tx Power1
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_TX_POWER1_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       CHAR TxPower;
+
+       TxPower = simple_strtol(arg, 0, 10);
+
+       if (pAd->ate.Channel <= 14)
+       {
+       if ((TxPower > 31) || (TxPower < 0))
+       {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower));
+               return FALSE;
+       }
+       }
+       else
+       {
+               if ((TxPower > 15) || (TxPower < -7))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower));
+                       return FALSE;
+               }
+       }
+
+       pAd->ate.TxPower1 = TxPower;
+       ATETxPwrHandler(pAd, 1);
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER1_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE Tx Antenna
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_TX_Antenna_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       CHAR value;
+
+       value = simple_strtol(arg, 0, 10);
+
+       if ((value > 2) || (value < 0))
+       {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_Antenna_Proc::Out of range (Value=%d)\n", value));
+               return FALSE;
+       }
+
+       pAd->ate.TxAntennaSel = value;
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_Antenna_Proc (Antenna = %d)\n", pAd->ate.TxAntennaSel));
+       ATEDBGPRINT(RT_DEBUG_TRACE,("Ralink: Set_ATE_TX_Antenna_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE Rx Antenna
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_RX_Antenna_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       CHAR value;
+
+       value = simple_strtol(arg, 0, 10);
+
+       if ((value > 3) || (value < 0))
+       {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_RX_Antenna_Proc::Out of range (Value=%d)\n", value));
+               return FALSE;
+       }
+
+       pAd->ate.RxAntennaSel = value;
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_Antenna_Proc (Antenna = %d)\n", pAd->ate.RxAntennaSel));
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_Antenna_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE RF frequence offset
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_TX_FREQOFFSET_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UCHAR RFFreqOffset;
+       ULONG R4;
+
+       RFFreqOffset = simple_strtol(arg, 0, 10);
+
+       if(RFFreqOffset >= 64)
+       {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_FREQOFFSET_Proc::Out of range, it should be in range of 0~63.\n"));
+               return FALSE;
+       }
+
+       pAd->ate.RFFreqOffset = RFFreqOffset;
+       R4 = pAd->ate.RFFreqOffset << 15;               // shift TX power control to correct RF register bit position
+       R4 |= (pAd->LatchRfRegs.R4 & ((~0x001f8000)));
+       pAd->LatchRfRegs.R4 = R4;
+
+       RtmpRfIoWrite(pAd);
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_FREQOFFSET_Proc (RFFreqOffset = %d)\n", pAd->ate.RFFreqOffset));
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_FREQOFFSET_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE RF BW
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_TX_BW_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       int i;
+       UCHAR value = 0;
+       UCHAR BBPCurrentBW;
+
+       BBPCurrentBW = simple_strtol(arg, 0, 10);
+
+       if(BBPCurrentBW == 0)
+               pAd->ate.TxWI.BW = BW_20;
+       else
+               pAd->ate.TxWI.BW = BW_40;
+
+       if(pAd->ate.TxWI.BW == BW_20)
+       {
+               if(pAd->ate.Channel <= 14)
+               {
+               for (i=0; i<5; i++)
+               {
+                               if (pAd->Tx20MPwrCfgGBand[i] != 0xffffffff)
+                               {
+                                       RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgGBand[i]);
+                                       RTMPusecDelay(5000);
+                               }
+                       }
+               }
+               else
+               {
+                       for (i=0; i<5; i++)
+                       {
+                               if (pAd->Tx20MPwrCfgABand[i] != 0xffffffff)
+                       {
+                                       RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgABand[i]);
+                               RTMPusecDelay(5000);
+                       }
+               }
+               }
+
+               //Set BBP R4 bit[4:3]=0:0
+               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value);
+               value &= (~0x18);
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value);
+
+               //Set BBP R66=0x3C
+               value = 0x3C;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value);
+               //Set BBP R68=0x0B
+               //to improve Rx sensitivity.
+               value = 0x0B;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value);
+               //Set BBP R69=0x16
+               value = 0x16;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value);
+               //Set BBP R70=0x08
+               value = 0x08;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value);
+               //Set BBP R73=0x11
+               value = 0x11;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value);
+
+           // If Channel=14, Bandwidth=20M and Mode=CCK, Set BBP R4 bit5=1
+           // (Japan filter coefficients)
+           // This segment of code will only works when ATETXMODE and ATECHANNEL
+           // were set to MODE_CCK and 14 respectively before ATETXBW is set to 0.
+           //=====================================================================
+               if (pAd->ate.Channel == 14)
+               {
+                       int TxMode = pAd->ate.TxWI.PHYMODE;
+                       if (TxMode == MODE_CCK)
+                       {
+                               // when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1
+                               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value);
+                               value |= 0x20; //set bit5=1
+                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value);
+                       }
+               }
+
+           //=====================================================================
+               // If bandwidth != 40M, RF Reg4 bit 21 = 0.
+               pAd->LatchRfRegs.R4 &= ~0x00200000;
+               RtmpRfIoWrite(pAd);
+       }
+       else if(pAd->ate.TxWI.BW == BW_40)
+       {
+               if(pAd->ate.Channel <= 14)
+               {
+                       for (i=0; i<5; i++)
+                       {
+                               if (pAd->Tx40MPwrCfgGBand[i] != 0xffffffff)
+                               {
+                                       RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgGBand[i]);
+                                       RTMPusecDelay(5000);
+                               }
+                       }
+               }
+               else
+               {
+                       for (i=0; i<5; i++)
+                       {
+                               if (pAd->Tx40MPwrCfgABand[i] != 0xffffffff)
+                               {
+                                       RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgABand[i]);
+                                       RTMPusecDelay(5000);
+                               }
+                       }
+#ifdef DOT11_N_SUPPORT
+                       if ((pAd->ate.TxWI.PHYMODE >= MODE_HTMIX) && (pAd->ate.TxWI.MCS == 7))
+                       {
+                       value = 0x28;
+                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value);
+                       }
+#endif // DOT11_N_SUPPORT //
+               }
+
+               //Set BBP R4 bit[4:3]=1:0
+               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value);
+               value &= (~0x18);
+               value |= 0x10;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value);
+
+               //Set BBP R66=0x3C
+               value = 0x3C;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value);
+               //Set BBP R68=0x0C
+               //to improve Rx sensitivity.
+               value = 0x0C;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value);
+               //Set BBP R69=0x1A
+               value = 0x1A;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value);
+               //Set BBP R70=0x0A
+               value = 0x0A;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value);
+               //Set BBP R73=0x16
+               value = 0x16;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value);
+
+               // If bandwidth = 40M, set RF Reg4 bit 21 = 1.
+               pAd->LatchRfRegs.R4 |= 0x00200000;
+               RtmpRfIoWrite(pAd);
+       }
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_BW_Proc (BBPCurrentBW = %d)\n", pAd->ate.TxWI.BW));
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_BW_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE Tx frame length
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_TX_LENGTH_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       pAd->ate.TxLength = simple_strtol(arg, 0, 10);
+
+       if((pAd->ate.TxLength < 24) || (pAd->ate.TxLength > (MAX_FRAME_SIZE - 34/* == 2312 */)))
+       {
+               pAd->ate.TxLength = (MAX_FRAME_SIZE - 34/* == 2312 */);
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_LENGTH_Proc::Out of range, it should be in range of 24~%d.\n", (MAX_FRAME_SIZE - 34/* == 2312 */)));
+               return FALSE;
+       }
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_LENGTH_Proc (TxLength = %d)\n", pAd->ate.TxLength));
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_LENGTH_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE Tx frame count
+
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_TX_COUNT_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       pAd->ate.TxCount = simple_strtol(arg, 0, 10);
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_COUNT_Proc (TxCount = %d)\n", pAd->ate.TxCount));
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_COUNT_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE Tx frame MCS
+
+        Return:
+               TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_TX_MCS_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UCHAR MCS;
+       int result;
+
+       MCS = simple_strtol(arg, 0, 10);
+       result = CheckMCSValid(pAd->ate.TxWI.PHYMODE, MCS);
+
+       if (result != -1)
+       {
+               pAd->ate.TxWI.MCS = (UCHAR)MCS;
+       }
+       else
+       {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MCS_Proc::Out of range, refer to rate table.\n"));
+               return FALSE;
+       }
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MCS_Proc (MCS = %d)\n", pAd->ate.TxWI.MCS));
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MCS_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE Tx frame Mode
+        0: MODE_CCK
+        1: MODE_OFDM
+        2: MODE_HTMIX
+        3: MODE_HTGREENFIELD
+
+        Return:
+               TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_TX_MODE_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       pAd->ate.TxWI.PHYMODE = simple_strtol(arg, 0, 10);
+
+       if(pAd->ate.TxWI.PHYMODE > 3)
+       {
+               pAd->ate.TxWI.PHYMODE = 0;
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MODE_Proc::Out of range. it should be in range of 0~3\n"));
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("0: CCK, 1: OFDM, 2: HT_MIX, 3: HT_GREEN_FIELD.\n"));
+               return FALSE;
+       }
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MODE_Proc (TxMode = %d)\n", pAd->ate.TxWI.PHYMODE));
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MODE_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set ATE Tx frame GI
+
+        Return:
+               TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_ATE_TX_GI_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       pAd->ate.TxWI.ShortGI = simple_strtol(arg, 0, 10);
+
+       if(pAd->ate.TxWI.ShortGI > 1)
+       {
+               pAd->ate.TxWI.ShortGI = 0;
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_GI_Proc::Out of range\n"));
+               return FALSE;
+       }
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_GI_Proc (GI = %d)\n", pAd->ate.TxWI.ShortGI));
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_GI_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+    ==========================================================================
+ */
+INT    Set_ATE_RX_FER_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       pAd->ate.bRxFer = simple_strtol(arg, 0, 10);
+
+       if (pAd->ate.bRxFer == 1)
+       {
+               pAd->ate.RxCntPerSec = 0;
+               pAd->ate.RxTotalCnt = 0;
+       }
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_FER_Proc (bRxFer = %d)\n", pAd->ate.bRxFer));
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_FER_Proc Success\n"));
+
+
+       return TRUE;
+}
+
+INT Set_ATE_Read_RF_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ate_print(KERN_EMERG "R1 = %lx\n", pAd->LatchRfRegs.R1);
+       ate_print(KERN_EMERG "R2 = %lx\n", pAd->LatchRfRegs.R2);
+       ate_print(KERN_EMERG "R3 = %lx\n", pAd->LatchRfRegs.R3);
+       ate_print(KERN_EMERG "R4 = %lx\n", pAd->LatchRfRegs.R4);
+
+       return TRUE;
+}
+
+INT Set_ATE_Write_RF1_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UINT32 value = simple_strtol(arg, 0, 16);
+
+       pAd->LatchRfRegs.R1 = value;
+       RtmpRfIoWrite(pAd);
+
+       return TRUE;
+}
+
+INT Set_ATE_Write_RF2_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UINT32 value = simple_strtol(arg, 0, 16);
+
+       pAd->LatchRfRegs.R2 = value;
+       RtmpRfIoWrite(pAd);
+
+       return TRUE;
+}
+
+INT Set_ATE_Write_RF3_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UINT32 value = simple_strtol(arg, 0, 16);
+
+       pAd->LatchRfRegs.R3 = value;
+       RtmpRfIoWrite(pAd);
+
+       return TRUE;
+}
+
+INT Set_ATE_Write_RF4_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UINT32 value = simple_strtol(arg, 0, 16);
+
+       pAd->LatchRfRegs.R4 = value;
+       RtmpRfIoWrite(pAd);
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Load and Write EEPROM from a binary file prepared in advance.
+
+        Return:
+               TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+#ifndef UCOS
+INT Set_ATE_Load_E2P_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       BOOLEAN             ret = FALSE;
+       PUCHAR                  src = EEPROM_BIN_FILE_NAME;
+       struct file             *srcf;
+       INT32                   retval, orgfsuid, orgfsgid;
+       mm_segment_t    orgfs;
+       USHORT                  WriteEEPROM[(EEPROM_SIZE/2)];
+       UINT32                  FileLength = 0;
+       UINT32                  value = simple_strtol(arg, 0, 10);
+
+       ATEDBGPRINT(RT_DEBUG_ERROR, ("===> %s (value=%d)\n\n", __FUNCTION__, value));
+
+       if (value > 0)
+       {
+               /* zero the e2p buffer */
+               NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE);
+
+               /* save uid and gid used for filesystem access.
+           ** set user and group to 0 (root)
+           */
+               orgfsuid = current->fsuid;
+               orgfsgid = current->fsgid;
+               /* as root */
+               current->fsuid = current->fsgid = 0;
+       orgfs = get_fs();
+       set_fs(KERNEL_DS);
+
+               do
+               {
+                       /* open the bin file */
+                       srcf = filp_open(src, O_RDONLY, 0);
+
+                       if (IS_ERR(srcf))
+                       {
+                               ate_print("%s - Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(srcf), src);
+                               break;
+                       }
+
+                       /* the object must have a read method */
+                       if ((srcf->f_op == NULL) || (srcf->f_op->read == NULL))
+                       {
+                               ate_print("%s - %s does not have a read method\n", __FUNCTION__, src);
+                               break;
+                       }
+
+                       /* read the firmware from the file *.bin */
+                       FileLength = srcf->f_op->read(srcf,
+                                                                                 (PUCHAR)WriteEEPROM,
+                                                                                 EEPROM_SIZE,
+                                                                                 &srcf->f_pos);
+
+                       if (FileLength != EEPROM_SIZE)
+                       {
+                               ate_print("%s: error file length (=%d) in e2p.bin\n",
+                                          __FUNCTION__, FileLength);
+                               break;
+                       }
+                       else
+                       {
+                               /* write the content of .bin file to EEPROM */
+                               rt_ee_write_all(pAd, WriteEEPROM);
+                               ret = TRUE;
+                       }
+                       break;
+               } while(TRUE);
+
+               /* close firmware file */
+               if (IS_ERR(srcf))
+               {
+                               ;
+               }
+               else
+               {
+                       retval = filp_close(srcf, NULL);
+                       if (retval)
+                       {
+                               ATEDBGPRINT(RT_DEBUG_ERROR, ("--> Error %d closing %s\n", -retval, src));
+
+                       }
+               }
+
+               /* restore */
+               set_fs(orgfs);
+               current->fsuid = orgfsuid;
+               current->fsgid = orgfsgid;
+       }
+    ATEDBGPRINT(RT_DEBUG_ERROR, ("<=== %s (ret=%d)\n", __FUNCTION__, ret));
+
+    return ret;
+
+}
+#else
+INT Set_ATE_Load_E2P_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       USHORT                  WriteEEPROM[(EEPROM_SIZE/2)];
+       struct iwreq    *wrq = (struct iwreq *)arg;
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("===> %s (wrq->u.data.length = %d)\n\n", __FUNCTION__, wrq->u.data.length));
+
+       if (wrq->u.data.length != EEPROM_SIZE)
+       {
+               ate_print("%s: error length (=%d) from host\n",
+                          __FUNCTION__, wrq->u.data.length);
+               return FALSE;
+       }
+       else/* (wrq->u.data.length == EEPROM_SIZE) */
+       {
+               /* zero the e2p buffer */
+               NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE);
+
+               /* fill the local buffer */
+               NdisMoveMemory((PUCHAR)WriteEEPROM, wrq->u.data.pointer, wrq->u.data.length);
+
+               do
+               {
+                               /* write the content of .bin file to EEPROM */
+                               rt_ee_write_all(pAd, WriteEEPROM);
+
+               } while(FALSE);
+               }
+
+    ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== %s\n", __FUNCTION__));
+
+    return TRUE;
+
+}
+#endif // !UCOS //
+
+INT Set_ATE_Read_E2P_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       USHORT buffer[EEPROM_SIZE/2];
+       USHORT *p;
+       int i;
+
+       rt_ee_read_all(pAd, (USHORT *)buffer);
+       p = buffer;
+       for (i = 0; i < (EEPROM_SIZE/2); i++)
+       {
+               ate_print("%4.4x ", *p);
+               if (((i+1) % 16) == 0)
+                       ate_print("\n");
+               p++;
+       }
+       return TRUE;
+}
+
+INT    Set_ATE_Show_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ate_print("Mode=%d\n", pAd->ate.Mode);
+       ate_print("TxPower0=%d\n", pAd->ate.TxPower0);
+       ate_print("TxPower1=%d\n", pAd->ate.TxPower1);
+       ate_print("TxAntennaSel=%d\n", pAd->ate.TxAntennaSel);
+       ate_print("RxAntennaSel=%d\n", pAd->ate.RxAntennaSel);
+       ate_print("BBPCurrentBW=%d\n", pAd->ate.TxWI.BW);
+       ate_print("GI=%d\n", pAd->ate.TxWI.ShortGI);
+       ate_print("MCS=%d\n", pAd->ate.TxWI.MCS);
+       ate_print("TxMode=%d\n", pAd->ate.TxWI.PHYMODE);
+       ate_print("Addr1=%02x:%02x:%02x:%02x:%02x:%02x\n",
+               pAd->ate.Addr1[0], pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5]);
+       ate_print("Addr2=%02x:%02x:%02x:%02x:%02x:%02x\n",
+               pAd->ate.Addr2[0], pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5]);
+       ate_print("Addr3=%02x:%02x:%02x:%02x:%02x:%02x\n",
+               pAd->ate.Addr3[0], pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5]);
+       ate_print("Channel=%d\n", pAd->ate.Channel);
+       ate_print("TxLength=%d\n", pAd->ate.TxLength);
+       ate_print("TxCount=%u\n", pAd->ate.TxCount);
+       ate_print("RFFreqOffset=%d\n", pAd->ate.RFFreqOffset);
+       ate_print(KERN_EMERG "Set_ATE_Show_Proc Success\n");
+       return TRUE;
+}
+
+INT    Set_ATE_Help_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ate_print("ATE=ATESTART, ATESTOP, TXCONT, TXCARR, TXFRAME, RXFRAME\n");
+       ate_print("ATEDA\n");
+       ate_print("ATESA\n");
+       ate_print("ATEBSSID\n");
+       ate_print("ATECHANNEL, range:0~14(unless A band !)\n");
+       ate_print("ATETXPOW0, set power level of antenna 1.\n");
+       ate_print("ATETXPOW1, set power level of antenna 2.\n");
+       ate_print("ATETXANT, set TX antenna. 0:all, 1:antenna one, 2:antenna two.\n");
+       ate_print("ATERXANT, set RX antenna.0:all, 1:antenna one, 2:antenna two, 3:antenna three.\n");
+       ate_print("ATETXFREQOFFSET, set frequency offset, range 0~63\n");
+       ate_print("ATETXBW, set BandWidth, 0:20MHz, 1:40MHz.\n");
+       ate_print("ATETXLEN, set Frame length, range 24~%d\n", (MAX_FRAME_SIZE - 34/* == 2312 */));
+       ate_print("ATETXCNT, set how many frame going to transmit.\n");
+       ate_print("ATETXMCS, set MCS, reference to rate table.\n");
+       ate_print("ATETXMODE, set Mode 0:CCK, 1:OFDM, 2:HT-Mix, 3:GreenField, reference to rate table.\n");
+       ate_print("ATETXGI, set GI interval, 0:Long, 1:Short\n");
+       ate_print("ATERXFER, 0:disable Rx Frame error rate. 1:enable Rx Frame error rate.\n");
+       ate_print("ATERRF, show all RF registers.\n");
+       ate_print("ATEWRF1, set RF1 register.\n");
+       ate_print("ATEWRF2, set RF2 register.\n");
+       ate_print("ATEWRF3, set RF3 register.\n");
+       ate_print("ATEWRF4, set RF4 register.\n");
+       ate_print("ATELDE2P, load EEPROM from .bin file.\n");
+       ate_print("ATERE2P, display all EEPROM content.\n");
+       ate_print("ATESHOW, display all parameters of ATE.\n");
+       ate_print("ATEHELP, online help.\n");
+
+       return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       AsicSwitchChannel() dedicated for ATE.
+
+    ==========================================================================
+*/
+VOID ATEAsicSwitchChannel(
+    IN PRTMP_ADAPTER pAd)
+{
+       UINT32 R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0, Value = 0;
+       CHAR TxPwer = 0, TxPwer2 = 0;
+       UCHAR index, BbpValue = 0, R66 = 0x30;
+       RTMP_RF_REGS *RFRegTable;
+       UCHAR Channel;
+
+#ifdef RALINK_28xx_QA
+       if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE))
+       {
+               if (pAd->ate.Channel != pAd->LatchRfRegs.Channel)
+               {
+                       pAd->ate.Channel = pAd->LatchRfRegs.Channel;
+               }
+               return;
+       }
+       else
+#endif // RALINK_28xx_QA //
+       Channel = pAd->ate.Channel;
+
+       // Select antenna
+       AsicAntennaSelect(pAd, Channel);
+
+       // fill Tx power value
+       TxPwer = pAd->ate.TxPower0;
+       TxPwer2 = pAd->ate.TxPower1;
+
+       RFRegTable = RF2850RegTable;
+
+       switch (pAd->RfIcType)
+       {
+               /* But only 2850 and 2750 support 5.5GHz band... */
+               case RFIC_2820:
+               case RFIC_2850:
+               case RFIC_2720:
+               case RFIC_2750:
+
+                       for (index = 0; index < NUM_OF_2850_CHNL; index++)
+                       {
+                               if (Channel == RFRegTable[index].Channel)
+                               {
+                                       R2 = RFRegTable[index].R2;
+                                       if (pAd->Antenna.field.TxPath == 1)
+                                       {
+                                               R2 |= 0x4000;   // If TXpath is 1, bit 14 = 1;
+                                       }
+
+                                       if (pAd->Antenna.field.RxPath == 2)
+                                       {
+                                               switch (pAd->ate.RxAntennaSel)
+                                               {
+                                                       case 1:
+                                                               R2 |= 0x20040;
+                                                               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+                                                               BbpValue &= 0xE4;
+                                                               BbpValue |= 0x00;
+                                                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+                                                               break;
+                                                       case 2:
+                                                               R2 |= 0x10040;
+                                                               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+                                                               BbpValue &= 0xE4;
+                                                               BbpValue |= 0x01;
+                                                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+                                                               break;
+                                                       default:
+                                                               R2 |= 0x40;
+                                                               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+                                                               BbpValue &= 0xE4;
+                                                               /* Only enable two Antenna to receive. */
+                                                               BbpValue |= 0x08;
+                                                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+                                                               break;
+                                               }
+                                       }
+                                       else if (pAd->Antenna.field.RxPath == 1)
+                                       {
+                                               R2 |= 0x20040;  // write 1 to off RxPath
+                                       }
+
+                                       if (pAd->Antenna.field.TxPath == 2)
+                                       {
+                                               if (pAd->ate.TxAntennaSel == 1)
+                                               {
+                                                       R2 |= 0x4000;   // If TX Antenna select is 1 , bit 14 = 1; Disable Ant 2
+                                                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue);
+                                                       BbpValue &= 0xE7;               //11100111B
+                                                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue);
+                                               }
+                                               else if (pAd->ate.TxAntennaSel == 2)
+                                               {
+                                                       R2 |= 0x8000;   // If TX Antenna select is 2 , bit 15 = 1; Disable Ant 1
+                                                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue);
+                                                       BbpValue &= 0xE7;
+                                                       BbpValue |= 0x08;
+                                                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue);
+                                               }
+                                               else
+                                               {
+                                                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue);
+                                                       BbpValue &= 0xE7;
+                                                       BbpValue |= 0x10;
+                                                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue);
+                                               }
+                                       }
+                                       if (pAd->Antenna.field.RxPath == 3)
+                                       {
+                                               switch (pAd->ate.RxAntennaSel)
+                                               {
+                                                       case 1:
+                                                               R2 |= 0x20040;
+                                                               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+                                                               BbpValue &= 0xE4;
+                                                               BbpValue |= 0x00;
+                                                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+                                                               break;
+                                                       case 2:
+                                                               R2 |= 0x10040;
+                                                               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+                                                               BbpValue &= 0xE4;
+                                                               BbpValue |= 0x01;
+                                                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+                                                               break;
+                                                       case 3:
+                                                               R2 |= 0x30000;
+                                                               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+                                                               BbpValue &= 0xE4;
+                                                               BbpValue |= 0x02;
+                                                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+                                                               break;
+                                                       default:
+                                                               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+                                                               BbpValue &= 0xE4;
+                                                               BbpValue |= 0x10;
+                                                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+                                                               break;
+                                               }
+                                       }
+
+                                       if (Channel > 14)
+                                       {
+                                               // initialize R3, R4
+                                               R3 = (RFRegTable[index].R3 & 0xffffc1ff);
+                                               R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15);
+
+                        // According the Rory's suggestion to solve the middle range issue.
+                                               // 5.5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
+                                               // R3
+                                               if ((TxPwer >= -7) && (TxPwer < 0))
+                                               {
+                                                       TxPwer = (7+TxPwer);
+                                                       TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
+                                                       R3 |= (TxPwer << 10);
+                                                       ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer=%d \n", TxPwer));
+                                               }
+                                               else
+                                               {
+                                                       TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
+                                                       R3 |= (TxPwer << 10) | (1 << 9);
+                                               }
+
+                                               // R4
+                                               if ((TxPwer2 >= -7) && (TxPwer2 < 0))
+                                               {
+                                                       TxPwer2 = (7+TxPwer2);
+                                                       TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
+                                                       R4 |= (TxPwer2 << 7);
+                                                       ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
+                                               }
+                                               else
+                                               {
+                                                       TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
+                                                       R4 |= (TxPwer2 << 7) | (1 << 6);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
+                                               R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15) | (TxPwer2 <<6);// Set freq offset & TxPwr1
+                                       }
+
+                                       // Based on BBP current mode before changing RF channel.
+                                       if (pAd->ate.TxWI.BW == BW_40)
+                                       {
+                                               R4 |=0x200000;
+                                       }
+
+                                       // Update variables
+                                       pAd->LatchRfRegs.Channel = Channel;
+                                       pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
+                                       pAd->LatchRfRegs.R2 = R2;
+                                       pAd->LatchRfRegs.R3 = R3;
+                                       pAd->LatchRfRegs.R4 = R4;
+
+                                       RtmpRfIoWrite(pAd);
+
+                                       break;
+                               }
+                       }
+                       break;
+
+               default:
+                       break;
+       }
+
+       // Change BBP setting during switch from a->g, g->a
+       if (Channel <= 14)
+       {
+           ULONG       TxPinCfg = 0x00050F0A;// 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A
+
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
+
+               /* For 1T/2R chip only... */
+           if (pAd->NicConfig2.field.ExternalLNAForG)
+           {
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
+           }
+           else
+           {
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
+           }
+
+        // According the Rory's suggestion to solve the middle range issue.
+               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue);
+               ASSERT((BbpValue == 0x00));
+               if ((BbpValue != 0x00))
+               {
+                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00);
+               }
+
+               // 5.5GHz band selection PIN, bit1 and bit2 are complement
+               RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
+               Value &= (~0x6);
+               Value |= (0x04);
+               RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+
+        // Turn off unused PA or LNA when only 1T or 1R.
+               if (pAd->Antenna.field.TxPath == 1)
+               {
+                       TxPinCfg &= 0xFFFFFFF3;
+               }
+               if (pAd->Antenna.field.RxPath == 1)
+               {
+                       TxPinCfg &= 0xFFFFF3FF;
+               }
+
+               RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
+       }
+       else
+       {
+           ULONG       TxPinCfg = 0x00050F05;//2007.10.09 by Brian : 0x00050505 ==> 0x00050F05
+
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
+
+        // According the Rory's suggestion to solve the middle range issue.
+               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue);
+               ASSERT((BbpValue == 0x00));
+               if ((BbpValue != 0x00))
+               {
+                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00);
+               }
+               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue);
+               ASSERT((BbpValue == 0x04));
+
+               ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R92, &BbpValue);
+               ASSERT((BbpValue == 0x00));
+
+               // 5.5GHz band selection PIN, bit1 and bit2 are complement
+               RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
+               Value &= (~0x6);
+               Value |= (0x02);
+               RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+
+        // Turn off unused PA or LNA when only 1T or 1R.
+               if (pAd->Antenna.field.TxPath == 1)
+               {
+                       TxPinCfg &= 0xFFFFFFF3;
+           }
+               if (pAd->Antenna.field.RxPath == 1)
+               {
+                       TxPinCfg &= 0xFFFFF3FF;
+               }
+
+               RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
+       }
+
+    // R66 should be set according to Channel and use 20MHz when scanning
+       if (Channel <= 14)
+       {
+               // BG band
+               R66 = 0x2E + GET_LNA_GAIN(pAd);
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+       }
+       else
+       {
+               // 5.5 GHz band
+               if (pAd->ate.TxWI.BW == BW_20)
+               {
+                       R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+               }
+               else
+               {
+                       R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
+                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+               }
+       }
+
+       //
+       // On 11A, We should delay and wait RF/BBP to be stable
+       // and the appropriate time should be 1000 micro seconds
+       // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
+       //
+       RTMPusecDelay(1000);
+
+       if (Channel > 14)
+       {
+               // When 5.5GHz band the LSB of TxPwr will be used to reduced 7dB or not.
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n",
+                                                                 Channel,
+                                                                 pAd->RfIcType,
+                                                                 pAd->Antenna.field.TxPath,
+                                                                 pAd->LatchRfRegs.R1,
+                                                                 pAd->LatchRfRegs.R2,
+                                                                 pAd->LatchRfRegs.R3,
+                                                                 pAd->LatchRfRegs.R4));
+       }
+       else
+       {
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%u, Pwr1=%u, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n",
+                                                                 Channel,
+                                                                 pAd->RfIcType,
+                                                                 (R3 & 0x00003e00) >> 9,
+                                                                 (R4 & 0x000007c0) >> 6,
+                                                                 pAd->Antenna.field.TxPath,
+                                                                 pAd->LatchRfRegs.R1,
+                                                                 pAd->LatchRfRegs.R2,
+                                                                 pAd->LatchRfRegs.R3,
+                                                                 pAd->LatchRfRegs.R4));
+    }
+}
+
+//
+// In fact, no one will call this routine so far !
+//
+/*
+       ==========================================================================
+       Description:
+               Gives CCK TX rate 2 more dB TX power.
+               This routine works only in ATE mode.
+
+               calculate desired Tx power in RF R3.Tx0~5,      should consider -
+               0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
+               1. TxPowerPercentage
+               2. auto calibration based on TSSI feedback
+               3. extra 2 db for CCK
+               4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
+
+       NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
+               it should be called AFTER MlmeDynamicTxRateSwitching()
+       ==========================================================================
+ */
+VOID ATEAsicAdjustTxPower(
+       IN PRTMP_ADAPTER pAd)
+{
+       INT                     i, j;
+       CHAR            DeltaPwr = 0;
+       BOOLEAN         bAutoTxAgc = FALSE;
+       UCHAR           TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
+       UCHAR           BbpR49 = 0, idx;
+       PCHAR           pTxAgcCompensate;
+       ULONG           TxPwr[5];
+       CHAR            Value;
+
+       /* no one calls this procedure so far */
+       if (pAd->ate.TxWI.BW == BW_40)
+       {
+               if (pAd->ate.Channel > 14)
+               {
+                       TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
+                       TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
+                       TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
+                       TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
+                       TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
+               }
+               else
+               {
+                       TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
+                       TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
+                       TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
+                       TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
+                       TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
+               }
+       }
+       else
+       {
+               if (pAd->ate.Channel > 14)
+               {
+                       TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
+                       TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
+                       TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
+                       TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
+                       TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
+               }
+               else
+               {
+                       TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
+                       TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
+                       TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
+                       TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
+                       TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
+               }
+       }
+
+       // TX power compensation for temperature variation based on TSSI.
+       // Do it per 4 seconds.
+       if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
+       {
+               if (pAd->ate.Channel <= 14)
+               {
+                       /* bg channel */
+                       bAutoTxAgc         = pAd->bAutoTxAgcG;
+                       TssiRef            = pAd->TssiRefG;
+                       pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
+                       pTssiPlusBoundary  = &pAd->TssiPlusBoundaryG[0];
+                       TxAgcStep          = pAd->TxAgcStepG;
+                       pTxAgcCompensate   = &pAd->TxAgcCompensateG;
+               }
+               else
+               {
+                       /* a channel */
+                       bAutoTxAgc         = pAd->bAutoTxAgcA;
+                       TssiRef            = pAd->TssiRefA;
+                       pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
+                       pTssiPlusBoundary  = &pAd->TssiPlusBoundaryA[0];
+                       TxAgcStep          = pAd->TxAgcStepA;
+                       pTxAgcCompensate   = &pAd->TxAgcCompensateA;
+               }
+
+               if (bAutoTxAgc)
+               {
+                       /* BbpR49 is unsigned char */
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
+
+                       /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
+                       /* compensate: +4     +3   +2   +1    0   -1   -2   -3   -4 * steps */
+                       /* step value is defined in pAd->TxAgcStepG for tx power value */
+
+                       /* [4]+1+[4]   p4     p3   p2   p1   o1   m1   m2   m3   m4 */
+                       /* ex:         0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
+                          above value are examined in mass factory production */
+                       /*             [4]    [3]  [2]  [1]  [0]  [1]  [2]  [3]  [4] */
+
+                       /* plus is 0x10 ~ 0x40, minus is 0x60 ~ 0x90 */
+                       /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
+                       /* if value is 0x65, tx power will be -= TxAgcStep*(2-1) */
+
+                       if (BbpR49 > pTssiMinusBoundary[1])
+                       {
+                               // Reading is larger than the reference value.
+                               // Check for how large we need to decrease the Tx power.
+                               for (idx = 1; idx < 5; idx++)
+                               {
+                                       if (BbpR49 <= pTssiMinusBoundary[idx])  // Found the range
+                                               break;
+                               }
+                               // The index is the step we should decrease, idx = 0 means there is nothing to compensate
+//                             if (R3 > (ULONG) (TxAgcStep * (idx-1)))
+                                       *pTxAgcCompensate = -(TxAgcStep * (idx-1));
+//                             else
+//                                     *pTxAgcCompensate = -((UCHAR)R3);
+
+                               DeltaPwr += (*pTxAgcCompensate);
+                               ATEDBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
+                                       BbpR49, TssiRef, TxAgcStep, idx-1));
+                       }
+                       else if (BbpR49 < pTssiPlusBoundary[1])
+                       {
+                               // Reading is smaller than the reference value
+                               // check for how large we need to increase the Tx power
+                               for (idx = 1; idx < 5; idx++)
+                               {
+                                       if (BbpR49 >= pTssiPlusBoundary[idx])   // Found the range
+                                               break;
+                               }
+                               // The index is the step we should increase, idx = 0 means there is nothing to compensate
+                               *pTxAgcCompensate = TxAgcStep * (idx-1);
+                               DeltaPwr += (*pTxAgcCompensate);
+                               ATEDBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
+                                       BbpR49, TssiRef, TxAgcStep, idx-1));
+                       }
+                       else
+                       {
+                               *pTxAgcCompensate = 0;
+                               ATEDBGPRINT(RT_DEBUG_TRACE, ("   Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
+                                       BbpR49, TssiRef, TxAgcStep, 0));
+                       }
+               }
+       }
+       else
+       {
+               if (pAd->ate.Channel <= 14)
+               {
+                       bAutoTxAgc         = pAd->bAutoTxAgcG;
+                       pTxAgcCompensate   = &pAd->TxAgcCompensateG;
+               }
+               else
+               {
+                       bAutoTxAgc         = pAd->bAutoTxAgcA;
+                       pTxAgcCompensate   = &pAd->TxAgcCompensateA;
+               }
+
+               if (bAutoTxAgc)
+                       DeltaPwr += (*pTxAgcCompensate);
+       }
+
+       /* calculate delta power based on the percentage specified from UI */
+       // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
+       // We lower TX power here according to the percentage specified from UI
+       if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff)       // AUTO TX POWER control
+               ;
+       else if (pAd->CommonCfg.TxPowerPercentage > 90)  // 91 ~ 100% & AUTO, treat as 100% in terms of mW
+               ;
+       else if (pAd->CommonCfg.TxPowerPercentage > 60)  // 61 ~ 90%, treat as 75% in terms of mW
+       {
+               DeltaPwr -= 1;
+       }
+       else if (pAd->CommonCfg.TxPowerPercentage > 30)  // 31 ~ 60%, treat as 50% in terms of mW
+       {
+               DeltaPwr -= 3;
+       }
+       else if (pAd->CommonCfg.TxPowerPercentage > 15)  // 16 ~ 30%, treat as 25% in terms of mW
+       {
+               DeltaPwr -= 6;
+       }
+       else if (pAd->CommonCfg.TxPowerPercentage > 9)   // 10 ~ 15%, treat as 12.5% in terms of mW
+       {
+               DeltaPwr -= 9;
+       }
+       else                                           // 0 ~ 9 %, treat as MIN(~3%) in terms of mW
+       {
+               DeltaPwr -= 12;
+       }
+
+       /* reset different new tx power for different TX rate */
+       for(i=0; i<5; i++)
+       {
+               if (TxPwr[i] != 0xffffffff)
+               {
+                       for (j=0; j<8; j++)
+                       {
+                               Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
+
+                               if ((Value + DeltaPwr) < 0)
+                               {
+                                       Value = 0; /* min */
+                               }
+                               else if ((Value + DeltaPwr) > 0xF)
+                               {
+                                       Value = 0xF; /* max */
+                               }
+                               else
+                               {
+                                       Value += DeltaPwr; /* temperature compensation */
+                               }
+
+                               /* fill new value to CSR offset */
+                               TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
+                       }
+
+                       /* write tx power value to CSR */
+                       /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
+                                                                                       TX power for OFDM 6M/9M
+                                                                                       TX power for CCK5.5M/11M
+                                                                                       TX power for CCK1M/2M */
+                       /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
+                       RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
+
+
+               }
+       }
+
+}
+
+/*
+       ========================================================================
+       Routine Description:
+               Write TxWI for ATE mode.
+
+       Return Value:
+               None
+       ========================================================================
+*/
+
+#ifdef RT2870
+static VOID ATEWriteTxWI(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTXWI_STRUC     pTxWI,
+       IN      BOOLEAN                 FRAG,
+       IN      BOOLEAN                 InsTimestamp,
+       IN      BOOLEAN                 AMPDU,
+       IN      BOOLEAN                 Ack,
+       IN      BOOLEAN                 NSeq,           // HW new a sequence.
+       IN      UCHAR                   BASize,
+       IN      UCHAR                   WCID,
+       IN      ULONG                   Length,
+       IN      UCHAR                   PID,
+       IN      UCHAR                   MIMOps,
+       IN      UCHAR                   Txopmode,
+       IN      BOOLEAN                 CfAck,
+       IN      HTTRANSMIT_SETTING      Transmit)
+{
+       //
+       // Always use Long preamble before verifiation short preamble functionality works well.
+       // Todo: remove the following line if short preamble functionality works
+       //
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+       pTxWI->FRAG= FRAG;
+       pTxWI->TS= InsTimestamp;
+       pTxWI->AMPDU = AMPDU;
+
+       pTxWI->MIMOps = PWR_ACTIVE;
+       pTxWI->MpduDensity = 4;
+       pTxWI->ACK = Ack;
+       pTxWI->txop = Txopmode;
+       pTxWI->NSEQ = NSeq;
+       pTxWI->BAWinSize = BASize;
+
+       pTxWI->WirelessCliID = WCID;
+       pTxWI->MPDUtotalByteCount = Length;
+       pTxWI->PacketId = PID;
+
+       pTxWI->BW = Transmit.field.BW;
+       pTxWI->ShortGI = Transmit.field.ShortGI;
+       pTxWI->STBC= Transmit.field.STBC;
+
+       pTxWI->MCS = Transmit.field.MCS;
+       pTxWI->PHYMODE= Transmit.field.MODE;
+
+#ifdef DOT11_N_SUPPORT
+       //
+       // MMPS is 802.11n features. Because TxWI->MCS > 7 must be HT mode,
+       // so need not check if it's HT rate.
+       //
+       if ((MIMOps == MMPS_STATIC) && (pTxWI->MCS > 7))
+               pTxWI->MCS = 7;
+
+       if ((MIMOps == MMPS_DYNAMIC) && (pTxWI->MCS > 7)) // SMPS protect 2 spatial.
+               pTxWI->MIMOps = 1;
+#endif // DOT11_N_SUPPORT //
+
+       pTxWI->CFACK = CfAck;
+
+       return;
+}
+#endif // RT2870 //
+/*
+       ========================================================================
+
+       Routine Description:
+               Disable protection for ATE.
+       ========================================================================
+*/
+VOID ATEDisableAsicProtect(
+       IN              PRTMP_ADAPTER   pAd)
+{
+       PROT_CFG_STRUC  ProtCfg, ProtCfg4;
+       UINT32 Protect[6];
+       USHORT                  offset;
+       UCHAR                   i;
+       UINT32 MacReg = 0;
+
+       // Config ASIC RTS threshold register
+       RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
+       MacReg &= 0xFF0000FF;
+       MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
+       RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
+
+       // Initial common protection settings
+       RTMPZeroMemory(Protect, sizeof(Protect));
+       ProtCfg4.word = 0;
+       ProtCfg.word = 0;
+       ProtCfg.field.TxopAllowGF40 = 1;
+       ProtCfg.field.TxopAllowGF20 = 1;
+       ProtCfg.field.TxopAllowMM40 = 1;
+       ProtCfg.field.TxopAllowMM20 = 1;
+       ProtCfg.field.TxopAllowOfdm = 1;
+       ProtCfg.field.TxopAllowCck = 1;
+       ProtCfg.field.RTSThEn = 1;
+       ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+
+       // Handle legacy(B/G) protection
+       ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
+       ProtCfg.field.ProtectCtrl = 0;
+       Protect[0] = ProtCfg.word;
+       Protect[1] = ProtCfg.word;
+
+       // NO PROTECT
+       // 1.All STAs in the BSS are 20/40 MHz HT
+       // 2. in ai 20/40MHz BSS
+       // 3. all STAs are 20MHz in a 20MHz BSS
+       // Pure HT. no protection.
+
+       // MM20_PROT_CFG
+       //      Reserved (31:27)
+       //      PROT_TXOP(25:20) -- 010111
+       //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
+       //  PROT_CTRL(17:16) -- 00 (None)
+       //      PROT_RATE(15:0)  -- 0x4004 (OFDM 24M)
+       Protect[2] = 0x01744004;
+
+       // MM40_PROT_CFG
+       //      Reserved (31:27)
+       //      PROT_TXOP(25:20) -- 111111
+       //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
+       //  PROT_CTRL(17:16) -- 00 (None)
+       //      PROT_RATE(15:0)  -- 0x4084 (duplicate OFDM 24M)
+       Protect[3] = 0x03f44084;
+
+       // CF20_PROT_CFG
+       //      Reserved (31:27)
+       //      PROT_TXOP(25:20) -- 010111
+       //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
+       //  PROT_CTRL(17:16) -- 00 (None)
+       //      PROT_RATE(15:0)  -- 0x4004 (OFDM 24M)
+       Protect[4] = 0x01744004;
+
+       // CF40_PROT_CFG
+       //      Reserved (31:27)
+       //      PROT_TXOP(25:20) -- 111111
+       //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
+       //  PROT_CTRL(17:16) -- 00 (None)
+       //      PROT_RATE(15:0)  -- 0x4084 (duplicate OFDM 24M)
+       Protect[5] = 0x03f44084;
+
+       pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
+
+       offset = CCK_PROT_CFG;
+       for (i = 0;i < 6;i++)
+               RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
+
+}
+
+#ifdef RT2870
+/*
+       ========================================================================
+       Routine Description:
+               Write TxInfo for ATE mode.
+
+       Return Value:
+               None
+       ========================================================================
+*/
+static VOID ATEWriteTxInfo(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTXINFO_STRUC   pTxInfo,
+       IN      USHORT          USBDMApktLen,
+       IN      BOOLEAN         bWiv,
+       IN      UCHAR                   QueueSel,
+       IN      UCHAR                   NextValid,
+       IN      UCHAR                   TxBurst)
+{
+       pTxInfo->USBDMATxPktLen = USBDMApktLen;
+       pTxInfo->QSEL = QueueSel;
+
+       if (QueueSel != FIFO_EDCA)
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("=======> QueueSel != FIFO_EDCA<=======\n"));
+
+       pTxInfo->USBDMANextVLD = NextValid;
+       pTxInfo->USBDMATxburst = TxBurst;
+       pTxInfo->WIV = bWiv;
+       pTxInfo->SwUseLastRound = 0;
+       pTxInfo->rsv = 0;
+       pTxInfo->rsv2 = 0;
+
+       return;
+}
+#endif // RT2870 //
+
+/* There are two ways to convert Rssi */
+#if 1
+//
+// The way used with GET_LNA_GAIN().
+//
+CHAR ATEConvertToRssi(
+       IN PRTMP_ADAPTER pAd,
+       IN      CHAR    Rssi,
+       IN  UCHAR   RssiNumber)
+{
+       UCHAR   RssiOffset, LNAGain;
+
+       // Rssi equals to zero should be an invalid value
+       if (Rssi == 0)
+               return -99;
+
+       LNAGain = GET_LNA_GAIN(pAd);
+       if (pAd->LatchRfRegs.Channel > 14)
+       {
+               if (RssiNumber == 0)
+                       RssiOffset = pAd->ARssiOffset0;
+               else if (RssiNumber == 1)
+                       RssiOffset = pAd->ARssiOffset1;
+               else
+                       RssiOffset = pAd->ARssiOffset2;
+       }
+       else
+       {
+               if (RssiNumber == 0)
+                       RssiOffset = pAd->BGRssiOffset0;
+               else if (RssiNumber == 1)
+                       RssiOffset = pAd->BGRssiOffset1;
+               else
+                       RssiOffset = pAd->BGRssiOffset2;
+       }
+
+       return (-12 - RssiOffset - LNAGain - Rssi);
+}
+#else
+//
+// The way originally used in ATE of rt2860ap.
+//
+CHAR ATEConvertToRssi(
+       IN PRTMP_ADAPTER pAd,
+       IN      CHAR                    Rssi,
+       IN  UCHAR   RssiNumber)
+{
+       UCHAR   RssiOffset, LNAGain;
+
+       // Rssi equals to zero should be an invalid value
+       if (Rssi == 0)
+               return -99;
+
+    if (pAd->LatchRfRegs.Channel > 14)
+    {
+        LNAGain = pAd->ALNAGain;
+        if (RssiNumber == 0)
+                       RssiOffset = pAd->ARssiOffset0;
+               else if (RssiNumber == 1)
+                       RssiOffset = pAd->ARssiOffset1;
+               else
+                       RssiOffset = pAd->ARssiOffset2;
+    }
+    else
+    {
+        LNAGain = pAd->BLNAGain;
+        if (RssiNumber == 0)
+                       RssiOffset = pAd->BGRssiOffset0;
+               else if (RssiNumber == 1)
+                       RssiOffset = pAd->BGRssiOffset1;
+               else
+                       RssiOffset = pAd->BGRssiOffset2;
+    }
+
+    return (-32 - RssiOffset + LNAGain - Rssi);
+}
+#endif /* end of #if 1 */
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Set Japan filter coefficients if needed.
+       Note:
+               This routine should only be called when
+               entering TXFRAME mode or TXCONT mode.
+
+       ========================================================================
+*/
+static VOID SetJapanFilter(
+       IN              PRTMP_ADAPTER   pAd)
+{
+       UCHAR                   BbpData = 0;
+
+       //
+       // If Channel=14 and Bandwidth=20M and Mode=CCK, set BBP R4 bit5=1
+       // (Japan Tx filter coefficients)when (TXFRAME or TXCONT).
+       //
+       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BbpData);
+
+    if ((pAd->ate.TxWI.PHYMODE == MODE_CCK) && (pAd->ate.Channel == 14) && (pAd->ate.TxWI.BW == BW_20))
+    {
+        BbpData |= 0x20;    // turn on
+        ATEDBGPRINT(RT_DEBUG_TRACE, ("SetJapanFilter!!!\n"));
+    }
+    else
+    {
+               BbpData &= 0xdf;    // turn off
+               ATEDBGPRINT(RT_DEBUG_TRACE, ("ClearJapanFilter!!!\n"));
+    }
+
+       ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpData);
+}
+
+VOID ATESampleRssi(
+       IN PRTMP_ADAPTER        pAd,
+       IN PRXWI_STRUC          pRxWI)
+{
+       /* There are two ways to collect RSSI. */
+#if 1
+       //pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
+       if (pRxWI->RSSI0 != 0)
+       {
+               pAd->ate.LastRssi0      = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0);
+               pAd->ate.AvgRssi0X8     = (pAd->ate.AvgRssi0X8 - pAd->ate.AvgRssi0) + pAd->ate.LastRssi0;
+               pAd->ate.AvgRssi0       = pAd->ate.AvgRssi0X8 >> 3;
+       }
+       if (pRxWI->RSSI1 != 0)
+       {
+               pAd->ate.LastRssi1      = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1);
+               pAd->ate.AvgRssi1X8     = (pAd->ate.AvgRssi1X8 - pAd->ate.AvgRssi1) + pAd->ate.LastRssi1;
+               pAd->ate.AvgRssi1       = pAd->ate.AvgRssi1X8 >> 3;
+       }
+       if (pRxWI->RSSI2 != 0)
+       {
+               pAd->ate.LastRssi2      = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2);
+               pAd->ate.AvgRssi2X8     = (pAd->ate.AvgRssi2X8 - pAd->ate.AvgRssi2) + pAd->ate.LastRssi2;
+               pAd->ate.AvgRssi2       = pAd->ate.AvgRssi2X8 >> 3;
+       }
+
+       pAd->ate.LastSNR0 = (CHAR)(pRxWI->SNR0);// CHAR ==> UCHAR ?
+       pAd->ate.LastSNR1 = (CHAR)(pRxWI->SNR1);// CHAR ==> UCHAR ?
+
+       pAd->ate.NumOfAvgRssiSample ++;
+#else
+       pAd->ate.LastSNR0 = (CHAR)(pRxWI->SNR0);
+       pAd->ate.LastSNR1 = (CHAR)(pRxWI->SNR1);
+       pAd->ate.RxCntPerSec++;
+       pAd->ate.LastRssi0 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0);
+       pAd->ate.LastRssi1 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1);
+       pAd->ate.LastRssi2 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2);
+       pAd->ate.AvgRssi0X8 = (pAd->ate.AvgRssi0X8 - pAd->ate.AvgRssi0) + pAd->ate.LastRssi0;
+       pAd->ate.AvgRssi0 = pAd->ate.AvgRssi0X8 >> 3;
+       pAd->ate.AvgRssi1X8 = (pAd->ate.AvgRssi1X8 - pAd->ate.AvgRssi1) + pAd->ate.LastRssi1;
+       pAd->ate.AvgRssi1 = pAd->ate.AvgRssi1X8 >> 3;
+       pAd->ate.AvgRssi2X8 = (pAd->ate.AvgRssi2X8 - pAd->ate.AvgRssi2) + pAd->ate.LastRssi2;
+       pAd->ate.AvgRssi2 = pAd->ate.AvgRssi2X8 >> 3;
+       pAd->ate.NumOfAvgRssiSample ++;
+#endif
+}
+
+#ifdef CONFIG_STA_SUPPORT
+VOID RTMPStationStop(
+    IN  PRTMP_ADAPTER   pAd)
+{
+//     BOOLEAN       Cancelled;
+
+    ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStop\n"));
+
+#if 0
+       RTMPCancelTimer(&pAd->MlmeAux.AssocTimer,      &Cancelled);
+       RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer,    &Cancelled);
+       RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer,   &Cancelled);
+       RTMPCancelTimer(&pAd->MlmeAux.AuthTimer,       &Cancelled);
+       RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer,     &Cancelled);
+       RTMPCancelTimer(&pAd->MlmeAux.ScanTimer,       &Cancelled);
+#endif
+       // For rx statistics, we need to keep this timer running.
+//     RTMPCancelTimer(&pAd->Mlme.PeriodicTimer,      &Cancelled);
+
+    ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStop\n"));
+}
+
+VOID RTMPStationStart(
+    IN  PRTMP_ADAPTER   pAd)
+{
+    ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStart\n"));
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStart\n"));
+}
+#endif // CONFIG_STA_SUPPORT //
+
+/*
+       ==========================================================================
+       Description:
+               Setup Frame format.
+       NOTE:
+               This routine should only be used in ATE mode.
+       ==========================================================================
+ */
+
+#ifdef RT2870
+/*======================Start of RT2870======================*/
+/*                                                           */
+/*                                                           */
+static INT ATESetUpFrame(
+       IN PRTMP_ADAPTER pAd,
+       IN UINT32 TxIdx)
+{
+       UINT j;
+       PTX_CONTEXT     pNullContext;
+       PUCHAR                  pDest;
+       HTTRANSMIT_SETTING      TxHTPhyMode;
+       PTXWI_STRUC             pTxWI;
+       PTXINFO_STRUC           pTxInfo;
+       UINT32                  TransferBufferLength, OrgBufferLength = 0;
+       UCHAR                   padLen = 0;
+#ifdef RALINK_28xx_QA
+       PHEADER_802_11  pHeader80211 = NULL;
+#endif // RALINK_28xx_QA //
+
+       if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
+               (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) ||
+               (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
+               (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+       {
+               return -1;
+       }
+
+       /* We always use QID_AC_BE and FIFO_EDCA in ATE mode. */
+
+       pNullContext = &(pAd->NullContext);
+       ASSERT(pNullContext != NULL);
+
+       if (pNullContext->InUse == FALSE)
+       {
+               // Set the in use bit
+               pNullContext->InUse = TRUE;
+               NdisZeroMemory(&(pAd->NullFrame), sizeof(HEADER_802_11));
+
+               // Fill 802.11 header.
+#ifdef RALINK_28xx_QA
+               if (pAd->ate.bQATxStart == TRUE)
+               {
+                       pHeader80211 = NdisMoveMemory(&(pAd->NullFrame), pAd->ate.Header, pAd->ate.HLen);
+//                     pDest = NdisMoveMemory(&(pAd->NullFrame), pAd->ate.Header, pAd->ate.HLen);
+//                     pHeader80211 = (PHEADER_802_11)pDest;
+               }
+               else
+#endif // RALINK_28xx_QA //
+               {
+                       // Fill 802.11 header.
+                       NdisMoveMemory(&(pAd->NullFrame), TemplateFrame, sizeof(HEADER_802_11));
+               }
+#ifdef RT_BIG_ENDIAN
+               RTMPFrameEndianChange(pAd, (PUCHAR)&(pAd->NullFrame), DIR_READ, FALSE);
+#endif // RT_BIG_ENDIAN //
+
+#ifdef RALINK_28xx_QA
+               if (pAd->ate.bQATxStart == TRUE)
+               {
+                       /* modify sequence number.... */
+                       if (pAd->ate.TxDoneCount == 0)
+                       {
+                               pAd->ate.seq = pHeader80211->Sequence;
+                       }
+                       else
+                       {
+                               pHeader80211->Sequence = ++pAd->ate.seq;
+                       }
+                       /* We already got all the addr. fields from QA GUI. */
+               }
+               else
+#endif // RALINK_28xx_QA //
+               {
+                       COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->ate.Addr1);
+                       COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->ate.Addr2);
+                       COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->ate.Addr3);
+               }
+
+               RTMPZeroMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[0], TX_BUFFER_NORMSIZE);//???
+               pTxInfo = (PTXINFO_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[0];
+
+#ifdef RALINK_28xx_QA
+               if (pAd->ate.bQATxStart == TRUE)
+               {
+                       // Avoid to exceed the range of WirelessPacket[].
+                       ASSERT(pAd->ate.TxInfo.USBDMATxPktLen <= (MAX_FRAME_SIZE - 34/* == 2312 */));
+                       NdisMoveMemory(pTxInfo, &(pAd->ate.TxInfo), sizeof(pAd->ate.TxInfo));
+               }
+               else
+#endif // RALINK_28xx_QA //
+               {
+                       // Avoid to exceed the range of WirelessPacket[].
+                       ASSERT(pAd->ate.TxLength <= (MAX_FRAME_SIZE - 34/* == 2312 */));
+
+                       // pTxInfo->USBDMATxPktLen will be updated to include padding later.
+                       ATEWriteTxInfo(pAd, pTxInfo, (USHORT)(TXWI_SIZE + pAd->ate.TxLength), TRUE, EpToQueue[MGMTPIPEIDX], FALSE,  FALSE);
+                       pTxInfo->QSEL = FIFO_EDCA;
+               }
+
+               pTxWI = (PTXWI_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE];
+
+               // Fill TxWI.
+               if (pAd->ate.bQATxStart == TRUE)
+               {
+                       TxHTPhyMode.field.BW = pAd->ate.TxWI.BW;
+                       TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI;
+                       TxHTPhyMode.field.STBC = pAd->ate.TxWI.STBC;
+                       TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS;
+                       TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE;
+                       ATEWriteTxWI(pAd, pTxWI, pAd->ate.TxWI.FRAG, pAd->ate.TxWI.TS, pAd->ate.TxWI.AMPDU, pAd->ate.TxWI.ACK, pAd->ate.TxWI.NSEQ,
+                               pAd->ate.TxWI.BAWinSize, BSSID_WCID, pAd->ate.TxWI.MPDUtotalByteCount/* include 802.11 header */, pAd->ate.TxWI.PacketId, 0, pAd->ate.TxWI.txop/*IFS_HTTXOP*/, pAd->ate.TxWI.CFACK/*FALSE*/, TxHTPhyMode);
+               }
+               else
+               {
+                       TxHTPhyMode.field.BW = pAd->ate.TxWI.BW;
+                       TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI;
+                       TxHTPhyMode.field.STBC = 0;
+                       TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS;
+                       TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE;
+
+                       ATEWriteTxWI(pAd, pTxWI,  FALSE, FALSE, FALSE, FALSE/* No ack required. */, FALSE, 0, BSSID_WCID, pAd->ate.TxLength,
+                               0, 0, IFS_HTTXOP, FALSE, TxHTPhyMode);// "MMPS_STATIC" instead of "MMPS_DYNAMIC" ???
+               }
+
+               RTMPMoveMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE+TXWI_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11));
+
+               pDest = &(pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE+TXWI_SIZE+sizeof(HEADER_802_11)]);
+
+               // Prepare frame payload
+#ifdef RALINK_28xx_QA
+               if (pAd->ate.bQATxStart == TRUE)
+               {
+                       // copy pattern
+                       if ((pAd->ate.PLen != 0))
+                       {
+                               for (j = 0; j < pAd->ate.DLen; j+=pAd->ate.PLen)
+                               {
+                                       RTMPMoveMemory(pDest, pAd->ate.Pattern, pAd->ate.PLen);
+                                       pDest += pAd->ate.PLen;
+                               }
+                       }
+                       TransferBufferLength = TXINFO_SIZE + TXWI_SIZE + pAd->ate.TxWI.MPDUtotalByteCount;
+               }
+               else
+#endif // RALINK_28xx_QA //
+               {
+                   for (j = 0; j < (pAd->ate.TxLength - sizeof(HEADER_802_11)); j++)
+                   {
+                               *pDest = 0xA5;
+                               pDest += 1;
+                   }
+                       TransferBufferLength = TXINFO_SIZE + TXWI_SIZE + pAd->ate.TxLength;
+               }
+
+#if 1
+               OrgBufferLength = TransferBufferLength;
+               TransferBufferLength = (TransferBufferLength + 3) & (~3);
+
+               // Always add 4 extra bytes at every packet.
+               padLen = TransferBufferLength - OrgBufferLength + 4;/* 4 == last packet padding */
+               ASSERT((padLen <= (RTMP_PKT_TAIL_PADDING - 4/* 4 == MaxBulkOutsize alignment padding */)));
+
+               /* Now memzero all extra padding bytes. */
+               NdisZeroMemory(pDest, padLen);
+               pDest += padLen;
+#else
+               if ((TransferBufferLength % 4) == 1)
+               {
+                       NdisZeroMemory(pDest, 7);
+                       pDest += 7;
+                       TransferBufferLength  += 3;
+               }
+               else if ((TransferBufferLength % 4) == 2)
+               {
+                       NdisZeroMemory(pDest, 6);
+                       pDest += 6;
+                       TransferBufferLength  += 2;
+               }
+               else if ((TransferBufferLength % 4) == 3)
+               {
+                       NdisZeroMemory(pDest, 5);
+                       pDest += 5;
+                       TransferBufferLength  += 1;
+               }
+#endif // 1 //
+
+               // Update pTxInfo->USBDMATxPktLen to include padding.
+               pTxInfo->USBDMATxPktLen = TransferBufferLength - TXINFO_SIZE;
+
+               TransferBufferLength += 4;
+
+               // If TransferBufferLength is multiple of 64, add extra 4 bytes again.
+               if ((TransferBufferLength % pAd->BulkOutMaxPacketSize) == 0)
+               {
+                       NdisZeroMemory(pDest, 4);
+                       TransferBufferLength += 4;
+               }
+
+               // Fill out frame length information for global Bulk out arbitor
+               pAd->NullContext.BulkOutSize = TransferBufferLength;
+       }
+#ifdef RT_BIG_ENDIAN
+       RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
+       RTMPFrameEndianChange(pAd, (((PUCHAR)pTxInfo)+TXWI_SIZE+TXINFO_SIZE), DIR_WRITE, FALSE);
+    RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO);
+#endif // RT_BIG_ENDIAN //
+       return 0;
+}
+
+VOID ATE_RTUSBBulkOutDataPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs)
+{
+       PRTMP_ADAPTER           pAd;
+       PTX_CONTEXT                 pNullContext;
+       UCHAR                           BulkOutPipeId;
+       NTSTATUS                        Status;
+       unsigned long           IrqFlags;
+       ULONG                       OldValue;
+
+       pNullContext = (PTX_CONTEXT)pUrb->context;
+       pAd = pNullContext->pAd;
+
+
+       // Reset Null frame context flags
+       pNullContext->IRPPending = FALSE;
+       pNullContext->InUse = FALSE;
+       Status = pUrb->status;
+
+       // Store BulkOut PipeId
+       BulkOutPipeId = pNullContext->BulkOutPipeId;
+       pAd->BulkOutDataOneSecCount++;
+
+       if (Status == USB_ST_NOERROR)
+       {
+#ifdef RALINK_28xx_QA
+               if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE))
+               {
+                       if (pAd->ate.QID == BulkOutPipeId)
+                       {
+                               // Let Rx can have a chance to break in during Tx process,
+                               // especially for loopback mode in QA ATE.
+                               // To trade off between tx performance and loopback mode integrity.
+                               /* Q   : Now Rx is handled by tasklet, do we still need this delay ? */
+                               /* Ans : Even tasklet is used, Rx/Tx < 1 if we do not delay for a while right here. */
+                               RTMPusecDelay(500);
+                               pAd->ate.TxDoneCount++;
+                               pAd->RalinkCounters.KickTxCount++;
+                               ASSERT(pAd->ate.QID == 0);
+                               pAd->ate.TxAc0++;
+                       }
+               }
+#endif // RALINK_28xx_QA //
+               pAd->BulkOutComplete++;
+
+               pAd->Counters8023.GoodTransmits++;
+
+               /* Don't worry about the queue is empty or not. This function will check itself. */
+               RTMPDeQueuePacket(pAd, TRUE, BulkOutPipeId, MAX_TX_PROCESS);
+
+               /* In 28xx, SendTxWaitQueue ==> TxSwQueue  */
+/*
+               if (pAd->SendTxWaitQueue[BulkOutPipeId].Number > 0)
+               {
+                       RTMPDeQueuePacket(pAd, BulkOutPipeId);
+               }
+*/
+       }
+       else    // STATUS_OTHER
+       {
+               pAd->BulkOutCompleteOther++;
+
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("BulkOutDataPacket Failed STATUS_OTHER = 0x%x . \n", Status));
+               ATEDBGPRINT(RT_DEBUG_ERROR, (">>BulkOutReq=0x%lx, BulkOutComplete=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete));
+
+               if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)))
+               {
+                       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+                       /* In 28xx, RT_OID_USB_RESET_BULK_OUT ==> CMDTHREAD_RESET_BULK_OUT */
+                       RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0);
+                       // Check
+                       BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+                       pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+                       pAd->bulkResetPipeid = BulkOutPipeId;
+                       BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+                       return;
+               }
+       }
+
+
+
+       if (atomic_read(&pAd->BulkOutRemained) > 0)
+       {
+               atomic_dec(&pAd->BulkOutRemained);
+       }
+
+       // 1st - Transmit Success
+       OldValue = pAd->WlanCounters.TransmittedFragmentCount.u.LowPart;
+       pAd->WlanCounters.TransmittedFragmentCount.u.LowPart++;
+
+       if (pAd->WlanCounters.TransmittedFragmentCount.u.LowPart < OldValue)
+       {
+               pAd->WlanCounters.TransmittedFragmentCount.u.HighPart++;
+       }
+
+       if(((pAd->ContinBulkOut == TRUE ) ||(atomic_read(&pAd->BulkOutRemained) > 0)) && (pAd->ate.Mode & ATE_TXFRAME))
+       {
+               RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE);
+       }
+       else
+       {
+               RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE);
+#ifdef RALINK_28xx_QA
+               pAd->ate.TxStatus = 0;
+#endif // RALINK_28xx_QA //
+       }
+
+       BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+       pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+       BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+
+       // Always call Bulk routine, even reset bulk.
+       // The protection of rest bulk should be in BulkOut routine.
+       RTUSBKickBulkOut(pAd);
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID   ATE_RTUSBBulkOutDataPacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   BulkOutPipeId)
+{
+       PTX_CONTEXT             pNullContext = &(pAd->NullContext);
+       PURB                    pUrb;
+       int                             ret = 0;
+       unsigned long   IrqFlags;
+
+
+       ASSERT(BulkOutPipeId == 0);
+
+       /* Build up the frame first. */
+//     ATESetUpFrame(pAd, 0);
+
+       BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+
+       if (pAd->BulkOutPending[BulkOutPipeId] == TRUE)
+       {
+               BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+               return;
+       }
+
+       pAd->BulkOutPending[BulkOutPipeId] = TRUE;
+       BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+
+       // Increase Total transmit byte counter
+       pAd->RalinkCounters.OneSecTransmittedByteCount +=  pNullContext->BulkOutSize;
+       pAd->RalinkCounters.TransmittedByteCount +=  pNullContext->BulkOutSize;
+
+       // Clear ATE frame bulk out flag
+       RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE);
+
+       // Init Tx context descriptor
+       pNullContext->IRPPending = TRUE;
+       RTUSBInitTxDesc(pAd, pNullContext, BulkOutPipeId, (usb_complete_t)ATE_RTUSBBulkOutDataPacketComplete);
+       pUrb = pNullContext->pUrb;
+
+       if((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+       {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("ATE_RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", ret));
+               return;
+       }
+
+       pAd->BulkOutReq++;
+       return;
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID   ATE_RTUSBCancelPendingBulkInIRP(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       PRX_CONTEXT             pRxContext;
+       UINT                    i;
+
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("--->ATE_RTUSBCancelPendingBulkInIRP\n"));
+#if 1
+       for ( i = 0; i < (RX_RING_SIZE); i++)
+       {
+               pRxContext = &(pAd->RxContext[i]);
+               if(pRxContext->IRPPending == TRUE)
+               {
+                       RTUSB_UNLINK_URB(pRxContext->pUrb);
+                       pRxContext->IRPPending = FALSE;
+                       pRxContext->InUse = FALSE;
+                       //NdisInterlockedDecrement(&pAd->PendingRx);
+                       //pAd->PendingRx--;
+               }
+       }
+#else
+       for ( i = 0; i < (RX_RING_SIZE); i++)
+       {
+               pRxContext = &(pAd->RxContext[i]);
+               if(atomic_read(&pRxContext->IrpLock) == IRPLOCK_CANCELABLE)
+               {
+                       RTUSB_UNLINK_URB(pRxContext->pUrb);
+               }
+               InterlockedExchange(&pRxContext->IrpLock, IRPLOCK_CANCE_START);
+       }
+#endif // 1 //
+       ATEDBGPRINT(RT_DEBUG_TRACE, ("<---ATE_RTUSBCancelPendingBulkInIRP\n"));
+       return;
+}
+#endif // RT2870 //
+
+VOID rt_ee_read_all(PRTMP_ADAPTER pAd, USHORT *Data)
+{
+       USHORT i;
+       USHORT value;
+
+       for (i = 0 ; i < EEPROM_SIZE/2 ; )
+       {
+               /* "value" is expecially for some compilers... */
+               RT28xx_EEPROM_READ16(pAd, i*2, value);
+               Data[i] = value;
+               i++;
+       }
+}
+
+VOID rt_ee_write_all(PRTMP_ADAPTER pAd, USHORT *Data)
+{
+       USHORT i;
+       USHORT value;
+
+       for (i = 0 ; i < EEPROM_SIZE/2 ; )
+       {
+               /* "value" is expecially for some compilers... */
+               value = Data[i];
+               RT28xx_EEPROM_WRITE16(pAd, i*2, value);
+               i ++;
+       }
+}
+#ifdef RALINK_28xx_QA
+VOID ATE_QA_Statistics(
+       IN PRTMP_ADAPTER                        pAd,
+       IN PRXWI_STRUC                          pRxWI,
+       IN PRT28XX_RXD_STRUC            pRxD,
+       IN PHEADER_802_11                       pHeader)
+{
+       // update counter first
+       if (pHeader != NULL)
+       {
+               if (pHeader->FC.Type == BTYPE_DATA)
+               {
+                       if (pRxD->U2M)
+                               pAd->ate.U2M++;
+                       else
+                               pAd->ate.OtherData++;
+               }
+               else if (pHeader->FC.Type == BTYPE_MGMT)
+               {
+                       if (pHeader->FC.SubType == SUBTYPE_BEACON)
+                               pAd->ate.Beacon++;
+                       else
+                               pAd->ate.OtherCount++;
+               }
+               else if (pHeader->FC.Type == BTYPE_CNTL)
+               {
+                       pAd->ate.OtherCount++;
+               }
+       }
+       pAd->ate.RSSI0 = pRxWI->RSSI0;
+       pAd->ate.RSSI1 = pRxWI->RSSI1;
+       pAd->ate.RSSI2 = pRxWI->RSSI2;
+       pAd->ate.SNR0 = pRxWI->SNR0;
+       pAd->ate.SNR1 = pRxWI->SNR1;
+}
+
+/* command id with Cmd Type == 0x0008(for 28xx)/0x0005(for iNIC) */
+#define RACFG_CMD_RF_WRITE_ALL         0x0000
+#define RACFG_CMD_E2PROM_READ16                0x0001
+#define RACFG_CMD_E2PROM_WRITE16       0x0002
+#define RACFG_CMD_E2PROM_READ_ALL      0x0003
+#define RACFG_CMD_E2PROM_WRITE_ALL     0x0004
+#define RACFG_CMD_IO_READ                      0x0005
+#define RACFG_CMD_IO_WRITE                     0x0006
+#define RACFG_CMD_IO_READ_BULK         0x0007
+#define RACFG_CMD_BBP_READ8                    0x0008
+#define RACFG_CMD_BBP_WRITE8           0x0009
+#define RACFG_CMD_BBP_READ_ALL         0x000a
+#define RACFG_CMD_GET_COUNTER          0x000b
+#define RACFG_CMD_CLEAR_COUNTER                0x000c
+
+#define RACFG_CMD_RSV1                         0x000d
+#define RACFG_CMD_RSV2                         0x000e
+#define RACFG_CMD_RSV3                         0x000f
+
+#define RACFG_CMD_TX_START                     0x0010
+#define RACFG_CMD_GET_TX_STATUS                0x0011
+#define RACFG_CMD_TX_STOP                      0x0012
+#define RACFG_CMD_RX_START                     0x0013
+#define RACFG_CMD_RX_STOP                      0x0014
+#define RACFG_CMD_GET_NOISE_LEVEL      0x0015
+
+#define RACFG_CMD_ATE_START                    0x0080
+#define RACFG_CMD_ATE_STOP                     0x0081
+
+#define RACFG_CMD_ATE_START_TX_CARRIER         0x0100
+#define RACFG_CMD_ATE_START_TX_CONT                    0x0101
+#define RACFG_CMD_ATE_START_TX_FRAME           0x0102
+#define RACFG_CMD_ATE_SET_BW               0x0103
+#define RACFG_CMD_ATE_SET_TX_POWER0            0x0104
+#define RACFG_CMD_ATE_SET_TX_POWER1                    0x0105
+#define RACFG_CMD_ATE_SET_FREQ_OFFSET          0x0106
+#define RACFG_CMD_ATE_GET_STATISTICS           0x0107
+#define RACFG_CMD_ATE_RESET_COUNTER                    0x0108
+#define RACFG_CMD_ATE_SEL_TX_ANTENNA           0x0109
+#define RACFG_CMD_ATE_SEL_RX_ANTENNA           0x010a
+#define RACFG_CMD_ATE_SET_PREAMBLE                     0x010b
+#define RACFG_CMD_ATE_SET_CHANNEL                      0x010c
+#define RACFG_CMD_ATE_SET_ADDR1                                0x010d
+#define RACFG_CMD_ATE_SET_ADDR2                                0x010e
+#define RACFG_CMD_ATE_SET_ADDR3                                0x010f
+#define RACFG_CMD_ATE_SET_RATE                         0x0110
+#define RACFG_CMD_ATE_SET_TX_FRAME_LEN         0x0111
+#define RACFG_CMD_ATE_SET_TX_FRAME_COUNT       0x0112
+#define RACFG_CMD_ATE_START_RX_FRAME           0x0113
+#define RACFG_CMD_ATE_E2PROM_READ_BULK 0x0114
+#define RACFG_CMD_ATE_E2PROM_WRITE_BULK        0x0115
+#define RACFG_CMD_ATE_IO_WRITE_BULK            0x0116
+#define RACFG_CMD_ATE_BBP_READ_BULK            0x0117
+#define RACFG_CMD_ATE_BBP_WRITE_BULK   0x0118
+#define RACFG_CMD_ATE_RF_READ_BULK             0x0119
+#define RACFG_CMD_ATE_RF_WRITE_BULK            0x011a
+
+
+
+#define A2Hex(_X, _p)                          \
+{                                                                      \
+       UCHAR *p;                                               \
+       _X = 0;                                                 \
+       p = _p;                                                 \
+       while (((*p >= 'a') && (*p <= 'f')) || ((*p >= 'A') && (*p <= 'F')) || ((*p >= '0') && (*p <= '9')))            \
+       {                                                                                               \
+               if ((*p >= 'a') && (*p <= 'f'))                         \
+                       _X = _X * 16 + *p - 87;                                 \
+               else if ((*p >= 'A') && (*p <= 'F'))            \
+                       _X = _X * 16 + *p - 55;                                 \
+               else if ((*p >= '0') && (*p <= '9'))            \
+                       _X = _X * 16 + *p - 48;                                 \
+               p++;                                                                            \
+       }                                                                                               \
+}
+
+
+static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len);
+static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len);
+static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len);
+
+#ifdef UCOS
+int ate_copy_to_user(
+       IN PUCHAR payload,
+       IN PUCHAR msg,
+       IN INT    len)
+{
+       memmove(payload, msg, len);
+       return 0;
+}
+
+#undef copy_to_user
+#define copy_to_user(x,y,z) ate_copy_to_user((PUCHAR)x, (PUCHAR)y, z)
+#endif // UCOS //
+
+#define        LEN_OF_ARG 16
+
+VOID RtmpDoAte(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq)
+{
+       unsigned short Command_Id;
+       struct ate_racfghdr *pRaCfg;
+       INT     Status = NDIS_STATUS_SUCCESS;
+
+
+
+       if((pRaCfg = kmalloc(sizeof(struct ate_racfghdr), GFP_KERNEL)) == NULL)
+       {
+               Status = -EINVAL;
+               return;
+       }
+
+       NdisZeroMemory(pRaCfg, sizeof(struct ate_racfghdr));
+
+    if (copy_from_user((PUCHAR)pRaCfg, wrq->u.data.pointer, wrq->u.data.length))
+       {
+               Status = -EFAULT;
+               kfree(pRaCfg);
+               return;
+       }
+
+
+       Command_Id = ntohs(pRaCfg->command_id);
+
+       ATEDBGPRINT(RT_DEBUG_TRACE,("\n%s: Command_Id = 0x%04x !\n", __FUNCTION__, Command_Id));
+
+       switch (Command_Id)
+       {
+               // We will get this command when QA starts.
+               case RACFG_CMD_ATE_START:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START\n"));
+
+                               // prepare feedback as soon as we can to avoid QA timeout.
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_ATE_START\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START is done !\n"));
+                               }
+                               Set_ATE_Proc(pAdapter, "ATESTART");
+                       }
+                       break;
+
+               // We will get this command either QA is closed or ated is killed by user.
+               case RACFG_CMD_ATE_STOP:
+                       {
+#ifndef UCOS
+                               INT32 ret;
+#endif // !UCOS //
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_STOP\n"));
+
+                               // Distinguish this command came from QA(via ated)
+                               // or ate daemon according to the existence of pid in payload.
+                               // No need to prepare feedback if this cmd came directly from ate daemon.
+                               pRaCfg->length = ntohs(pRaCfg->length);
+
+                               if (pRaCfg->length == sizeof(pAdapter->ate.AtePid))
+                               {
+                                       // This command came from QA.
+                                       // Get the pid of ATE daemon.
+                                       memcpy((UCHAR *)&pAdapter->ate.AtePid,
+                                               (&pRaCfg->data[0]) - 2/* == &(pRaCfg->status) */,
+                                               sizeof(pAdapter->ate.AtePid));
+
+                                       // prepare feedback as soon as we can to avoid QA timeout.
+                                       pRaCfg->length = htons(2);
+                                       pRaCfg->status = htons(0);
+
+                                       wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                               + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                               + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+                                       ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+                       if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+                       {
+                               ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_STOP\n"));
+                           Status = -EFAULT;
+                       }
+
+                                       //
+                                       // kill ATE daemon when leaving ATE mode.
+                                       // We must kill ATE daemon first before setting ATESTOP,
+                                       // or Microsoft will report sth. wrong.
+#ifndef UCOS
+                                       ret = KILL_THREAD_PID(pAdapter->ate.AtePid, SIGTERM, 1);
+                                       if (ret)
+                                       {
+                                               ATEDBGPRINT(RT_DEBUG_ERROR, ("%s: unable to signal thread\n", pAdapter->net_dev->name));
+                                       }
+#endif // !UCOS //
+                               }
+
+                               // AP might have in ATE_STOP mode due to cmd from QA.
+                               if (ATE_ON(pAdapter))
+                               {
+                                       // Someone has killed ate daemon while QA GUI is still open.
+                                       Set_ATE_Proc(pAdapter, "ATESTOP");
+                                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_AP_START is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_RF_WRITE_ALL:
+                       {
+                               UINT32 R1, R2, R3, R4;
+                               USHORT channel;
+
+                               memcpy(&R1, pRaCfg->data-2, 4);
+                               memcpy(&R2, pRaCfg->data+2, 4);
+                               memcpy(&R3, pRaCfg->data+6, 4);
+                               memcpy(&R4, pRaCfg->data+10, 4);
+                               memcpy(&channel, pRaCfg->data+14, 2);
+
+                               pAdapter->LatchRfRegs.R1 = ntohl(R1);
+                               pAdapter->LatchRfRegs.R2 = ntohl(R2);
+                               pAdapter->LatchRfRegs.R3 = ntohl(R3);
+                               pAdapter->LatchRfRegs.R4 = ntohl(R4);
+                               pAdapter->LatchRfRegs.Channel = ntohs(channel);
+
+                               RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R1);
+                               RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R2);
+                               RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R3);
+                               RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R4);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RF_WRITE_ALL\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RF_WRITE_ALL is done !\n"));
+                               }
+                       }
+            break;
+
+               case RACFG_CMD_E2PROM_READ16:
+                       {
+                               USHORT  offset, value, tmp;
+
+                               offset = ntohs(pRaCfg->status);
+                               /* "tmp" is expecially for some compilers... */
+                               RT28xx_EEPROM_READ16(pAdapter, offset, tmp);
+                               value = tmp;
+                               value = htons(value);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("EEPROM Read offset = 0x%04x, value = 0x%04x\n", offset, value));
+
+                               // prepare feedback
+                               pRaCfg->length = htons(4);
+                               pRaCfg->status = htons(0);
+                               memcpy(pRaCfg->data, &value, 2);
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE, ("sizeof(struct ate_racfghdr) = %d\n", sizeof(struct ate_racfghdr)));
+                               ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_READ16\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_READ16 is done !\n"));
+                               }
+               }
+                       break;
+
+               case RACFG_CMD_E2PROM_WRITE16:
+                       {
+                               USHORT  offset, value;
+
+                               offset = ntohs(pRaCfg->status);
+                               memcpy(&value, pRaCfg->data, 2);
+                               value = ntohs(value);
+                               RT28xx_EEPROM_WRITE16(pAdapter, offset, value);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_WRITE16\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_WRITE16 is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_E2PROM_READ_ALL:
+                       {
+                               USHORT buffer[EEPROM_SIZE/2];
+
+                               rt_ee_read_all(pAdapter,(USHORT *)buffer);
+                               memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer, EEPROM_SIZE);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2+EEPROM_SIZE);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_READ_ALL\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_READ_ALL is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_E2PROM_WRITE_ALL:
+                       {
+                               USHORT buffer[EEPROM_SIZE/2];
+
+                               NdisZeroMemory((UCHAR *)buffer, EEPROM_SIZE);
+                               memcpy_exs(pAdapter, (UCHAR *)buffer, (UCHAR *)&pRaCfg->status, EEPROM_SIZE);
+                               rt_ee_write_all(pAdapter,(USHORT *)buffer);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_WRITE_ALL\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_E2PROM_WRITE_ALL is done !\n"));
+                               }
+
+                       }
+                       break;
+
+               case RACFG_CMD_IO_READ:
+                       {
+                               UINT32  offset;
+                               UINT32  value;
+
+                               memcpy(&offset, &pRaCfg->status, 4);
+                               offset = ntohl(offset);
+
+                               // We do not need the base address.
+                               // So just extract the offset out.
+                               offset &= 0x0000FFFF;
+                               RTMP_IO_READ32(pAdapter, offset, &value);
+                               value = htonl(value);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(6);
+                               pRaCfg->status = htons(0);
+                               memcpy(pRaCfg->data, &value, 4);
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_READ\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_READ is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_IO_WRITE:
+                       {
+                               UINT32  offset, value;
+
+                               memcpy(&offset, pRaCfg->data-2, 4);
+                               memcpy(&value, pRaCfg->data+2, 4);
+
+                               offset = ntohl(offset);
+
+                               // We do not need the base address.
+                               // So just extract out the offset.
+                               offset &= 0x0000FFFF;
+                               value = ntohl(value);
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_IO_WRITE: offset = %x, value = %x\n", offset, value));
+                               RTMP_IO_WRITE32(pAdapter, offset, value);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_WRITE\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_WRITE is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_IO_READ_BULK:
+                       {
+                               UINT32  offset;
+                               USHORT  len;
+
+                               memcpy(&offset, &pRaCfg->status, 4);
+                               offset = ntohl(offset);
+
+                               // We do not need the base address.
+                               // So just extract the offset.
+                               offset &= 0x0000FFFF;
+                               memcpy(&len, pRaCfg->data+2, 2);
+                               len = ntohs(len);
+
+                               if (len > 371)
+                               {
+                                       ATEDBGPRINT(RT_DEBUG_TRACE,("len is too large, make it smaller\n"));
+                                       pRaCfg->length = htons(2);
+                                       pRaCfg->status = htons(1);
+                                       break;
+                               }
+
+                               RTMP_IO_READ_BULK(pAdapter, pRaCfg->data, (UCHAR *)offset, len*4);// unit in four bytes
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2+len*4);// unit in four bytes
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_READ_BULK\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_READ_BULK is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_BBP_READ8:
+                       {
+                               USHORT  offset;
+                               UCHAR   value;
+
+                               value = 0;
+                               offset = ntohs(pRaCfg->status);
+
+                               if (ATE_ON(pAdapter))
+                               {
+                                       ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, offset,  &value);
+                               }
+                               else
+                               {
+                                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, offset,  &value);
+                               }
+                               // prepare feedback
+                               pRaCfg->length = htons(3);
+                               pRaCfg->status = htons(0);
+                               pRaCfg->data[0] = value;
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("BBP value = %x\n", value));
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_READ8\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_READ8 is done !\n"));
+                               }
+                       }
+                       break;
+               case RACFG_CMD_BBP_WRITE8:
+                       {
+                               USHORT  offset;
+                               UCHAR   value;
+
+                               offset = ntohs(pRaCfg->status);
+                               memcpy(&value, pRaCfg->data, 1);
+
+                               if (ATE_ON(pAdapter))
+                               {
+                                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset,  value);
+                               }
+                               else
+                               {
+                                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset,  value);
+                               }
+
+                               if ((offset == BBP_R1) || (offset == BBP_R3))
+                               {
+                                       SyncTxRxConfig(pAdapter, offset, value);
+                               }
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_WRITE8\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_WRITE8 is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_BBP_READ_ALL:
+                       {
+                               USHORT j;
+
+                               for (j = 0; j < 137; j++)
+                               {
+                                       pRaCfg->data[j] = 0;
+
+                                       if (ATE_ON(pAdapter))
+                                       {
+                                               ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, j,  &pRaCfg->data[j]);
+                                       }
+                                       else
+                                       {
+                                               RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, j,  &pRaCfg->data[j]);
+                                       }
+                               }
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2+137);
+                               pRaCfg->status = htons(0);
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_READ_ALL\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_READ_ALL is done !\n"));
+                               }
+                       }
+
+                       break;
+
+               case RACFG_CMD_ATE_E2PROM_READ_BULK:
+               {
+                       USHORT offset;
+                       USHORT len;
+                       USHORT buffer[EEPROM_SIZE/2];
+
+                       offset = ntohs(pRaCfg->status);
+                       memcpy(&len, pRaCfg->data, 2);
+                       len = ntohs(len);
+
+                       rt_ee_read_all(pAdapter,(USHORT *)buffer);
+                       if (offset + len <= EEPROM_SIZE)
+                               memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer+offset, len);
+                       else
+                               ATEDBGPRINT(RT_DEBUG_ERROR, ("exceed EEPROM size\n"));
+
+                       // prepare feedback
+                       pRaCfg->length = htons(2+len);
+                       pRaCfg->status = htons(0);
+                       wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+            if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+            {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_E2PROM_READ_BULK\n"));
+                Status = -EFAULT;
+            }
+                       else
+                       {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_E2PROM_READ_BULK is done !\n"));
+                       }
+
+               }
+                       break;
+
+               case RACFG_CMD_ATE_E2PROM_WRITE_BULK:
+               {
+                       USHORT offset;
+                       USHORT len;
+                       USHORT buffer[EEPROM_SIZE/2];
+
+                       offset = ntohs(pRaCfg->status);
+                       memcpy(&len, pRaCfg->data, 2);
+                       len = ntohs(len);
+
+                       rt_ee_read_all(pAdapter,(USHORT *)buffer);
+                       memcpy_exs(pAdapter, (UCHAR *)buffer + offset, (UCHAR *)pRaCfg->data + 2, len);
+                       rt_ee_write_all(pAdapter,(USHORT *)buffer);
+
+                       // prepare feedback
+                       pRaCfg->length = htons(2);
+                       pRaCfg->status = htons(0);
+                       wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                               + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                               + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+            if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+            {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_E2PROM_WRITE_BULK\n"));
+                   Status = -EFAULT;
+            }
+                       else
+                       {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_ATE_E2PROM_WRITE_BULK is done !\n"));
+                       }
+
+               }
+                       break;
+
+               case RACFG_CMD_ATE_IO_WRITE_BULK:
+               {
+                       UINT32 offset, i, value;
+                       USHORT len;
+
+                       memcpy(&offset, &pRaCfg->status, 4);
+                       offset = ntohl(offset);
+                       memcpy(&len, pRaCfg->data+2, 2);
+                       len = ntohs(len);
+
+                       for (i = 0; i < len; i += 4)
+                       {
+                               memcpy_exl(pAdapter, (UCHAR *)&value, pRaCfg->data+4+i, 4);
+                               printk("Write %x %x\n", offset + i, value);
+                               RTMP_IO_WRITE32(pAdapter, (offset +i) & 0xffff, value);
+                       }
+
+                       // prepare feedback
+                       pRaCfg->length = htons(2);
+                       pRaCfg->status = htons(0);
+                       wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                               + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                               + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+            if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+            {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_IO_WRITE_BULK\n"));
+                   Status = -EFAULT;
+            }
+                       else
+                       {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_ATE_IO_WRITE_BULK is done !\n"));
+                       }
+
+               }
+                       break;
+
+               case RACFG_CMD_ATE_BBP_READ_BULK:
+               {
+                       USHORT offset;
+                       USHORT len;
+                       USHORT j;
+
+                       offset = ntohs(pRaCfg->status);
+                       memcpy(&len, pRaCfg->data, 2);
+                       len = ntohs(len);
+
+
+                       for (j = offset; j < (offset+len); j++)
+                       {
+                               pRaCfg->data[j - offset] = 0;
+
+                               if (pAdapter->ate.Mode == ATE_STOP)
+                               {
+                                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, j,  &pRaCfg->data[j - offset]);
+                               }
+                               else
+                               {
+                                       ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, j,  &pRaCfg->data[j - offset]);
+                               }
+                       }
+
+                       // prepare feedback
+                       pRaCfg->length = htons(2+len);
+                       pRaCfg->status = htons(0);
+                       wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                               + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                               + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+            if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+            {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_BBP_READ_BULK\n"));
+                   Status = -EFAULT;
+            }
+                       else
+                       {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_BBP_READ_BULK is done !\n"));
+                       }
+
+               }
+                       break;
+
+               case RACFG_CMD_ATE_BBP_WRITE_BULK:
+               {
+                       USHORT offset;
+                       USHORT len;
+                       USHORT j;
+                       UCHAR *value;
+
+                       offset = ntohs(pRaCfg->status);
+                       memcpy(&len, pRaCfg->data, 2);
+                       len = ntohs(len);
+
+                       for (j = offset; j < (offset+len); j++)
+                       {
+                               value = pRaCfg->data + 2 + (j - offset);
+                               if (pAdapter->ate.Mode == ATE_STOP)
+                               {
+                                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j,  *value);
+                               }
+                               else
+                               {
+                                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j,  *value);
+                               }
+                       }
+
+                       // prepare feedback
+                       pRaCfg->length = htons(2);
+                       pRaCfg->status = htons(0);
+                       wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                               + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                               + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+            if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+            {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_BBP_WRITE_BULK\n"));
+                   Status = -EFAULT;
+            }
+                       else
+                       {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_BBP_WRITE_BULK is done !\n"));
+                       }
+               }
+                       break;
+
+#ifdef CONFIG_RALINK_RT3052
+               case RACFG_CMD_ATE_RF_READ_BULK:
+               {
+                       USHORT offset;
+                       USHORT len;
+                       USHORT j;
+
+                       offset = ntohs(pRaCfg->status);
+                       memcpy(&len, pRaCfg->data, 2);
+                       len = ntohs(len);
+
+                       for (j = offset; j < (offset+len); j++)
+                       {
+                               pRaCfg->data[j - offset] = 0;
+                               RT30xxReadRFRegister(pAdapter, j,  &pRaCfg->data[j - offset]);
+                       }
+
+                       // prepare feedback
+                       pRaCfg->length = htons(2+len);
+                       pRaCfg->status = htons(0);
+                       wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                               + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                               + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+            if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+            {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RF_READ_BULK\n"));
+                   Status = -EFAULT;
+            }
+                       else
+                       {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RF_READ_BULK is done !\n"));
+                       }
+
+               }
+                       break;
+
+               case RACFG_CMD_ATE_RF_WRITE_BULK:
+               {
+                       USHORT offset;
+                       USHORT len;
+                       USHORT j;
+                       UCHAR *value;
+
+                       offset = ntohs(pRaCfg->status);
+                       memcpy(&len, pRaCfg->data, 2);
+                       len = ntohs(len);
+
+                       for (j = offset; j < (offset+len); j++)
+                       {
+                               value = pRaCfg->data + 2 + (j - offset);
+                               RT30xxWriteRFRegister(pAdapter, j,  *value);
+                       }
+
+                       // prepare feedback
+                       pRaCfg->length = htons(2);
+                       pRaCfg->status = htons(0);
+                       wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                               + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                               + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+            if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+            {
+               ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RF_WRITE_BULK\n"));
+                   Status = -EFAULT;
+            }
+                       else
+                       {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RF_WRITE_BULK is done !\n"));
+                       }
+
+               }
+                       break;
+#endif
+
+
+               case RACFG_CMD_GET_NOISE_LEVEL:
+                       {
+                               UCHAR   channel;
+                               INT32   buffer[3][10];/* 3 : RxPath ; 10 : no. of per rssi samples */
+
+                               channel = (ntohs(pRaCfg->status) & 0x00FF);
+                               CalNoiseLevel(pAdapter, channel, buffer);
+                               memcpy_exl(pAdapter, (UCHAR *)pRaCfg->data, (UCHAR *)&(buffer[0][0]), (sizeof(INT32)*3*10));
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2 + (sizeof(INT32)*3*10));
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_NOISE_LEVEL\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_NOISE_LEVEL is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_GET_COUNTER:
+                       {
+                               memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.U2M, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->ate.OtherData, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->ate.Beacon, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->ate.OtherCount, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->ate.TxAc0, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->ate.TxAc1, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->ate.TxAc2, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->ate.TxAc3, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->ate.TxHCCA, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->ate.TxMgmt, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&pAdapter->ate.RSSI0, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&pAdapter->ate.RSSI1, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&pAdapter->ate.RSSI2, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[52], (UCHAR *)&pAdapter->ate.SNR0, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[56], (UCHAR *)&pAdapter->ate.SNR1, 4);
+
+                               pRaCfg->length = htons(2+60);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_COUNTER\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_COUNTER is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_CLEAR_COUNTER:
+                       {
+                               pAdapter->ate.U2M = 0;
+                               pAdapter->ate.OtherData = 0;
+                               pAdapter->ate.Beacon = 0;
+                               pAdapter->ate.OtherCount = 0;
+                               pAdapter->ate.TxAc0 = 0;
+                               pAdapter->ate.TxAc1 = 0;
+                               pAdapter->ate.TxAc2 = 0;
+                               pAdapter->ate.TxAc3 = 0;
+                               pAdapter->ate.TxHCCA = 0;
+                               pAdapter->ate.TxMgmt = 0;
+                               pAdapter->ate.TxDoneCount = 0;
+
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_CLEAR_COUNTER\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_CLEAR_COUNTER is done !\n"));
+                               }
+                       }
+
+                       break;
+
+               case RACFG_CMD_TX_START:
+                       {
+                               USHORT *p;
+                               USHORT  err = 1;
+                               UCHAR   Bbp22Value = 0, Bbp24Value = 0;
+
+                               if ((pAdapter->ate.TxStatus != 0) && (pAdapter->ate.Mode & ATE_TXFRAME))
+                               {
+                                       ATEDBGPRINT(RT_DEBUG_TRACE,("Ate Tx is already running, to run next Tx, you must stop it first\n"));
+                                       err = 2;
+                                       goto TX_START_ERROR;
+                               }
+                               else if ((pAdapter->ate.TxStatus != 0) && !(pAdapter->ate.Mode & ATE_TXFRAME))
+                               {
+                                       int i = 0;
+
+                                       while ((i++ < 10) && (pAdapter->ate.TxStatus != 0))
+                                       {
+                                               RTMPusecDelay(5000);
+                                       }
+
+                                       // force it to stop
+                                       pAdapter->ate.TxStatus = 0;
+                                       pAdapter->ate.TxDoneCount = 0;
+                                       //pAdapter->ate.Repeat = 0;
+                                       pAdapter->ate.bQATxStart = FALSE;
+                               }
+
+                               // If pRaCfg->length == 0, this "RACFG_CMD_TX_START" is for Carrier test or Carrier Suppression.
+                               if (ntohs(pRaCfg->length) != 0)
+                               {
+                                       // Get frame info
+#ifdef RT2870
+                                       NdisMoveMemory(&pAdapter->ate.TxInfo, pRaCfg->data - 2, 4);
+#ifdef RT_BIG_ENDIAN
+                                       RTMPDescriptorEndianChange((PUCHAR) &pAdapter->ate.TxInfo, TYPE_TXINFO);
+#endif // RT_BIG_ENDIAN //
+#endif // RT2870 //
+
+                                       NdisMoveMemory(&pAdapter->ate.TxWI, pRaCfg->data + 2, 16);
+#ifdef RT_BIG_ENDIAN
+                                       RTMPWIEndianChange((PUCHAR)&pAdapter->ate.TxWI, TYPE_TXWI);
+#endif // RT_BIG_ENDIAN //
+
+                                       NdisMoveMemory(&pAdapter->ate.TxCount, pRaCfg->data + 18, 4);
+                                       pAdapter->ate.TxCount = ntohl(pAdapter->ate.TxCount);
+
+                                       p = (USHORT *)(&pRaCfg->data[22]);
+                                       //p = pRaCfg->data + 22;
+                                       // always use QID_AC_BE
+                                       pAdapter->ate.QID = 0;
+                                       p = (USHORT *)(&pRaCfg->data[24]);
+                                       //p = pRaCfg->data + 24;
+                                       pAdapter->ate.HLen = ntohs(*p);
+
+                                       if (pAdapter->ate.HLen > 32)
+                                       {
+                                               ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.HLen > 32\n"));
+                                               err = 3;
+                                               goto TX_START_ERROR;
+                                       }
+
+                                       NdisMoveMemory(&pAdapter->ate.Header, pRaCfg->data + 26, pAdapter->ate.HLen);
+
+
+                                       pAdapter->ate.PLen = ntohs(pRaCfg->length) - (pAdapter->ate.HLen + 28);
+
+                                       if (pAdapter->ate.PLen > 32)
+                                       {
+                                               ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.PLen > 32\n"));
+                                               err = 4;
+                                               goto TX_START_ERROR;
+                                       }
+
+                                       NdisMoveMemory(&pAdapter->ate.Pattern, pRaCfg->data + 26 + pAdapter->ate.HLen, pAdapter->ate.PLen);
+                                       pAdapter->ate.DLen = pAdapter->ate.TxWI.MPDUtotalByteCount - pAdapter->ate.HLen;
+                               }
+
+                               ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R22, &Bbp22Value);
+
+                               switch (Bbp22Value)
+                               {
+                                       case BBP22_TXFRAME:
+                                               {
+                                                       if (pAdapter->ate.TxCount == 0)
+                                                       {
+                                                       }
+                                                       ATEDBGPRINT(RT_DEBUG_TRACE,("START TXFRAME\n"));
+                                                       pAdapter->ate.bQATxStart = TRUE;
+                                                       Set_ATE_Proc(pAdapter, "TXFRAME");
+                                               }
+                                               break;
+
+                                       case BBP22_TXCONT_OR_CARRSUPP:
+                                               {
+                                                       ATEDBGPRINT(RT_DEBUG_TRACE,("BBP22_TXCONT_OR_CARRSUPP\n"));
+                                                       ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, 24, &Bbp24Value);
+
+                                                       switch (Bbp24Value)
+                                                       {
+                                                               case BBP24_TXCONT:
+                                                                       {
+                                                                               ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCONT\n"));
+                                                                               pAdapter->ate.bQATxStart = TRUE;
+                                                                               Set_ATE_Proc(pAdapter, "TXCONT");
+                                                                       }
+                                                                       break;
+
+                                                               case BBP24_CARRSUPP:
+                                                                       {
+                                                                               ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARRSUPP\n"));
+                                                                               pAdapter->ate.bQATxStart = TRUE;
+                                                                               pAdapter->ate.Mode |= ATE_TXCARRSUPP;
+                                                                       }
+                                                                       break;
+
+                                                               default:
+                                                                       {
+                                                                               ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown Start TX subtype !"));
+                                                                       }
+                                                                       break;
+                                                       }
+                                               }
+                                               break;
+
+                                       case BBP22_TXCARR:
+                                               {
+                                                       ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARR\n"));
+                                                       pAdapter->ate.bQATxStart = TRUE;
+                                                       Set_ATE_Proc(pAdapter, "TXCARR");
+                                               }
+                                               break;
+
+                                       default:
+                                               {
+                                                       ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown Start TX subtype !"));
+                                               }
+                                               break;
+                               }
+
+                               if (pAdapter->ate.bQATxStart == TRUE)
+                               {
+                                       // prepare feedback
+                                       pRaCfg->length = htons(2);
+                                       pRaCfg->status = htons(0);
+
+                                       wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                               + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                               + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+                       if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+                       {
+                               ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() was failed in case RACFG_CMD_TX_START\n"));
+                           Status = -EFAULT;
+                       }
+                                       else
+                                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_TX_START is done !\n"));
+                                       }
+                                       break;
+                               }
+
+TX_START_ERROR:
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(err);
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_TX_START\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("feedback of TX_START_ERROR is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_GET_TX_STATUS:
+                       {
+                               UINT32 count;
+
+                               // prepare feedback
+                               pRaCfg->length = htons(6);
+                               pRaCfg->status = htons(0);
+                               count = htonl(pAdapter->ate.TxDoneCount);
+                               NdisMoveMemory(pRaCfg->data, &count, 4);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_TX_STATUS\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_TX_STATUS is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_TX_STOP:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_TX_STOP\n"));
+
+                               Set_ATE_Proc(pAdapter, "TXSTOP");
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_TX_STOP\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_TX_STOP is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_RX_START:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n"));
+
+                               pAdapter->ate.bQARxStart = TRUE;
+                               Set_ATE_Proc(pAdapter, "RXFRAME");
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_START\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_START is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_RX_STOP:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_STOP\n"));
+
+                               Set_ATE_Proc(pAdapter, "RXSTOP");
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_STOP\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_STOP is done !\n"));
+                               }
+                       }
+                       break;
+
+               /* The following cases are for new ATE GUI(not QA). */
+               /*==================================================*/
+               case RACFG_CMD_ATE_START_TX_CARRIER:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CARRIER\n"));
+
+                               Set_ATE_Proc(pAdapter, "TXCARR");
+
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_CARRIER\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_CARRIER is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_START_TX_CONT:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CONT\n"));
+
+                               Set_ATE_Proc(pAdapter, "TXCONT");
+
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_CONT\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_CONT is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_START_TX_FRAME:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_FRAME\n"));
+
+                               Set_ATE_Proc(pAdapter, "TXFRAME");
+
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_FRAME\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_FRAME is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_BW:
+                       {
+                               SHORT    value = 0;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_BW\n"));
+
+                               memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+                               value = ntohs(value);
+                               sprintf((PCHAR)str, "%d", value);
+
+                               Set_ATE_TX_BW_Proc(pAdapter, str);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_BW\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_BW is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_TX_POWER0:
+                       {
+                               SHORT    value = 0;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER0\n"));
+
+                               memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+                               value = ntohs(value);
+                               sprintf((PCHAR)str, "%d", value);
+                               Set_ATE_TX_POWER0_Proc(pAdapter, str);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_POWER0\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_POWER0 is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_TX_POWER1:
+                       {
+                               SHORT    value = 0;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER1\n"));
+
+                               memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+                               value = ntohs(value);
+                               sprintf((PCHAR)str, "%d", value);
+                               Set_ATE_TX_POWER1_Proc(pAdapter, str);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_POWER1\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_POWER1 is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_FREQ_OFFSET:
+                       {
+                               SHORT    value = 0;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_FREQ_OFFSET\n"));
+
+                               memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+                               value = ntohs(value);
+                               sprintf((PCHAR)str, "%d", value);
+                               Set_ATE_TX_FREQOFFSET_Proc(pAdapter, str);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_FREQ_OFFSET\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_FREQ_OFFSET is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_GET_STATISTICS:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_GET_STATISTICS\n"));
+
+                               memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.TxDoneCount, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->WlanCounters.RetryCount.u.LowPart, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->WlanCounters.FailedCount.u.LowPart, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->WlanCounters.RTSSuccessCount.u.LowPart, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->WlanCounters.RTSFailureCount.u.LowPart, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->WlanCounters.FCSErrorCount.u.LowPart, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->Counters8023.RxNoBuffer, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->WlanCounters.FrameDuplicateCount.u.LowPart, 4);
+                               memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->RalinkCounters.OneSecFalseCCACnt, 4);
+
+                               if (pAdapter->ate.RxAntennaSel == 0)
+                               {
+                                       INT32 RSSI0 = 0;
+                                       INT32 RSSI1 = 0;
+                                       INT32 RSSI2 = 0;
+
+                                       RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta);
+                                       RSSI1 = (INT32)(pAdapter->ate.LastRssi1 - pAdapter->BbpRssiToDbmDelta);
+                                       RSSI2 = (INT32)(pAdapter->ate.LastRssi2 - pAdapter->BbpRssiToDbmDelta);
+                                       memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4);
+                                       memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&RSSI1, 4);
+                                       memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&RSSI2, 4);
+                                       pRaCfg->length = htons(2+52);
+                               }
+                               else
+                               {
+                                       INT32 RSSI0 = 0;
+
+                                       RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta);
+                                       memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4);
+                                       pRaCfg->length = htons(2+44);
+                               }
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_GET_STATISTICS\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_GET_STATISTICS is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_RESET_COUNTER:
+                       {
+                               SHORT    value = 1;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_RESET_COUNTER\n"));
+
+                               sprintf((PCHAR)str, "%d", value);
+                               Set_ResetStatCounter_Proc(pAdapter, str);
+
+                               pAdapter->ate.TxDoneCount = 0;
+
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RESET_COUNTER\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RESET_COUNTER is done !\n"));
+                               }
+                       }
+
+                       break;
+
+               case RACFG_CMD_ATE_SEL_TX_ANTENNA:
+                       {
+                               SHORT    value = 0;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_TX_ANTENNA\n"));
+
+                               memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+                               value = ntohs(value);
+                               sprintf((PCHAR)str, "%d", value);
+                               Set_ATE_TX_Antenna_Proc(pAdapter, str);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SEL_TX_ANTENNA\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SEL_TX_ANTENNA is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SEL_RX_ANTENNA:
+                       {
+                               SHORT    value = 0;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_RX_ANTENNA\n"));
+
+                               memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+                               value = ntohs(value);
+                               sprintf((PCHAR)str, "%d", value);
+                               Set_ATE_RX_Antenna_Proc(pAdapter, str);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SEL_RX_ANTENNA\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SEL_RX_ANTENNA is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_PREAMBLE:
+                       {
+                               SHORT    value = 0;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_PREAMBLE\n"));
+
+                               memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+                               value = ntohs(value);
+                               sprintf((PCHAR)str, "%d", value);
+                               Set_ATE_TX_MODE_Proc(pAdapter, str);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_PREAMBLE\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_PREAMBLE is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_CHANNEL:
+                       {
+                               SHORT    value = 0;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_CHANNEL\n"));
+
+                               memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+                               value = ntohs(value);
+                               sprintf((PCHAR)str, "%d", value);
+                               Set_ATE_CHANNEL_Proc(pAdapter, str);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_CHANNEL\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_CHANNEL is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_ADDR1:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR1\n"));
+
+                               // Addr is an array of UCHAR,
+                               // so no need to perform endian swap.
+                               memcpy(pAdapter->ate.Addr1, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR1\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR1 is done !\n (ADDR1 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr1[0],
+                                               pAdapter->ate.Addr1[1], pAdapter->ate.Addr1[2], pAdapter->ate.Addr1[3], pAdapter->ate.Addr1[4], pAdapter->ate.Addr1[5]));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_ADDR2:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR2\n"));
+
+                               // Addr is an array of UCHAR,
+                               // so no need to perform endian swap.
+                               memcpy(pAdapter->ate.Addr2, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR2\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR2 is done !\n (ADDR2 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr2[0],
+                                               pAdapter->ate.Addr2[1], pAdapter->ate.Addr2[2], pAdapter->ate.Addr2[3], pAdapter->ate.Addr2[4], pAdapter->ate.Addr2[5]));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_ADDR3:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR3\n"));
+
+                               // Addr is an array of UCHAR,
+                               // so no need to perform endian swap.
+                               memcpy(pAdapter->ate.Addr3, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR3\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR3 is done !\n (ADDR3 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr3[0],
+                                               pAdapter->ate.Addr3[1], pAdapter->ate.Addr3[2], pAdapter->ate.Addr3[3], pAdapter->ate.Addr3[4], pAdapter->ate.Addr3[5]));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_RATE:
+                       {
+                               SHORT    value = 0;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_RATE\n"));
+
+                               memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+                               value = ntohs(value);
+                               sprintf((PCHAR)str, "%d", value);
+                               Set_ATE_TX_MCS_Proc(pAdapter, str);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_RATE\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_RATE is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_TX_FRAME_LEN:
+                       {
+                               SHORT    value = 0;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_LEN\n"));
+
+                               memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+                               value = ntohs(value);
+                               sprintf((PCHAR)str, "%d", value);
+                               Set_ATE_TX_LENGTH_Proc(pAdapter, str);
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_FRAME_LEN\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_FRAME_LEN is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_SET_TX_FRAME_COUNT:
+                       {
+                               USHORT    value = 0;
+                               UCHAR    str[LEN_OF_ARG];
+
+                               NdisZeroMemory(str, LEN_OF_ARG);
+
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n"));
+
+                               memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+                               value = ntohs(value);
+                               {
+                                       sprintf((PCHAR)str, "%d", value);
+                                       Set_ATE_TX_COUNT_Proc(pAdapter, str);
+                               }
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_FRAME_COUNT is done !\n"));
+                               }
+                       }
+                       break;
+
+               case RACFG_CMD_ATE_START_RX_FRAME:
+                       {
+                               ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n"));
+
+                               Set_ATE_Proc(pAdapter, "RXFRAME");
+
+                               // prepare feedback
+                               pRaCfg->length = htons(2);
+                               pRaCfg->status = htons(0);
+                               wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+                                                                       + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+                                                                       + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+               if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+               {
+                       ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_START\n"));
+                    Status = -EFAULT;
+               }
+                               else
+                               {
+                       ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_START is done !\n"));
+                               }
+                       }
+                       break;
+               default:
+                       break;
+       }
+    ASSERT(pRaCfg != NULL);
+    if (pRaCfg != NULL)
+    {
+    kfree(pRaCfg);
+    }
+       return;
+}
+
+VOID BubbleSort(INT32 n, INT32 a[])
+{
+       INT32 k, j, temp;
+
+       for (k = n-1;  k>0;  k--)
+       {
+               for (j = 0; j<k; j++)
+               {
+                       if(a[j] > a[j+1])
+                       {
+                               temp = a[j];
+                               a[j]=a[j+1];
+                               a[j+1]=temp;
+                       }
+               }
+       }
+}
+
+VOID CalNoiseLevel(PRTMP_ADAPTER pAd, UCHAR channel, INT32 RSSI[3][10])
+{
+       INT32           RSSI0, RSSI1, RSSI2;
+       CHAR            Rssi0Offset, Rssi1Offset, Rssi2Offset;
+       UCHAR           BbpR50Rssi0 = 0, BbpR51Rssi1 = 0, BbpR52Rssi2 = 0;
+       UCHAR           Org_BBP66value = 0, Org_BBP69value = 0, Org_BBP70value = 0, data = 0;
+       USHORT          LNA_Gain = 0;
+       INT32       j = 0;
+       UCHAR           Org_Channel = pAd->ate.Channel;
+       USHORT      GainValue = 0, OffsetValue = 0;
+
+       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &Org_BBP66value);
+       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R69, &Org_BBP69value);
+       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R70, &Org_BBP70value);
+
+       //**********************************************************************
+       // Read the value of LNA gain and Rssi offset
+       //**********************************************************************
+       RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, GainValue);
+
+       // for Noise Level
+       if (channel <= 14)
+       {
+               LNA_Gain = GainValue & 0x00FF;
+
+               RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, OffsetValue);
+               Rssi0Offset = OffsetValue & 0x00FF;
+               Rssi1Offset = (OffsetValue & 0xFF00) >> 8;
+               RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_BG_OFFSET + 2)/* 0x48 */, OffsetValue);
+               Rssi2Offset = OffsetValue & 0x00FF;
+       }
+       else
+       {
+               LNA_Gain = (GainValue & 0xFF00) >> 8;
+
+               RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, OffsetValue);
+               Rssi0Offset = OffsetValue & 0x00FF;
+               Rssi1Offset = (OffsetValue & 0xFF00) >> 8;
+               RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET + 2)/* 0x4C */, OffsetValue);
+               Rssi2Offset = OffsetValue & 0x00FF;
+       }
+       //**********************************************************************
+       {
+               pAd->ate.Channel = channel;
+               ATEAsicSwitchChannel(pAd);
+               mdelay(5);
+
+               data = 0x10;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, data);
+               data = 0x40;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, data);
+               data = 0x40;
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, data);
+               mdelay(5);
+
+               // Start Rx
+               pAd->ate.bQARxStart = TRUE;
+               Set_ATE_Proc(pAd, "RXFRAME");
+
+               mdelay(5);
+
+               for (j = 0; j < 10; j++)
+               {
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R50, &BbpR50Rssi0);
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R51, &BbpR51Rssi1);
+                       ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R52, &BbpR52Rssi2);
+
+                       mdelay(10);
+
+                       // Calculate RSSI 0
+                       if (BbpR50Rssi0 == 0)
+                       {
+                               RSSI0 = -100;
+                       }
+                       else
+                       {
+                               RSSI0 = (INT32)(-12 - BbpR50Rssi0 - LNA_Gain - Rssi0Offset);
+                       }
+                       RSSI[0][j] = RSSI0;
+
+                       if ( pAd->Antenna.field.RxPath >= 2 ) // 2R
+                       {
+                               // Calculate RSSI 1
+                               if (BbpR51Rssi1 == 0)
+                               {
+                                       RSSI1 = -100;
+                               }
+                               else
+                               {
+                                       RSSI1 = (INT32)(-12 - BbpR51Rssi1 - LNA_Gain - Rssi1Offset);
+                               }
+                               RSSI[1][j] = RSSI1;
+                       }
+
+                       if ( pAd->Antenna.field.RxPath >= 3 ) // 3R
+                       {
+                               // Calculate RSSI 2
+                               if (BbpR52Rssi2 == 0)
+                                       RSSI2 = -100;
+                               else
+                                       RSSI2 = (INT32)(-12 - BbpR52Rssi2 - LNA_Gain - Rssi2Offset);
+
+                               RSSI[2][j] = RSSI2;
+                       }
+               }
+
+               // Stop Rx
+               Set_ATE_Proc(pAd, "RXSTOP");
+
+               mdelay(5);
+
+#if 0// Debug Message................
+               ate_print("\n**********************************************************\n");
+               ate_print("Noise Level: Channel %d\n", channel);
+               ate_print("RSSI0 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+                       RSSI[0][0], RSSI[0][1], RSSI[0][2],
+                       RSSI[0][3], RSSI[0][4], RSSI[0][5],
+                       RSSI[0][6], RSSI[0][7], RSSI[0][8],
+                       RSSI[0][9]);
+               if ( pAd->Antenna.field.RxPath >= 2 ) // 2R
+               {
+                       ate_print("RSSI1 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+                               RSSI[1][0], RSSI[1][1], RSSI[1][2],
+                               RSSI[1][3], RSSI[1][4], RSSI[1][5],
+                               RSSI[1][6], RSSI[1][7], RSSI[1][8],
+                               RSSI[1][9]);
+               }
+               if ( pAd->Antenna.field.RxPath >= 3 ) // 3R
+               {
+                       ate_print("RSSI2 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+                               RSSI[2][0], RSSI[2][1], RSSI[2][2],
+                               RSSI[2][3], RSSI[2][4], RSSI[2][5],
+                               RSSI[2][6], RSSI[2][7], RSSI[2][8],
+                               RSSI[2][9]);
+               }
+#endif // 0 //
+               BubbleSort(10, RSSI[0]);        // 1R
+
+               if ( pAd->Antenna.field.RxPath >= 2 ) // 2R
+               {
+                       BubbleSort(10, RSSI[1]);
+               }
+
+               if ( pAd->Antenna.field.RxPath >= 3 ) // 3R
+               {
+                       BubbleSort(10, RSSI[2]);
+               }
+
+#if 0// Debug Message................
+               ate_print("\nAfter Sorting....Channel %d\n", channel);
+               ate_print("RSSI0 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+                       RSSI[0][0], RSSI[0][1], RSSI[0][2],
+                       RSSI[0][3], RSSI[0][4], RSSI[0][5],
+                       RSSI[0][6], RSSI[0][7], RSSI[0][8],
+                       RSSI[0][9]);
+               if ( pAd->Antenna.field.RxPath >= 2 ) // 2R
+               {
+                       ate_print("RSSI1 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+                               RSSI[1][0], RSSI[1][1], RSSI[1][2],
+                               RSSI[1][3], RSSI[1][4], RSSI[1][5],
+                               RSSI[1][6], RSSI[1][7], RSSI[1][8],
+                               RSSI[1][9]);
+               }
+               if ( pAd->Antenna.field.RxPath >= 3 ) // 3R
+               {
+                       ate_print("RSSI2 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+                               RSSI[2][0], RSSI[2][1], RSSI[2][2],
+                               RSSI[2][3], RSSI[2][4], RSSI[2][5],
+                               RSSI[2][6], RSSI[2][7], RSSI[2][8],
+                               RSSI[2][9]);
+               }
+               ate_print("**********************************************************\n");
+#endif // 0 //
+       }
+
+       pAd->ate.Channel = Org_Channel;
+       ATEAsicSwitchChannel(pAd);
+
+       // Restore original value
+    ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, Org_BBP66value);
+    ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, Org_BBP69value);
+    ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, Org_BBP70value);
+
+       return;
+}
+
+BOOLEAN SyncTxRxConfig(PRTMP_ADAPTER pAd, USHORT offset, UCHAR value)
+{
+       UCHAR tmp = 0, bbp_data = 0;
+
+       if (ATE_ON(pAd))
+       {
+               ATE_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data);
+       }
+       else
+       {
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data);
+       }
+
+       /* confirm again */
+       ASSERT(bbp_data == value);
+
+       switch(offset)
+       {
+               case BBP_R1:
+                       /* Need to sync. tx configuration with legacy ATE. */
+                       tmp = (bbp_data & ((1 << 4) | (1 << 3))/* 0x18 */) >> 3;
+                   switch(tmp)
+                   {
+                               /* The BBP R1 bit[4:3] = 2 :: Both DACs will be used by QA. */
+                       case 2:
+                                       /* All */
+                                       pAd->ate.TxAntennaSel = 0;
+                           break;
+                               /* The BBP R1 bit[4:3] = 0 :: DAC 0 will be used by QA. */
+                       case 0:
+                                       /* Antenna one */
+                                       pAd->ate.TxAntennaSel = 1;
+                           break;
+                               /* The BBP R1 bit[4:3] = 1 :: DAC 1 will be used by QA. */
+                       case 1:
+                                       /* Antenna two */
+                                       pAd->ate.TxAntennaSel = 2;
+                           break;
+                       default:
+                           DBGPRINT(RT_DEBUG_TRACE, ("%s -- Sth. wrong!  : return FALSE; \n", __FUNCTION__));
+                           return FALSE;
+                   }
+                       break;/* case BBP_R1 */
+
+               case BBP_R3:
+                       /* Need to sync. rx configuration with legacy ATE. */
+                       tmp = (bbp_data & ((1 << 1) | (1 << 0))/* 0x03 */);
+                   switch(tmp)
+                   {
+                               /* The BBP R3 bit[1:0] = 3 :: All ADCs will be used by QA. */
+                       case 3:
+                                       /* All */
+                                       pAd->ate.RxAntennaSel = 0;
+                           break;
+                               /* The BBP R3 bit[1:0] = 0 :: ADC 0 will be used by QA, */
+                               /* unless the BBP R3 bit[4:3] = 2 */
+                       case 0:
+                                       /* Antenna one */
+                                       pAd->ate.RxAntennaSel = 1;
+                                       tmp = ((bbp_data & ((1 << 4) | (1 << 3))/* 0x03 */) >> 3);
+                                       if (tmp == 2)// 3R
+                                       {
+                                               /* Default : All ADCs will be used by QA */
+                                               pAd->ate.RxAntennaSel = 0;
+                                       }
+                           break;
+                               /* The BBP R3 bit[1:0] = 1 :: ADC 1 will be used by QA. */
+                       case 1:
+                                       /* Antenna two */
+                                       pAd->ate.RxAntennaSel = 2;
+                           break;
+                               /* The BBP R3 bit[1:0] = 2 :: ADC 2 will be used by QA. */
+                       case 2:
+                                       /* Antenna three */
+                                       pAd->ate.RxAntennaSel = 3;
+                           break;
+                       default:
+                           DBGPRINT(RT_DEBUG_ERROR, ("%s -- Impossible!  : return FALSE; \n", __FUNCTION__));
+                           return FALSE;
+                   }
+                       break;/* case BBP_R3 */
+
+        default:
+            DBGPRINT(RT_DEBUG_ERROR, ("%s -- Sth. wrong!  : return FALSE; \n", __FUNCTION__));
+            return FALSE;
+
+       }
+       return TRUE;
+}
+
+static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len)
+{
+       ULONG i, Value = 0;
+       ULONG *pDst, *pSrc;
+       UCHAR *p8;
+
+       p8 = src;
+       pDst = (ULONG *) dst;
+       pSrc = (ULONG *) src;
+
+       for (i = 0 ; i < (len/4); i++)
+       {
+               /* For alignment issue, we need a variable "Value". */
+               memmove(&Value, pSrc, 4);
+               Value = htonl(Value);
+               memmove(pDst, &Value, 4);
+               pDst++;
+               pSrc++;
+       }
+       if ((len % 4) != 0)
+       {
+               /* wish that it will never reach here */
+               memmove(&Value, pSrc, (len % 4));
+               Value = htonl(Value);
+               memmove(pDst, &Value, (len % 4));
+       }
+}
+
+static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len)
+{
+       ULONG i;
+       UCHAR *pDst, *pSrc;
+
+       pDst = dst;
+       pSrc = src;
+
+       for (i = 0; i < (len/2); i++)
+       {
+               memmove(pDst, pSrc, 2);
+               *((USHORT *)pDst) = htons(*((USHORT *)pDst));
+               pDst+=2;
+               pSrc+=2;
+       }
+
+       if ((len % 2) != 0)
+       {
+               memmove(pDst, pSrc, 1);
+       }
+}
+
+static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len)
+{
+       UINT32 i, Value;
+       UINT32 *pDst, *pSrc;
+
+       pDst = (UINT32 *) dst;
+       pSrc = (UINT32 *) src;
+
+       for (i = 0 ; i < (len/4); i++)
+       {
+               RTMP_IO_READ32(pAd, (ULONG)pSrc, &Value);
+               Value = htonl(Value);
+               memmove(pDst, &Value, 4);
+               pDst++;
+               pSrc++;
+       }
+       return;
+}
+
+// TODO:
+#if 0
+/* These work only when RALINK_ATE is defined */
+INT Set_TxStart_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ULONG value = simple_strtol(arg, 0, 10);
+       UCHAR buffer[26] = {0x88, 0x02, 0x2c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x00, 0x55, 0x44, 0x33, 0x22, 0x11, 0xc0, 0x22, 0x00, 0x00};
+       POS_COOKIE pObj;
+
+       if (pAd->ate.TxStatus != 0)
+               return FALSE;
+
+       pAd->ate.TxInfo = 0x04000000;
+       bzero(&pAd->ate.TxWI, sizeof(TXWI_STRUC));
+       pAd->ate.TxWI.PHYMODE = 0;// MODE_CCK
+       pAd->ate.TxWI.MPDUtotalByteCount = 1226;
+       pAd->ate.TxWI.MCS = 3;
+       //pAd->ate.Mode = ATE_START;
+       pAd->ate.Mode |= ATE_TXFRAME;
+       pAd->ate.TxCount = value;
+       pAd->ate.QID = 0;
+       pAd->ate.HLen = 26;
+       pAd->ate.PLen = 0;
+       pAd->ate.DLen = 1200;
+       memcpy(pAd->ate.Header, buffer, 26);
+       pAd->ate.bQATxStart = TRUE;
+       //pObj = (POS_COOKIE) pAd->OS_Cookie;
+       //tasklet_hi_schedule(&pObj->AteTxTask);
+       return TRUE;
+}
+#endif  /* end of #if 0 */
+
+INT Set_TxStop_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ATEDBGPRINT(RT_DEBUG_TRACE,("Set_TxStop_Proc\n"));
+
+       if (Set_ATE_Proc(pAd, "TXSTOP"))
+       {
+       return TRUE;
+}
+       else
+       {
+               return FALSE;
+       }
+}
+
+INT Set_RxStop_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       ATEDBGPRINT(RT_DEBUG_TRACE,("Set_RxStop_Proc\n"));
+
+       if (Set_ATE_Proc(pAd, "RXSTOP"))
+       {
+       return TRUE;
+}
+       else
+       {
+               return FALSE;
+       }
+}
+
+#if 0
+INT Set_EEWrite_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       USHORT offset = 0, value;
+       PUCHAR p2 = arg;
+
+       while((*p2 != ':') && (*p2 != '\0'))
+       {
+               p2++;
+       }
+
+       if (*p2 == ':')
+       {
+               A2Hex(offset, arg);
+               A2Hex(value, p2+ 1);
+       }
+       else
+       {
+               A2Hex(value, arg);
+       }
+
+       if (offset >= EEPROM_SIZE)
+       {
+               ate_print("Offset can not exceed EEPROM_SIZE( == 0x%04x)\n", EEPROM_SIZE);
+               return FALSE;
+       }
+
+       RTMP_EEPROM_WRITE16(pAd, offset, value);
+
+       return TRUE;
+}
+
+INT Set_BBPRead_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UCHAR value = 0, offset;
+
+       A2Hex(offset, arg);
+
+       if (ATE_ON(pAd))
+       {
+               ATE_BBP_IO_READ8_BY_REG_ID(pAd, offset,  &value);
+       }
+       else
+       {
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, offset,  &value);
+       }
+
+       ate_print("%x\n", value);
+
+       return TRUE;
+}
+
+
+INT Set_BBPWrite_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       USHORT offset = 0;
+       PUCHAR p2 = arg;
+       UCHAR value;
+
+       while((*p2 != ':') && (*p2 != '\0'))
+       {
+               p2++;
+       }
+
+       if (*p2 == ':')
+       {
+               A2Hex(offset, arg);
+               A2Hex(value, p2+ 1);
+       }
+       else
+       {
+               A2Hex(value, arg);
+       }
+
+       if (ATE_ON(pAd))
+       {
+               ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, offset,  value);
+       }
+       else
+       {
+               RTNP_BBP_IO_WRITE8_BY_REG_ID(pAd, offset,  value);
+       }
+
+       return TRUE;
+}
+
+INT Set_RFWrite_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       PUCHAR p2, p3, p4;
+       ULONG R1, R2, R3, R4;
+
+       p2 = arg;
+
+       while((*p2 != ':') && (*p2 != '\0'))
+       {
+               p2++;
+       }
+
+       if (*p2 != ':')
+               return FALSE;
+
+       p3 = p2 + 1;
+
+       while((*p3 != ':') && (*p3 != '\0'))
+       {
+               p3++;
+       }
+
+       if (*p3 != ':')
+               return FALSE;
+
+       p4 = p3 + 1;
+
+       while((*p4 != ':') && (*p4 != '\0'))
+       {
+               p4++;
+       }
+
+       if (*p4 != ':')
+               return FALSE;
+
+
+       A2Hex(R1, arg);
+       A2Hex(R2, p2 + 1);
+       A2Hex(R3, p3 + 1);
+       A2Hex(R4, p4 + 1);
+
+       RTMP_RF_IO_WRITE32(pAd, R1);
+       RTMP_RF_IO_WRITE32(pAd, R2);
+       RTMP_RF_IO_WRITE32(pAd, R3);
+       RTMP_RF_IO_WRITE32(pAd, R4);
+
+       return TRUE;
+}
+#endif  // end of #if 0 //
+#endif // RALINK_28xx_QA //
+
+#endif // RALINK_ATE //
+
diff --git a/drivers/staging/rt2870/rt_ate.h b/drivers/staging/rt2870/rt_ate.h
new file mode 100644 (file)
index 0000000..b618ce3
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#ifndef __ATE_H__
+#define __ATE_H__
+
+#ifndef UCOS
+#define ate_print printk
+#define ATEDBGPRINT DBGPRINT
+
+#ifdef RT2870
+#define EEPROM_SIZE                                                            0x400
+#ifdef CONFIG_STA_SUPPORT
+#define EEPROM_BIN_FILE_NAME  "/etc/Wireless/RT2870STA/e2p.bin"
+#endif // CONFIG_STA_SUPPORT //
+#endif // RT2870 //
+#else // !UCOS //
+#define fATE_LOAD_EEPROM                                               0x0C43
+#ifdef CONFIG_PRINTK
+extern INT ConsoleResponse(IN PUCHAR buff);
+extern int (*remote_display)(char *);
+extern void puts (const char *s);
+
+/* specificly defined to redirect and show ate-related messages to host. */
+/* Try to define ate_print as a macro. */
+#define ate_print(fmt, args...)                 \
+do{   int (*org_remote_display)(char *) = NULL;   \
+       org_remote_display = remote_display;\
+       /* Save original "remote_display" */\
+       remote_display = (int (*)(char *))ConsoleResponse;           \
+       printk(fmt, ## args);                       \
+       /* Restore the remote_display function pointer */        \
+       remote_display = org_remote_display; }while(0)
+
+#define ATEDBGPRINT(Level, Fmt)        \
+{                                   \
+    if ((Level) <= RTDebugLevel)      \
+    {                               \
+        ate_print Fmt;                                 \
+    }                               \
+}
+#endif // CONFIG_PRINTK //
+#endif // !UCOS //
+
+#define ATE_ON(_p)              (((_p)->ate.Mode) != ATE_STOP)
+
+/* RT2880_iNIC will define "RT2860". */
+
+/* RT2880_iNIC will define RT2860. */
+
+#ifdef RT2870
+#define EEPROM_SIZE                                                            0x400
+#ifdef CONFIG_STA_SUPPORT
+#define EEPROM_BIN_FILE_NAME  "/etc/Wireless/RT2870STA/e2p.bin"
+#endif // CONFIG_STA_SUPPORT //
+#endif // RT2870 //
+
+#ifdef RT2870
+#define ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV)    RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV)
+#define ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V)    RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V)
+
+#define BULK_OUT_LOCK(pLock, IrqFlags) \
+               if(1 /*!(in_interrupt() & 0xffff0000)*/)        \
+                       RTMP_IRQ_LOCK((pLock), IrqFlags);
+
+#define BULK_OUT_UNLOCK(pLock, IrqFlags)       \
+               if(1 /*!(in_interrupt() & 0xffff0000)*/)        \
+                       RTMP_IRQ_UNLOCK((pLock), IrqFlags);
+
+// Prototypes of completion funuc.
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#define ATE_RTUSBBulkOutDataPacketComplete(purb, pt_regs)    ATE_RTUSBBulkOutDataPacketComplete(purb)
+#endif
+
+VOID ATE_RTUSBBulkOutDataPacketComplete(
+       IN purbb_t purb,
+       OUT struct pt_regs *pt_regs);
+
+VOID ATE_RTUSBBulkOutDataPacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   BulkOutPipeId);
+
+VOID ATE_RTUSBCancelPendingBulkInIRP(
+       IN      PRTMP_ADAPTER   pAd);
+#endif // RT2870 //
+
+VOID rt_ee_read_all(
+       IN  PRTMP_ADAPTER   pAd,
+       OUT USHORT *Data);
+
+
+VOID rt_ee_write_all(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  USHORT *Data);
+
+INT Set_ATE_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_DA_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_SA_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_BSSID_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_CHANNEL_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_TX_POWER0_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_TX_POWER1_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_TX_Antenna_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_RX_Antenna_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_TX_FREQOFFSET_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_TX_BW_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_TX_LENGTH_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_TX_COUNT_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_TX_MCS_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_TX_MODE_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_TX_GI_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+
+INT    Set_ATE_RX_FER_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_ATE_Read_RF_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_ATE_Write_RF1_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_ATE_Write_RF2_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_ATE_Write_RF3_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_ATE_Write_RF4_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_ATE_Load_E2P_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_ATE_Read_E2P_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_Show_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ATE_Help_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+#ifdef RALINK_ATE
+#ifdef RALINK_28xx_QA
+VOID ATE_QA_Statistics(
+       IN PRTMP_ADAPTER                pAd,
+       IN PRXWI_STRUC                  pRxWI,
+       IN PRT28XX_RXD_STRUC    p28xxRxD,
+       IN PHEADER_802_11               pHeader);
+
+VOID RtmpDoAte(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq);
+
+VOID BubbleSort(
+       IN  INT32 n,
+       IN  INT32 a[]);
+
+VOID CalNoiseLevel(
+       IN  PRTMP_ADAPTER   pAdapter,
+       IN  UCHAR           channel,
+       OUT INT32           buffer[3][10]);
+
+BOOLEAN SyncTxRxConfig(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      USHORT                  offset,
+       IN      UCHAR                   value);
+
+#if 0
+INT Set_TxStart_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif  // 0 //
+
+INT Set_TxStop_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_RxStop_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+#if 0
+INT Set_EERead_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_EEWrite_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_BBPRead_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_BBPWrite_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_RFWrite_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif // end of #if 0 //
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+VOID ATEAsicSwitchChannel(
+       IN PRTMP_ADAPTER pAd);
+
+VOID ATEAsicAdjustTxPower(
+       IN PRTMP_ADAPTER pAd);
+
+VOID ATEDisableAsicProtect(
+       IN              PRTMP_ADAPTER   pAd);
+
+CHAR ATEConvertToRssi(
+       IN PRTMP_ADAPTER  pAd,
+       IN CHAR                         Rssi,
+       IN UCHAR    RssiNumber);
+
+VOID ATESampleRssi(
+       IN PRTMP_ADAPTER        pAd,
+       IN PRXWI_STRUC          pRxWI);
+
+
+#ifdef CONFIG_STA_SUPPORT
+VOID RTMPStationStop(
+    IN  PRTMP_ADAPTER   pAd);
+
+VOID RTMPStationStart(
+    IN  PRTMP_ADAPTER   pAd);
+#endif // CONFIG_STA_SUPPORT //
+#endif // __ATE_H__ //
diff --git a/drivers/staging/rt2870/rt_config.h b/drivers/staging/rt2870/rt_config.h
new file mode 100644 (file)
index 0000000..e3fe264
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       rt_config.h
+
+       Abstract:
+       Central header file to maintain all include files for all NDIS
+       miniport driver routines.
+
+       Revision History:
+       Who         When          What
+       --------    ----------    ----------------------------------------------
+       Paul Lin    08-01-2002    created
+
+*/
+#ifndef        __RT_CONFIG_H__
+#define        __RT_CONFIG_H__
+
+#include    "rtmp_type.h"
+#ifdef UCOS
+#include "includes.h"
+#include <stdio.h>
+#include       "rt_ucos.h"
+#endif
+
+#ifdef LINUX
+#include       "rt_linux.h"
+#endif
+#include    "rtmp_def.h"
+#include    "rt28xx.h"
+
+
+#ifdef RT2870
+#include       "rt2870.h"
+#endif // RT2870 //
+
+#include    "oid.h"
+#include    "mlme.h"
+#include    "wpa.h"
+#include    "md5.h"
+#include    "rtmp.h"
+#include       "ap.h"
+#include       "dfs.h"
+#include       "chlist.h"
+#include       "spectrum.h"
+
+
+#ifdef LEAP_SUPPORT
+#include    "leap.h"
+#endif // LEAP_SUPPORT //
+
+#ifdef BLOCK_NET_IF
+#include "netif_block.h"
+#endif // BLOCK_NET_IF //
+
+#ifdef IGMP_SNOOP_SUPPORT
+#include "igmp_snoop.h"
+#endif // IGMP_SNOOP_SUPPORT //
+
+#ifdef RALINK_ATE
+#include "rt_ate.h"
+#endif // RALINK_ATE //
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+#ifndef WPA_SUPPLICANT_SUPPORT
+#error "Build for being controlled by NetworkManager or wext, please set HAS_WPA_SUPPLICANT=y and HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y"
+#endif // WPA_SUPPLICANT_SUPPORT //
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef IKANOS_VX_1X0
+#include       "vr_ikans.h"
+#endif // IKANOS_VX_1X0 //
+
+#endif // __RT_CONFIG_H__
+
diff --git a/drivers/staging/rt2870/rt_linux.c b/drivers/staging/rt2870/rt_linux.c
new file mode 100644 (file)
index 0000000..f2ea8eb
--- /dev/null
@@ -0,0 +1,1095 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#include "rt_config.h"
+
+ULONG  RTDebugLevel = RT_DEBUG_ERROR;
+
+BUILD_TIMER_FUNCTION(MlmePeriodicExec);
+//BUILD_TIMER_FUNCTION(MlmeRssiReportExec);
+BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout);
+BUILD_TIMER_FUNCTION(APSDPeriodicExec);
+BUILD_TIMER_FUNCTION(AsicRfTuningExec);
+#ifdef RT2870
+BUILD_TIMER_FUNCTION(BeaconUpdateExec);
+#endif // RT2870 //
+
+
+#ifdef CONFIG_STA_SUPPORT
+BUILD_TIMER_FUNCTION(BeaconTimeout);
+BUILD_TIMER_FUNCTION(ScanTimeout);
+BUILD_TIMER_FUNCTION(AuthTimeout);
+BUILD_TIMER_FUNCTION(AssocTimeout);
+BUILD_TIMER_FUNCTION(ReassocTimeout);
+BUILD_TIMER_FUNCTION(DisassocTimeout);
+BUILD_TIMER_FUNCTION(LinkDownExec);
+#ifdef LEAP_SUPPORT
+BUILD_TIMER_FUNCTION(LeapAuthTimeout);
+#endif
+BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec);
+BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc);
+#ifdef QOS_DLS_SUPPORT
+BUILD_TIMER_FUNCTION(DlsTimeoutAction);
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+// for wireless system event message
+char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
+       // system status event
+    "had associated successfully",                                                     /* IW_ASSOC_EVENT_FLAG */
+    "had disassociated",                                                                       /* IW_DISASSOC_EVENT_FLAG */
+    "had deauthenticated",                                                                     /* IW_DEAUTH_EVENT_FLAG */
+    "had been aged-out and disassociated",                                     /* IW_AGEOUT_EVENT_FLAG */
+    "occurred CounterMeasures attack",                                         /* IW_COUNTER_MEASURES_EVENT_FLAG */
+    "occurred replay counter different in Key Handshaking",    /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
+    "occurred RSNIE different in Key Handshaking",                     /* IW_RSNIE_DIFF_EVENT_FLAG */
+    "occurred MIC different in Key Handshaking",                       /* IW_MIC_DIFF_EVENT_FLAG */
+    "occurred ICV error in RX",                                                                /* IW_ICV_ERROR_EVENT_FLAG */
+    "occurred MIC error in RX",                                                                /* IW_MIC_ERROR_EVENT_FLAG */
+       "Group Key Handshaking timeout",                                                /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */
+       "Pairwise Key Handshaking timeout",                                             /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
+       "RSN IE sanity check failure",                                                  /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */
+       "set key done in WPA/WPAPSK",                                                   /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */
+       "set key done in WPA2/WPA2PSK",                         /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */
+       "connects with our wireless client",                    /* IW_STA_LINKUP_EVENT_FLAG */
+       "disconnects with our wireless client",                 /* IW_STA_LINKDOWN_EVENT_FLAG */
+       "scan completed"                                                                                /* IW_SCAN_COMPLETED_EVENT_FLAG */
+       "scan terminate!! Busy!! Enqueue fail!!"                                /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
+       };
+
+// for wireless IDS_spoof_attack event message
+char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
+    "detected conflict SSID",                                                          /* IW_CONFLICT_SSID_EVENT_FLAG */
+    "detected spoofed association response",                           /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
+    "detected spoofed reassociation responses",                                /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
+    "detected spoofed probe response",                                         /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
+    "detected spoofed beacon",                                                         /* IW_SPOOF_BEACON_EVENT_FLAG */
+    "detected spoofed disassociation",                                         /* IW_SPOOF_DISASSOC_EVENT_FLAG */
+    "detected spoofed authentication",                                         /* IW_SPOOF_AUTH_EVENT_FLAG */
+    "detected spoofed deauthentication",                                       /* IW_SPOOF_DEAUTH_EVENT_FLAG */
+    "detected spoofed unknown management frame",                       /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
+       "detected replay attack"                                                                /* IW_REPLAY_ATTACK_EVENT_FLAG */
+       };
+
+// for wireless IDS_flooding_attack event message
+char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = {
+       "detected authentication flooding",                                             /* IW_FLOOD_AUTH_EVENT_FLAG */
+    "detected association request flooding",                           /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
+    "detected reassociation request flooding",                         /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
+    "detected probe request flooding",                                         /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
+    "detected disassociation flooding",                                                /* IW_FLOOD_DISASSOC_EVENT_FLAG */
+    "detected deauthentication flooding",                                      /* IW_FLOOD_DEAUTH_EVENT_FLAG */
+    "detected 802.1x eap-request flooding"                                     /* IW_FLOOD_EAP_REQ_EVENT_FLAG */
+       };
+
+/* timeout -- ms */
+VOID RTMP_SetPeriodicTimer(
+       IN      NDIS_MINIPORT_TIMER *pTimer,
+       IN      unsigned long timeout)
+{
+       timeout = ((timeout*HZ) / 1000);
+       pTimer->expires = jiffies + timeout;
+       add_timer(pTimer);
+}
+
+/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
+VOID RTMP_OS_Init_Timer(
+       IN      PRTMP_ADAPTER pAd,
+       IN      NDIS_MINIPORT_TIMER *pTimer,
+       IN      TIMER_FUNCTION function,
+       IN      PVOID data)
+{
+       init_timer(pTimer);
+    pTimer->data = (unsigned long)data;
+    pTimer->function = function;
+}
+
+
+VOID RTMP_OS_Add_Timer(
+       IN      NDIS_MINIPORT_TIMER             *pTimer,
+       IN      unsigned long timeout)
+{
+       if (timer_pending(pTimer))
+               return;
+
+       timeout = ((timeout*HZ) / 1000);
+       pTimer->expires = jiffies + timeout;
+       add_timer(pTimer);
+}
+
+VOID RTMP_OS_Mod_Timer(
+       IN      NDIS_MINIPORT_TIMER             *pTimer,
+       IN      unsigned long timeout)
+{
+       timeout = ((timeout*HZ) / 1000);
+       mod_timer(pTimer, jiffies + timeout);
+}
+
+VOID RTMP_OS_Del_Timer(
+       IN      NDIS_MINIPORT_TIMER             *pTimer,
+       OUT     BOOLEAN                                 *pCancelled)
+{
+       if (timer_pending(pTimer))
+       {
+               *pCancelled = del_timer_sync(pTimer);
+       }
+       else
+       {
+               *pCancelled = TRUE;
+       }
+
+}
+
+VOID RTMP_OS_Release_Packet(
+       IN      PRTMP_ADAPTER pAd,
+       IN      PQUEUE_ENTRY  pEntry)
+{
+       //RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry);
+}
+
+// Unify all delay routine by using udelay
+VOID RTMPusecDelay(
+       IN      ULONG   usec)
+{
+       ULONG   i;
+
+       for (i = 0; i < (usec / 50); i++)
+               udelay(50);
+
+       if (usec % 50)
+               udelay(usec % 50);
+}
+
+void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time)
+{
+       time->u.LowPart = jiffies;
+}
+
+// pAd MUST allow to be NULL
+NDIS_STATUS os_alloc_mem(
+       IN      PRTMP_ADAPTER pAd,
+       OUT     PUCHAR *mem,
+       IN      ULONG  size)
+{
+       *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC);
+       if (*mem)
+               return (NDIS_STATUS_SUCCESS);
+       else
+               return (NDIS_STATUS_FAILURE);
+}
+
+// pAd MUST allow to be NULL
+NDIS_STATUS os_free_mem(
+       IN      PRTMP_ADAPTER pAd,
+       IN      PUCHAR mem)
+{
+
+       ASSERT(mem);
+       kfree(mem);
+       return (NDIS_STATUS_SUCCESS);
+}
+
+
+PNDIS_PACKET RTMP_AllocateFragPacketBuffer(
+       IN      PRTMP_ADAPTER pAd,
+       IN      ULONG   Length)
+{
+       struct sk_buff *pkt;
+
+       pkt = dev_alloc_skb(Length);
+
+       if (pkt == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length));
+       }
+
+       if (pkt)
+       {
+               RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
+       }
+
+       return (PNDIS_PACKET) pkt;
+}
+
+
+PNDIS_PACKET RTMP_AllocateTxPacketBuffer(
+       IN      PRTMP_ADAPTER pAd,
+       IN      ULONG   Length,
+       IN      BOOLEAN Cached,
+       OUT     PVOID   *VirtualAddress)
+{
+       struct sk_buff *pkt;
+
+       pkt = dev_alloc_skb(Length);
+
+       if (pkt == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length));
+       }
+
+       if (pkt)
+       {
+               RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
+               *VirtualAddress = (PVOID) pkt->data;
+       }
+       else
+       {
+               *VirtualAddress = (PVOID) NULL;
+       }
+
+       return (PNDIS_PACKET) pkt;
+}
+
+
+VOID build_tx_packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      PUCHAR  pFrame,
+       IN      ULONG   FrameLen)
+{
+
+       struct sk_buff  *pTxPkt;
+
+       ASSERT(pPacket);
+       pTxPkt = RTPKT_TO_OSPKT(pPacket);
+
+       NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
+}
+
+VOID   RTMPFreeAdapter(
+       IN      PRTMP_ADAPTER   pAd)
+{
+    POS_COOKIE os_cookie;
+       int index;
+
+       os_cookie=(POS_COOKIE)pAd->OS_Cookie;
+
+       kfree(pAd->BeaconBuf);
+
+
+       NdisFreeSpinLock(&pAd->MgmtRingLock);
+
+
+       for (index =0 ; index < NUM_OF_TX_RING; index++)
+       {
+       NdisFreeSpinLock(&pAd->TxSwQueueLock[index]);
+               NdisFreeSpinLock(&pAd->DeQueueLock[index]);
+               pAd->DeQueueRunning[index] = FALSE;
+       }
+
+       NdisFreeSpinLock(&pAd->irq_lock);
+
+
+       vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa);
+       kfree(os_cookie);
+}
+
+BOOLEAN OS_Need_Clone_Packet(void)
+{
+       return (FALSE);
+}
+
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
+               must have only one NDIS BUFFER
+               return - byte copied. 0 means can't create NDIS PACKET
+               NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket
+
+       Arguments:
+               pAd     Pointer to our adapter
+               pInsAMSDUHdr    EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
+               *pSrcTotalLen                   return total packet length. This lenght is calculated with 802.3 format packet.
+
+       Return Value:
+               NDIS_STATUS_SUCCESS
+               NDIS_STATUS_FAILURE
+
+       Note:
+
+       ========================================================================
+*/
+NDIS_STATUS RTMPCloneNdisPacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      BOOLEAN                 pInsAMSDUHdr,
+       IN      PNDIS_PACKET    pInPacket,
+       OUT PNDIS_PACKET   *ppOutPacket)
+{
+
+       struct sk_buff *pkt;
+
+       ASSERT(pInPacket);
+       ASSERT(ppOutPacket);
+
+       // 1. Allocate a packet
+       pkt = dev_alloc_skb(2048);
+
+       if (pkt == NULL)
+       {
+               return NDIS_STATUS_FAILURE;
+       }
+
+       skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
+       NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket));
+       *ppOutPacket = OSPKT_TO_RTPKT(pkt);
+
+
+       RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
+
+       printk("###Clone###\n");
+
+       return NDIS_STATUS_SUCCESS;
+}
+
+
+// the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket()
+NDIS_STATUS RTMPAllocateNdisPacket(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT PNDIS_PACKET   *ppPacket,
+       IN      PUCHAR                  pHeader,
+       IN      UINT                    HeaderLen,
+       IN      PUCHAR                  pData,
+       IN      UINT                    DataLen)
+{
+       PNDIS_PACKET    pPacket;
+       ASSERT(pData);
+       ASSERT(DataLen);
+
+       // 1. Allocate a packet
+       pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + TXPADDING_SIZE);
+       if (pPacket == NULL)
+       {
+               *ppPacket = NULL;
+#ifdef DEBUG
+               printk("RTMPAllocateNdisPacket Fail\n\n");
+#endif
+               return NDIS_STATUS_FAILURE;
+       }
+
+       // 2. clone the frame content
+       if (HeaderLen > 0)
+               NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen);
+       if (DataLen > 0)
+               NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen);
+
+       // 3. update length of packet
+       skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen);
+
+       RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
+//     printk("%s : pPacket = %p, len = %d\n", __FUNCTION__, pPacket, GET_OS_PKT_LEN(pPacket));
+       *ppPacket = pPacket;
+       return NDIS_STATUS_SUCCESS;
+}
+
+/*
+  ========================================================================
+  Description:
+       This routine frees a miniport internally allocated NDIS_PACKET and its
+       corresponding NDIS_BUFFER and allocated memory.
+  ========================================================================
+*/
+VOID RTMPFreeNdisPacket(
+       IN PRTMP_ADAPTER pAd,
+       IN PNDIS_PACKET  pPacket)
+{
+       dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
+}
+
+
+// IRQL = DISPATCH_LEVEL
+// NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same
+//                      scatter gather buffer
+NDIS_STATUS Sniff2BytesFromNdisBuffer(
+       IN      PNDIS_BUFFER    pFirstBuffer,
+       IN      UCHAR                   DesiredOffset,
+       OUT PUCHAR                      pByte0,
+       OUT PUCHAR                      pByte1)
+{
+    *pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset);
+    *pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1);
+
+       return NDIS_STATUS_SUCCESS;
+}
+
+
+void RTMP_QueryPacketInfo(
+       IN  PNDIS_PACKET pPacket,
+       OUT PACKET_INFO  *pPacketInfo,
+       OUT PUCHAR               *pSrcBufVA,
+       OUT     UINT             *pSrcBufLen)
+{
+       pPacketInfo->BufferCount = 1;
+       pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket);
+       pPacketInfo->PhysicalBufferCount = 1;
+       pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
+
+       *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
+       *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
+}
+
+void RTMP_QueryNextPacketInfo(
+       IN  PNDIS_PACKET *ppPacket,
+       OUT PACKET_INFO  *pPacketInfo,
+       OUT PUCHAR               *pSrcBufVA,
+       OUT     UINT             *pSrcBufLen)
+{
+       PNDIS_PACKET pPacket = NULL;
+
+       if (*ppPacket)
+               pPacket = GET_OS_PKT_NEXT(*ppPacket);
+
+       if (pPacket)
+       {
+               pPacketInfo->BufferCount = 1;
+               pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket);
+               pPacketInfo->PhysicalBufferCount = 1;
+               pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
+
+               *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
+               *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
+               *ppPacket = GET_OS_PKT_NEXT(pPacket);
+       }
+       else
+       {
+               pPacketInfo->BufferCount = 0;
+               pPacketInfo->pFirstBuffer = NULL;
+               pPacketInfo->PhysicalBufferCount = 0;
+               pPacketInfo->TotalPacketLength = 0;
+
+               *pSrcBufVA = NULL;
+               *pSrcBufLen = 0;
+               *ppPacket = NULL;
+       }
+}
+
+// not yet support MBSS
+PNET_DEV get_netdev_from_bssid(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   FromWhichBSSID)
+{
+    PNET_DEV dev_p = NULL;
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               dev_p = pAd->net_dev;
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       ASSERT(dev_p);
+       return dev_p; /* return one of MBSS */
+}
+
+PNDIS_PACKET DuplicatePacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      UCHAR                   FromWhichBSSID)
+{
+       struct sk_buff  *skb;
+       PNDIS_PACKET    pRetPacket = NULL;
+       USHORT                  DataSize;
+       UCHAR                   *pData;
+
+       DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
+       pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
+
+
+       skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
+       if (skb)
+       {
+               skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+               pRetPacket = OSPKT_TO_RTPKT(skb);
+       }
+
+#if 0
+       if ((skb = __dev_alloc_skb(DataSize + 2+32, MEM_ALLOC_FLAG)) != NULL)
+       {
+               skb_reserve(skb, 2+32);
+               NdisMoveMemory(skb->tail, pData, DataSize);
+               skb_put(skb, DataSize);
+               skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+               pRetPacket = OSPKT_TO_RTPKT(skb);
+       }
+#endif
+
+       return pRetPacket;
+
+}
+
+PNDIS_PACKET duplicate_pkt(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pHeader802_3,
+    IN  UINT            HdrLen,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize,
+       IN      UCHAR                   FromWhichBSSID)
+{
+       struct sk_buff  *skb;
+       PNDIS_PACKET    pPacket = NULL;
+
+
+       if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL)
+       {
+               skb_reserve(skb, 2);
+               NdisMoveMemory(skb->tail, pHeader802_3, HdrLen);
+               skb_put(skb, HdrLen);
+               NdisMoveMemory(skb->tail, pData, DataSize);
+               skb_put(skb, DataSize);
+               skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+               pPacket = OSPKT_TO_RTPKT(skb);
+       }
+
+       return pPacket;
+}
+
+
+#define TKIP_TX_MIC_SIZE               8
+PNDIS_PACKET duplicate_pkt_with_TKIP_MIC(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket)
+{
+       struct sk_buff  *skb, *newskb;
+
+
+       skb = RTPKT_TO_OSPKT(pPacket);
+       if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE)
+       {
+               // alloc a new skb and copy the packet
+               newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC);
+               dev_kfree_skb_any(skb);
+               if (newskb == NULL)
+               {
+                       DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n"));
+                       return NULL;
+               }
+               skb = newskb;
+       }
+
+       return OSPKT_TO_RTPKT(skb);
+
+#if 0
+       if ((data = skb_put(skb, TKIP_TX_MIC_SIZE)) != NULL)
+       {       // If we can extend it, well, copy it first.
+               NdisMoveMemory(data, pAd->PrivateInfo.Tx.MIC, TKIP_TX_MIC_SIZE);
+       }
+       else
+       {
+               // Otherwise, copy the packet.
+               newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC);
+               dev_kfree_skb_any(skb);
+               if (newskb == NULL)
+               {
+                       DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC to packet failed!, dropping packet\n"));
+                       return NULL;
+               }
+               skb = newskb;
+
+               NdisMoveMemory(skb->tail, pAd->PrivateInfo.Tx.MIC, TKIP_TX_MIC_SIZE);
+               skb_put(skb, TKIP_TX_MIC_SIZE);
+       }
+
+       return OSPKT_TO_RTPKT(skb);
+#endif
+
+}
+
+
+
+
+PNDIS_PACKET ClonePacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize)
+{
+       struct sk_buff  *pRxPkt;
+       struct sk_buff  *pClonedPkt;
+
+       ASSERT(pPacket);
+       pRxPkt = RTPKT_TO_OSPKT(pPacket);
+
+       // clone the packet
+       pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
+
+       if (pClonedPkt)
+       {
+       // set the correct dataptr and data len
+       pClonedPkt->dev = pRxPkt->dev;
+       pClonedPkt->data = pData;
+       pClonedPkt->len = DataSize;
+       pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len;
+               ASSERT(DataSize < 1530);
+       }
+       return pClonedPkt;
+}
+
+//
+// change OS packet DataPtr and DataLen
+//
+void  update_os_packet_info(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN  UCHAR                       FromWhichBSSID)
+{
+       struct sk_buff  *pOSPkt;
+
+       ASSERT(pRxBlk->pRxPacket);
+       pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
+
+       pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+       pOSPkt->data = pRxBlk->pData;
+       pOSPkt->len = pRxBlk->DataSize;
+       pOSPkt->tail = pOSPkt->data + pOSPkt->len;
+}
+
+
+void wlan_802_11_to_802_3_packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      PUCHAR                  pHeader802_3,
+       IN  UCHAR                       FromWhichBSSID)
+{
+       struct sk_buff  *pOSPkt;
+
+       ASSERT(pRxBlk->pRxPacket);
+       ASSERT(pHeader802_3);
+
+       pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
+
+       pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+       pOSPkt->data = pRxBlk->pData;
+       pOSPkt->len = pRxBlk->DataSize;
+       pOSPkt->tail = pOSPkt->data + pOSPkt->len;
+
+       //
+       // copy 802.3 header
+       //
+       //
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3);
+#endif // CONFIG_STA_SUPPORT //
+       }
+
+
+
+void announce_802_3_packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket)
+{
+
+       struct sk_buff  *pRxPkt;
+
+       ASSERT(pPacket);
+
+       pRxPkt = RTPKT_TO_OSPKT(pPacket);
+
+#ifdef CONFIG_STA_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+
+    /* Push up the protocol stack */
+#ifdef IKANOS_VX_1X0
+       IKANOS_DataFrameRx(pAd, pRxPkt->dev, pRxPkt, pRxPkt->len);
+#else
+       pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
+
+//#ifdef CONFIG_5VT_ENHANCE
+//     *(int*)(pRxPkt->cb) = BRIDGE_TAG;
+//#endif
+       netif_rx(pRxPkt);
+#endif // IKANOS_VX_1X0 //
+}
+
+
+PRTMP_SCATTER_GATHER_LIST
+rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg)
+{
+       sg->NumberOfElements = 1;
+       sg->Elements[0].Address =  GET_OS_PKT_DATAPTR(pPacket);
+       sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket);
+       return (sg);
+}
+
+void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen)
+{
+       unsigned char *pt;
+       int x;
+
+       if (RTDebugLevel < RT_DEBUG_TRACE)
+               return;
+
+       pt = pSrcBufVA;
+       printk("%s: %p, len = %d\n",str,  pSrcBufVA, SrcBufLen);
+       for (x=0; x<SrcBufLen; x++)
+       {
+               if (x % 16 == 0)
+                       printk("0x%04x : ", x);
+               printk("%02x ", ((unsigned char)pt[x]));
+               if (x%16 == 15) printk("\n");
+       }
+       printk("\n");
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Send log message through wireless event
+
+               Support standard iw_event with IWEVCUSTOM. It is used below.
+
+               iwreq_data.data.flags is used to store event_flag that is defined by user.
+               iwreq_data.data.length is the length of the event log.
+
+               The format of the event log is composed of the entry's MAC address and
+               the desired log message (refer to pWirelessEventText).
+
+                       ex: 11:22:33:44:55:66 has associated successfully
+
+               p.s. The requirement of Wireless Extension is v15 or newer.
+
+       ========================================================================
+*/
+VOID RTMPSendWirelessEvent(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Event_flag,
+       IN      PUCHAR                  pAddr,
+       IN      UCHAR                   BssIdx,
+       IN      CHAR                    Rssi)
+{
+#if WIRELESS_EXT >= 15
+
+       union   iwreq_data      wrqu;
+       PUCHAR  pBuf = NULL, pBufPtr = NULL;
+       USHORT  event, type, BufLen;
+       UCHAR   event_table_len = 0;
+
+       type = Event_flag & 0xFF00;
+       event = Event_flag & 0x00FF;
+
+       switch (type)
+       {
+               case IW_SYS_EVENT_FLAG_START:
+                       event_table_len = IW_SYS_EVENT_TYPE_NUM;
+                       break;
+
+               case IW_SPOOF_EVENT_FLAG_START:
+                       event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
+                       break;
+
+               case IW_FLOOD_EVENT_FLAG_START:
+                       event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
+                       break;
+       }
+
+       if (event_table_len == 0)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __FUNCTION__, type));
+               return;
+       }
+
+       if (event >= event_table_len)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __FUNCTION__, event));
+               return;
+       }
+
+       //Allocate memory and copy the msg.
+       if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL)
+       {
+               //Prepare the payload
+               memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
+
+               pBufPtr = pBuf;
+
+               if (pAddr)
+                       pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr));
+               else if (BssIdx < MAX_MBSSID_NUM)
+                       pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", BssIdx);
+               else
+                       pBufPtr += sprintf(pBufPtr, "(RT2860) ");
+
+               if (type == IW_SYS_EVENT_FLAG_START)
+                       pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]);
+               else if (type == IW_SPOOF_EVENT_FLAG_START)
+                       pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi);
+               else if (type == IW_FLOOD_EVENT_FLAG_START)
+                       pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]);
+               else
+                       pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
+
+               pBufPtr[pBufPtr - pBuf] = '\0';
+               BufLen = pBufPtr - pBuf;
+
+               memset(&wrqu, 0, sizeof(wrqu));
+           wrqu.data.flags = Event_flag;
+               wrqu.data.length = BufLen;
+
+               //send wireless event
+           wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, pBuf);
+
+               //DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __FUNCTION__, pBuf));
+
+               kfree(pBuf);
+       }
+       else
+               DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __FUNCTION__));
+#else
+       DBGPRINT(RT_DEBUG_ERROR, ("%s : The Wireless Extension MUST be v15 or newer.\n", __FUNCTION__));
+#endif  /* WIRELESS_EXT >= 15 */
+}
+
+
+#ifdef CONFIG_STA_SUPPORT
+void send_monitor_packets(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk)
+{
+    struct sk_buff     *pOSPkt;
+    wlan_ng_prism2_header *ph;
+    int rate_index = 0;
+    USHORT header_len = 0;
+    UCHAR temp_header[40] = {0};
+
+    u_int32_t ralinkrate[256] = {2,4,11,22, 12,18,24,36,48,72,96,  108,   109, 110, 111, 112, 13, 26, 39, 52,78,104, 117, 130, 26, 52, 78,104, 156, 208, 234, 260, 27, 54,81,108,162, 216, 243, 270, // Last 38
+       54, 108, 162, 216, 324, 432, 486, 540,  14, 29, 43, 57, 87, 115, 130, 144, 29, 59,87,115, 173, 230,260, 288, 30, 60,90,120,180,240,270,300,60,120,180,240,360,480,540,600, 0,1,2,3,4,5,6,7,8,9,10,
+       11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80};
+
+
+    ASSERT(pRxBlk->pRxPacket);
+    if (pRxBlk->DataSize < 10)
+    {
+        DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __FUNCTION__, pRxBlk->DataSize));
+               goto err_free_sk_buff;
+    }
+
+    if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE)
+    {
+        DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __FUNCTION__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header)));
+               goto err_free_sk_buff;
+    }
+
+    pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
+       pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
+    if (pRxBlk->pHeader->FC.Type == BTYPE_DATA)
+    {
+        pRxBlk->DataSize -= LENGTH_802_11;
+        if ((pRxBlk->pHeader->FC.ToDs == 1) &&
+            (pRxBlk->pHeader->FC.FrDs == 1))
+            header_len = LENGTH_802_11_WITH_ADDR4;
+        else
+            header_len = LENGTH_802_11;
+
+        // QOS
+       if (pRxBlk->pHeader->FC.SubType & 0x08)
+       {
+           header_len += 2;
+               // Data skip QOS contorl field
+               pRxBlk->DataSize -=2;
+       }
+
+       // Order bit: A-Ralink or HTC+
+       if (pRxBlk->pHeader->FC.Order)
+       {
+           header_len += 4;
+                       // Data skip HTC contorl field
+                       pRxBlk->DataSize -= 4;
+       }
+
+        // Copy Header
+        if (header_len <= 40)
+            NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
+
+        // skip HW padding
+       if (pRxBlk->RxD.L2PAD)
+           pRxBlk->pData += (header_len + 2);
+        else
+            pRxBlk->pData += header_len;
+    } //end if
+
+
+       if (pRxBlk->DataSize < pOSPkt->len) {
+        skb_trim(pOSPkt,pRxBlk->DataSize);
+    } else {
+        skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len));
+    } //end if
+
+    if ((pRxBlk->pData - pOSPkt->data) > 0) {
+           skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data));
+           skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data));
+    } //end if
+
+    if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) {
+        if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) {
+               DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __FUNCTION__));
+                       goto err_free_sk_buff;
+           } //end if
+    } //end if
+
+    if (header_len > 0)
+        NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len);
+
+    ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header));
+       NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header));
+
+    ph->msgcode                    = DIDmsg_lnxind_wlansniffrm;
+       ph->msglen                  = sizeof(wlan_ng_prism2_header);
+       strcpy(ph->devname, pAd->net_dev->name);
+
+    ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
+       ph->hosttime.status = 0;
+       ph->hosttime.len = 4;
+       ph->hosttime.data = jiffies;
+
+       ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
+       ph->mactime.status = 0;
+       ph->mactime.len = 0;
+       ph->mactime.data = 0;
+
+    ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
+       ph->istx.status = 0;
+       ph->istx.len = 0;
+       ph->istx.data = 0;
+
+    ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
+       ph->channel.status = 0;
+       ph->channel.len = 4;
+
+    ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel;
+
+    ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
+       ph->rssi.status = 0;
+       ph->rssi.len = 4;
+    ph->rssi.data = (u_int32_t)RTMPMaxRssi(pAd, ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2));;
+
+       ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
+       ph->signal.status = 0;
+       ph->signal.len = 4;
+       ph->signal.data = 0; //rssi + noise;
+
+       ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
+       ph->noise.status = 0;
+       ph->noise.len = 4;
+       ph->noise.data = 0;
+
+#ifdef DOT11_N_SUPPORT
+    if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX)
+    {
+       rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS);
+    }
+    else
+#endif // DOT11_N_SUPPORT //
+       if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
+       rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4;
+    else
+       rate_index = (UCHAR)(pRxBlk->pRxWI->MCS);
+    if (rate_index < 0)
+        rate_index = 0;
+    if (rate_index > 255)
+        rate_index = 255;
+
+       ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
+       ph->rate.status = 0;
+       ph->rate.len = 4;
+    ph->rate.data = ralinkrate[rate_index];
+
+       ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
+    ph->frmlen.status = 0;
+       ph->frmlen.len = 4;
+       ph->frmlen.data = (u_int32_t)pRxBlk->DataSize;
+
+
+    pOSPkt->pkt_type = PACKET_OTHERHOST;
+    pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
+    pOSPkt->ip_summed = CHECKSUM_NONE;
+    netif_rx(pOSPkt);
+
+    return;
+
+err_free_sk_buff:
+       RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+       return;
+
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify)
+{
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+       daemonize(pThreadName /*"%s",pAd->net_dev->name*/);
+
+       allow_signal(SIGTERM);
+       allow_signal(SIGKILL);
+       current->flags |= PF_NOFREEZE;
+#else
+       unsigned long flags;
+
+       daemonize();
+       reparent_to_init();
+       strcpy(current->comm, pThreadName);
+
+       siginitsetinv(&current->blocked, sigmask(SIGTERM) | sigmask(SIGKILL));
+
+       /* Allow interception of SIGKILL only
+        * Don't allow other signals to interrupt the transmission */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)
+       spin_lock_irqsave(&current->sigmask_lock, flags);
+       flush_signals(current);
+       recalc_sigpending(current);
+       spin_unlock_irqrestore(&current->sigmask_lock, flags);
+#endif
+#endif
+
+    /* signal that we've started the thread */
+       complete(pNotify);
+
+}
+
+void RTMP_IndicateMediaState(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       if (pAd->CommonCfg.bWirelessEvent)
+       {
+               if (pAd->IndicateMediaState == NdisMediaStateConnected)
+               {
+                       RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+               }
+               else
+               {
+                       RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+               }
+       }
+}
+
diff --git a/drivers/staging/rt2870/rt_linux.h b/drivers/staging/rt2870/rt_linux.h
new file mode 100644 (file)
index 0000000..8142975
--- /dev/null
@@ -0,0 +1,908 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+/***********************************************************************/
+/*                                                                     */
+/*   Program:    rt_linux.c                                            */
+/*   Created:    4/21/2006 1:17:38 PM                                  */
+/*   Author:     Wu Xi-Kun                                             */
+/*   Comments:   `description`                                         */
+/*                                                                     */
+/*---------------------------------------------------------------------*/
+/*                                                                     */
+/* History:                                                            */
+/*    Revision 1.1 4/21/2006 1:17:38 PM  xsikun                        */
+/*    Initial revision                                                 */
+/*                                                                     */
+/***********************************************************************/
+
+#include "rtmp_type.h"
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/wireless.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/if_arp.h>
+#include <linux/ctype.h>
+#include <linux/vmalloc.h>
+
+
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+
+// load firmware
+#define __KERNEL_SYSCALLS__
+#include <linux/unistd.h>
+#include <asm/uaccess.h>
+
+
+#define MEM_ALLOC_FLAG      (GFP_ATOMIC) //(GFP_DMA | GFP_ATOMIC)
+
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+
+//#define CONFIG_CKIP_SUPPORT
+
+#undef __inline
+#define __inline          static inline
+
+typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_dev);
+
+// add by kathy
+
+#ifdef CONFIG_STA_SUPPORT
+
+#ifdef RT2870
+#define STA_PROFILE_PATH                       "/etc/Wireless/RT2870STA/RT2870STA.dat"
+#define STA_RT2870_IMAGE_FILE_NAME  "/etc/Wireless/RT2870STA/rt2870.bin"
+#define STA_NIC_DEVICE_NAME                    "RT2870STA"
+#define STA_DRIVER_VERSION                     "1.4.0.0"
+#ifdef MULTIPLE_CARD_SUPPORT
+#define CARD_INFO_PATH                 "/etc/Wireless/RT2870STA/RT2870STACard.dat"
+#endif // MULTIPLE_CARD_SUPPORT //
+#endif // RT2870 //
+
+#endif // CONFIG_STA_SUPPORT //
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+
+#define RTMP_TIME_AFTER(a,b)           \
+       (typecheck(unsigned long, (unsigned long)a) && \
+        typecheck(unsigned long, (unsigned long)b) && \
+        ((long)(b) - (long)(a) < 0))
+
+#define RTMP_TIME_AFTER_EQ(a,b)        \
+       (typecheck(unsigned long, (unsigned long)a) && \
+        typecheck(unsigned long, (unsigned long)b) && \
+        ((long)(a) - (long)(b) >= 0))
+#define RTMP_TIME_BEFORE(a,b)  RTMP_TIME_AFTER_EQ(b,a)
+#else
+#define RTMP_TIME_AFTER(a,b) time_after(a, b)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define RT_MOD_INC_USE_COUNT() \
+       if (!try_module_get(THIS_MODULE)) \
+       { \
+               DBGPRINT(RT_DEBUG_ERROR, ("%s: cannot reserve module\n", __FUNCTION__)); \
+               return -1; \
+       }
+
+#define RT_MOD_DEC_USE_COUNT() module_put(THIS_MODULE);
+#else
+#define RT_MOD_INC_USE_COUNT() MOD_INC_USE_COUNT;
+#define RT_MOD_DEC_USE_COUNT() MOD_DEC_USE_COUNT;
+#endif
+
+#define OS_HZ                  HZ
+
+#define ETH_LENGTH_OF_ADDRESS  6
+
+#define IN
+#define OUT
+
+#define NDIS_STATUS                             INT
+#define NDIS_STATUS_SUCCESS                     0x00
+#define NDIS_STATUS_FAILURE                     0x01
+#define NDIS_STATUS_INVALID_DATA                               0x02
+#define NDIS_STATUS_RESOURCES                   0x03
+
+#define MIN_NET_DEVICE_FOR_AID                 0x00            //0x00~0x3f
+#define MIN_NET_DEVICE_FOR_MBSSID              0x00            //0x00,0x10,0x20,0x30
+#define MIN_NET_DEVICE_FOR_WDS                 0x10            //0x40,0x50,0x60,0x70
+#define MIN_NET_DEVICE_FOR_APCLI               0x20
+#define MIN_NET_DEVICE_FOR_MESH                        0x30
+#ifdef CONFIG_STA_SUPPORT
+#define MIN_NET_DEVICE_FOR_DLS                 0x40
+#endif // CONFIG_STA_SUPPORT //
+
+
+#ifdef CONFIG_STA_SUPPORT
+#define NDIS_PACKET_TYPE_DIRECTED              0
+#define NDIS_PACKET_TYPE_MULTICAST             1
+#define NDIS_PACKET_TYPE_BROADCAST             2
+#define NDIS_PACKET_TYPE_ALL_MULTICAST 3
+#endif // CONFIG_STA_SUPPORT //
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+typedef        struct pid *    THREAD_PID;
+#define        THREAD_PID_INIT_VALUE   NULL
+#define        GET_PID(_v)     find_get_pid(_v)
+#define        GET_PID_NUMBER(_v)      pid_nr(_v)
+#define CHECK_PID_LEGALITY(_pid)       if (pid_nr(_pid) >= 0)
+#define KILL_THREAD_PID(_A, _B, _C)    kill_pid(_A, _B, _C)
+#else
+typedef        pid_t   THREAD_PID;
+#define        THREAD_PID_INIT_VALUE   -1
+#define        GET_PID(_v)     _v
+#define        GET_PID_NUMBER(_v)      _v
+#define CHECK_PID_LEGALITY(_pid)       if (_pid >= 0)
+#define KILL_THREAD_PID(_A, _B, _C)    kill_proc(_A, _B, _C)
+#endif
+
+struct os_lock  {
+       spinlock_t              lock;
+       unsigned long   flags;
+};
+
+
+struct os_cookie {
+
+#ifdef RT2870
+       struct usb_device               *pUsb_Dev;
+
+       THREAD_PID                              MLMEThr_pid;
+       THREAD_PID                              RTUSBCmdThr_pid;
+       THREAD_PID                              TimerQThr_pid;
+#endif // RT2870 //
+
+       struct tasklet_struct   rx_done_task;
+       struct tasklet_struct   mgmt_dma_done_task;
+       struct tasklet_struct   ac0_dma_done_task;
+       struct tasklet_struct   ac1_dma_done_task;
+       struct tasklet_struct   ac2_dma_done_task;
+       struct tasklet_struct   ac3_dma_done_task;
+       struct tasklet_struct   hcca_dma_done_task;
+       struct tasklet_struct   tbtt_task;
+#ifdef RT2870
+       struct tasklet_struct   null_frame_complete_task;
+       struct tasklet_struct   rts_frame_complete_task;
+       struct tasklet_struct   pspoll_frame_complete_task;
+#endif // RT2870 //
+
+
+       unsigned long                   apd_pid; //802.1x daemon pid
+       INT                                             ioctl_if_type;
+       INT                                     ioctl_if;
+};
+
+typedef struct _VIRTUAL_ADAPTER
+{
+       struct net_device               *RtmpDev;
+       struct net_device               *VirtualDev;
+} VIRTUAL_ADAPTER, PVIRTUAL_ADAPTER;
+
+#undef  ASSERT
+#define ASSERT(x)                                                               \
+{                                                                               \
+    if (!(x))                                                                   \
+    {                                                                           \
+        printk(KERN_WARNING __FILE__ ":%d assert " #x "failed\n", __LINE__);    \
+    }                                                                           \
+}
+
+typedef struct os_cookie       * POS_COOKIE;
+typedef struct pci_dev                 * PPCI_DEV;
+typedef struct net_device      * PNET_DEV;
+typedef void                           * PNDIS_PACKET;
+typedef char                           NDIS_PACKET;
+typedef PNDIS_PACKET           * PPNDIS_PACKET;
+typedef        dma_addr_t                      NDIS_PHYSICAL_ADDRESS;
+typedef        dma_addr_t                      * PNDIS_PHYSICAL_ADDRESS;
+//typedef struct timer_list    RALINK_TIMER_STRUCT;
+//typedef struct timer_list    * PRALINK_TIMER_STRUCT;
+//typedef struct os_lock               NDIS_SPIN_LOCK;
+typedef spinlock_t                     NDIS_SPIN_LOCK;
+typedef struct timer_list      NDIS_MINIPORT_TIMER;
+typedef void                           * NDIS_HANDLE;
+typedef char                           * PNDIS_BUFFER;
+
+
+
+void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen);
+
+dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction);
+void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int direction);
+
+
+////////////////////////////////////////
+// MOVE TO rtmp.h ?
+/////////////////////////////////////////
+#define PKTSRC_NDIS             0x7f
+#define PKTSRC_DRIVER           0x0f
+#define PRINT_MAC(addr)        \
+       addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
+
+
+#define RT2860_PCI_DEVICE_ID           0x0601
+
+
+#ifdef RT2870
+#define PCI_MAP_SINGLE(_handle, _ptr, _size, _dir) (ULONG)0
+
+#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir)
+#endif // RT2870 //
+
+
+#define BEACON_FRAME_DMA_CACHE_WBACK(_ptr, _size)      \
+       dma_cache_wback(_ptr, _size)
+
+
+//////////////////////////////////////////
+//
+//////////////////////////////////////////
+
+
+#define NdisMIndicateStatus(_w, _x, _y, _z)
+
+typedef struct timer_list      RTMP_OS_TIMER;
+
+#ifdef RT2870
+/* ----------------- Timer Related MARCO ---------------*/
+// In RT2870, we have a lot of timer functions and will read/write register, it's
+//     not allowed in Linux USB sub-system to do it ( because of sleep issue when submit
+//  to ctrl pipe). So we need a wrapper function to take care it.
+
+typedef VOID (*RT2870_TIMER_HANDLE)(
+       IN  PVOID   SystemSpecific1,
+       IN  PVOID   FunctionContext,
+       IN  PVOID   SystemSpecific2,
+       IN  PVOID   SystemSpecific3);
+#endif // RT2870 //
+
+
+typedef struct  _RALINK_TIMER_STRUCT    {
+    RTMP_OS_TIMER              TimerObj;       // Ndis Timer object
+       BOOLEAN                         Valid;                  // Set to True when call RTMPInitTimer
+    BOOLEAN             State;          // True if timer cancelled
+    BOOLEAN                    PeriodicType;   // True if timer is periodic timer
+    BOOLEAN             Repeat;         // True if periodic timer
+    ULONG               TimerValue;     // Timer value in milliseconds
+       ULONG                           cookie;                 // os specific object
+#ifdef RT2870
+       RT2870_TIMER_HANDLE     handle;
+       void                            *pAd;
+#endif // RT2870 //
+}   RALINK_TIMER_STRUCT, *PRALINK_TIMER_STRUCT;
+
+
+#ifdef RT2870
+
+typedef enum _RT2870_KERNEL_THREAD_STATUS_
+{
+       RT2870_THREAD_UNKNOWN = 0,
+       RT2870_THREAD_INITED = 1,
+       RT2870_THREAD_RUNNING = 2,
+       RT2870_THREAD_STOPED = 4,
+}RT2870_KERNEL_THREAD_STATUS;
+
+#define RT2870_THREAD_CAN_DO_INSERT            (RT2870_THREAD_INITED |RT2870_THREAD_RUNNING)
+
+typedef struct _RT2870_TIMER_ENTRY_
+{
+       RALINK_TIMER_STRUCT                     *pRaTimer;
+       struct _RT2870_TIMER_ENTRY_     *pNext;
+}RT2870_TIMER_ENTRY;
+
+
+#define TIMER_QUEUE_SIZE_MAX   128
+typedef struct _RT2870_TIMER_QUEUE_
+{
+       unsigned int            status;
+       //wait_queue_head_t     timerWaitQ;
+       //atomic_t                      count;
+       UCHAR                           *pTimerQPoll;
+       RT2870_TIMER_ENTRY      *pQPollFreeList;
+       RT2870_TIMER_ENTRY      *pQHead;
+       RT2870_TIMER_ENTRY      *pQTail;
+}RT2870_TIMER_QUEUE;
+#endif // RT2870 //
+
+
+//#define DBG  1
+
+//
+//  MACRO for debugging information
+//
+
+#ifdef DBG
+extern ULONG    RTDebugLevel;
+
+#define DBGPRINT_RAW(Level, Fmt)    \
+{                                   \
+    if (Level <= RTDebugLevel)      \
+    {                               \
+        printk Fmt;               \
+    }                               \
+}
+
+#define DBGPRINT(Level, Fmt)    DBGPRINT_RAW(Level, Fmt)
+
+
+#define DBGPRINT_ERR(Fmt)           \
+{                                   \
+    printk("ERROR!!! ");          \
+    printk Fmt;                  \
+}
+
+#define DBGPRINT_S(Status, Fmt)                \
+{                                                                      \
+       printk Fmt;                                     \
+}
+
+
+#else
+#define DBGPRINT(Level, Fmt)
+#define DBGPRINT_RAW(Level, Fmt)
+#define DBGPRINT_S(Status, Fmt)
+#define DBGPRINT_ERR(Fmt)
+#endif
+
+
+//
+//  spin_lock enhanced for Nested spin lock
+//
+#define NdisAllocateSpinLock(__lock)      \
+{                                       \
+    spin_lock_init((spinlock_t *)(__lock));               \
+}
+
+#define NdisFreeSpinLock(lock)          \
+{                                       \
+}
+
+
+#define RTMP_SEM_LOCK(__lock)                                  \
+{                                                                                              \
+       spin_lock_bh((spinlock_t *)(__lock));                           \
+}
+
+#define RTMP_SEM_UNLOCK(__lock)                                        \
+{                                                                                              \
+       spin_unlock_bh((spinlock_t *)(__lock));                         \
+}
+
+#if 0 // sample, IRQ LOCK
+#define RTMP_IRQ_LOCK(__lock, __irqflags)                                      \
+{                                                                                                      \
+       spin_lock_irqsave((spinlock_t *)__lock, __irqflags);    \
+       pAd->irq_disabled |= 1; \
+}
+
+#define RTMP_IRQ_UNLOCK(__lock, __irqflag)                                             \
+{                                                                                                              \
+       pAd->irq_disabled &= 0; \
+       spin_unlock_irqrestore((spinlock_t *)(__lock), ((unsigned long)__irqflag));     \
+}
+#else
+
+// sample, use semaphore lock to replace IRQ lock, 2007/11/15
+#define RTMP_IRQ_LOCK(__lock, __irqflags)                      \
+{                                                                                                      \
+       __irqflags = 0;                                                                 \
+       spin_lock_bh((spinlock_t *)(__lock));                   \
+       pAd->irq_disabled |= 1; \
+}
+
+#define RTMP_IRQ_UNLOCK(__lock, __irqflag)                     \
+{                                                                                                      \
+       pAd->irq_disabled &= 0; \
+       spin_unlock_bh((spinlock_t *)(__lock));                 \
+}
+
+#define RTMP_INT_LOCK(__lock, __irqflags)                      \
+{                                                                                                      \
+       spin_lock_irqsave((spinlock_t *)__lock, __irqflags);    \
+}
+
+#define RTMP_INT_UNLOCK(__lock, __irqflag)                     \
+{                                                                                                      \
+       spin_unlock_irqrestore((spinlock_t *)(__lock), ((unsigned long)__irqflag));     \
+}
+#endif
+
+
+
+#ifdef RT2870
+//Patch for ASIC turst read/write bug, needs to remove after metel fix
+#define RTMP_IO_READ32(_A, _R, _pV)                                                            \
+       RTUSBReadMACRegister(_A, _R, _pV)
+
+#define RTMP_IO_READ8(_A, _R, _pV)                                                             \
+{                                                                                                                              \
+}
+
+#define RTMP_IO_WRITE32(_A, _R, _V)                                                            \
+       RTUSBWriteMACRegister(_A, _R, _V)
+
+
+#define RTMP_IO_WRITE8(_A, _R, _V)                                                             \
+{                                                                                                                              \
+       USHORT  _Val = _V;                                                                                      \
+       RTUSBSingleWrite(_A, _R, _Val);                                                         \
+}
+
+
+#define RTMP_IO_WRITE16(_A, _R, _V)                                                            \
+{                                                                                                                              \
+       RTUSBSingleWrite(_A, _R, _V);                                                           \
+}
+#endif // RT2870 //
+
+#ifndef wait_event_interruptible_timeout
+#define __wait_event_interruptible_timeout(wq, condition, ret) \
+do { \
+        wait_queue_t __wait; \
+        init_waitqueue_entry(&__wait, current); \
+        add_wait_queue(&wq, &__wait); \
+        for (;;) { \
+                set_current_state(TASK_INTERRUPTIBLE); \
+                if (condition) \
+                        break; \
+                if (!signal_pending(current)) { \
+                        ret = schedule_timeout(ret); \
+                        if (!ret) \
+                                break; \
+                        continue; \
+                } \
+                ret = -ERESTARTSYS; \
+                break; \
+        } \
+        current->state = TASK_RUNNING; \
+        remove_wait_queue(&wq, &__wait); \
+} while (0)
+
+#define wait_event_interruptible_timeout(wq, condition, timeout) \
+({ \
+        long __ret = timeout; \
+        if (!(condition)) \
+                __wait_event_interruptible_timeout(wq, condition, __ret); \
+        __ret; \
+})
+#endif
+#define ONE_TICK 1
+#define OS_WAIT(_time) \
+{      int _i; \
+       long _loop = ((_time)/(1000/OS_HZ)) > 0 ? ((_time)/(1000/OS_HZ)) : 1;\
+       wait_queue_head_t _wait; \
+       init_waitqueue_head(&_wait); \
+       for (_i=0; _i<(_loop); _i++) \
+               wait_event_interruptible_timeout(_wait, 0, ONE_TICK); }
+
+
+typedef void (*TIMER_FUNCTION)(unsigned long);
+
+#define COPY_MAC_ADDR(Addr1, Addr2)             memcpy((Addr1), (Addr2), MAC_ADDR_LEN)
+
+#define MlmeAllocateMemory(_pAd, _ppVA) os_alloc_mem(_pAd, _ppVA, MGMT_DMA_BUFFER_SIZE)
+#define MlmeFreeMemory(_pAd, _pVA)     os_free_mem(_pAd, _pVA)
+
+
+#ifdef RT2870
+#define BUILD_TIMER_FUNCTION(_func)                                                                                                    \
+void linux_##_func(unsigned long data)                                                                                         \
+{                                                                                                                                                                      \
+       PRALINK_TIMER_STRUCT    _pTimer = (PRALINK_TIMER_STRUCT)data;                                   \
+       RT2870_TIMER_ENTRY              *_pQNode;                                                                                               \
+       RTMP_ADAPTER                    *_pAd;                                                                                                  \
+                                                                                                                                                               \
+       _pTimer->handle = _func;                                                                                                                        \
+       _pAd = (RTMP_ADAPTER *)_pTimer->pAd;                                                                                            \
+       _pQNode = RT2870_TimerQ_Insert(_pAd, _pTimer);                                                                  \
+       if ((_pQNode == NULL) && (_pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT))   \
+               RTMP_OS_Add_Timer(&_pTimer->TimerObj, HZ);                                                      \
+}
+#endif // RT2870 //
+
+
+#define DECLARE_TIMER_FUNCTION(_func)                  \
+void linux_##_func(unsigned long data)
+
+#define GET_TIMER_FUNCTION(_func)                              \
+               linux_##_func
+
+DECLARE_TIMER_FUNCTION(MlmePeriodicExec);
+DECLARE_TIMER_FUNCTION(MlmeRssiReportExec);
+DECLARE_TIMER_FUNCTION(AsicRxAntEvalTimeout);
+DECLARE_TIMER_FUNCTION(APSDPeriodicExec);
+DECLARE_TIMER_FUNCTION(AsicRfTuningExec);
+#ifdef RT2870
+DECLARE_TIMER_FUNCTION(BeaconUpdateExec);
+#endif // RT2870 //
+
+
+#ifdef CONFIG_STA_SUPPORT
+DECLARE_TIMER_FUNCTION(BeaconTimeout);
+DECLARE_TIMER_FUNCTION(ScanTimeout);
+DECLARE_TIMER_FUNCTION(AuthTimeout);
+DECLARE_TIMER_FUNCTION(AssocTimeout);
+DECLARE_TIMER_FUNCTION(ReassocTimeout);
+DECLARE_TIMER_FUNCTION(DisassocTimeout);
+DECLARE_TIMER_FUNCTION(LinkDownExec);
+#ifdef LEAP_SUPPORT
+DECLARE_TIMER_FUNCTION(LeapAuthTimeout);
+#endif
+DECLARE_TIMER_FUNCTION(StaQuickResponeForRateUpExec);
+DECLARE_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc);
+DECLARE_TIMER_FUNCTION(PsPollWakeExec);
+DECLARE_TIMER_FUNCTION(RadioOnExec);
+
+#ifdef QOS_DLS_SUPPORT
+DECLARE_TIMER_FUNCTION(DlsTimeoutAction);
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time);
+
+
+/*
+ * packet helper
+ *     - convert internal rt packet to os packet or
+ *             os packet to rt packet
+ */
+#define RTPKT_TO_OSPKT(_p)             ((struct sk_buff *)(_p))
+#define OSPKT_TO_RTPKT(_p)             ((PNDIS_PACKET)(_p))
+
+#define GET_OS_PKT_DATAPTR(_pkt) \
+               (RTPKT_TO_OSPKT(_pkt)->data)
+
+#define GET_OS_PKT_LEN(_pkt) \
+               (RTPKT_TO_OSPKT(_pkt)->len)
+
+#define GET_OS_PKT_DATATAIL(_pkt) \
+               (RTPKT_TO_OSPKT(_pkt)->tail)
+
+#define GET_OS_PKT_HEAD(_pkt) \
+               (RTPKT_TO_OSPKT(_pkt)->head)
+
+#define GET_OS_PKT_END(_pkt) \
+               (RTPKT_TO_OSPKT(_pkt)->end)
+
+#define GET_OS_PKT_NETDEV(_pkt) \
+               (RTPKT_TO_OSPKT(_pkt)->dev)
+
+#define GET_OS_PKT_TYPE(_pkt) \
+               (RTPKT_TO_OSPKT(_pkt))
+
+#define GET_OS_PKT_NEXT(_pkt) \
+               (RTPKT_TO_OSPKT(_pkt)->next)
+
+
+#define OS_NTOHS(_Val) \
+               (ntohs(_Val))
+#define OS_HTONS(_Val) \
+               (htons(_Val))
+#define OS_NTOHL(_Val) \
+               (ntohl(_Val))
+#define OS_HTONL(_Val) \
+               (htonl(_Val))
+
+/* statistics counter */
+#define STATS_INC_RX_PACKETS(_pAd, _dev)
+#define STATS_INC_TX_PACKETS(_pAd, _dev)
+
+#define STATS_INC_RX_BYTESS(_pAd, _dev, len)
+#define STATS_INC_TX_BYTESS(_pAd, _dev, len)
+
+#define STATS_INC_RX_ERRORS(_pAd, _dev)
+#define STATS_INC_TX_ERRORS(_pAd, _dev)
+
+#define STATS_INC_RX_DROPPED(_pAd, _dev)
+#define STATS_INC_TX_DROPPED(_pAd, _dev)
+
+
+#define CB_OFF  10
+
+
+//   check DDK NDIS_PACKET data structure and find out only MiniportReservedEx[0..7] can be used by our driver without
+//   ambiguity. Fields after pPacket->MiniportReservedEx[8] may be used by other wrapper layer thus crashes the driver
+//
+//#define RTMP_GET_PACKET_MR(_p)                       (RTPKT_TO_OSPKT(_p))
+
+// User Priority
+#define RTMP_SET_PACKET_UP(_p, _prio)                  (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0] = _prio)
+#define RTMP_GET_PACKET_UP(_p)                                 (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0])
+
+// Fragment #
+#define RTMP_SET_PACKET_FRAGMENTS(_p, _num)            (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1] = _num)
+#define RTMP_GET_PACKET_FRAGMENTS(_p)                  (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1])
+
+// 0x0 ~0x7f: TX to AP's own BSS which has the specified AID. if AID>127, set bit 7 in RTMP_SET_PACKET_EMACTAB too.
+//(this value also as MAC(on-chip WCID) table index)
+// 0x80~0xff: TX to a WDS link. b0~6: WDS index
+#define RTMP_SET_PACKET_WCID(_p, _wdsidx)              (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2] = _wdsidx)
+#define RTMP_GET_PACKET_WCID(_p)                       ((UCHAR)(RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2]))
+
+// 0xff: PKTSRC_NDIS, others: local TX buffer index. This value affects how to a packet
+#define RTMP_SET_PACKET_SOURCE(_p, _pktsrc)            (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3] = _pktsrc)
+#define RTMP_GET_PACKET_SOURCE(_p)                     (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3])
+
+// RTS/CTS-to-self protection method
+#define RTMP_SET_PACKET_RTS(_p, _num)                  (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4] = _num)
+#define RTMP_GET_PACKET_RTS(_p)                        (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4])
+// see RTMP_S(G)ET_PACKET_EMACTAB
+
+// TX rate index
+#define RTMP_SET_PACKET_TXRATE(_p, _rate)              (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5] = _rate)
+#define RTMP_GET_PACKET_TXRATE(_p)                             (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5])
+
+// From which Interface
+#define RTMP_SET_PACKET_IF(_p, _ifdx)          (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6] = _ifdx)
+#define RTMP_GET_PACKET_IF(_p)                         (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6])
+#define RTMP_SET_PACKET_NET_DEVICE_MBSSID(_p, _bss)            RTMP_SET_PACKET_IF((_p), (_bss))
+#define RTMP_SET_PACKET_NET_DEVICE_WDS(_p, _bss)               RTMP_SET_PACKET_IF((_p), ((_bss) + MIN_NET_DEVICE_FOR_WDS))
+#define RTMP_SET_PACKET_NET_DEVICE_APCLI(_p, _idx)     RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_APCLI))
+#define RTMP_SET_PACKET_NET_DEVICE_MESH(_p, _idx)      RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_MESH))
+#define RTMP_GET_PACKET_NET_DEVICE_MBSSID(_p)                  RTMP_GET_PACKET_IF((_p))
+#define RTMP_GET_PACKET_NET_DEVICE(_p)                                 RTMP_GET_PACKET_IF((_p))
+
+#define RTMP_SET_PACKET_MOREDATA(_p, _morebit)         (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7] = _morebit)
+#define RTMP_GET_PACKET_MOREDATA(_p)                           (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7])
+
+//#define RTMP_SET_PACKET_NET_DEVICE_MBSSID(_p, _bss)  (RTPKT_TO_OSPKT(_p)->cb[8] = _bss)
+//#define RTMP_GET_PACKET_NET_DEVICE_MBSSID(_p)                (RTPKT_TO_OSPKT(_p)->cb[8])
+
+
+
+
+#if 0
+//#define RTMP_SET_PACKET_DHCP(_p, _flg)       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] = _flg)
+//#define RTMP_GET_PACKET_DHCP(_p)             (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11])
+#else
+//
+//     Sepcific Pakcet Type definition
+//
+#define RTMP_PACKET_SPECIFIC_CB_OFFSET 11
+
+#define RTMP_PACKET_SPECIFIC_DHCP              0x01
+#define RTMP_PACKET_SPECIFIC_EAPOL             0x02
+#define RTMP_PACKET_SPECIFIC_IPV4              0x04
+#define RTMP_PACKET_SPECIFIC_WAI               0x08
+#define RTMP_PACKET_SPECIFIC_VLAN              0x10
+#define RTMP_PACKET_SPECIFIC_LLCSNAP   0x20
+
+//Specific
+#define RTMP_SET_PACKET_SPECIFIC(_p, _flg)             (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] = _flg)
+
+//DHCP
+#define RTMP_SET_PACKET_DHCP(_p, _flg)                                                                                                         \
+                       do{                                                                                                                                                             \
+                               if (_flg)                                                                                                                                       \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_DHCP);             \
+                               else                                                                                                                                            \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_DHCP);    \
+                       }while(0)
+#define RTMP_GET_PACKET_DHCP(_p)               (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_DHCP)
+
+//EAPOL
+#define RTMP_SET_PACKET_EAPOL(_p, _flg)                                                                                                        \
+                       do{                                                                                                                                                             \
+                               if (_flg)                                                                                                                                       \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_EAPOL);            \
+                               else                                                                                                                                            \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_EAPOL);   \
+                       }while(0)
+#define RTMP_GET_PACKET_EAPOL(_p)              (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_EAPOL)
+
+//WAI
+#define RTMP_SET_PACKET_WAI(_p, _flg)                                                                                                          \
+                       do{                                                                                                                                                             \
+                               if (_flg)                                                                                                                                       \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_WAI);              \
+                               else                                                                                                                                            \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_WAI);     \
+                       }while(0)
+#define RTMP_GET_PACKET_WAI(_p)                (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_WAI)
+
+#define RTMP_GET_PACKET_LOWRATE(_p)            (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & (RTMP_PACKET_SPECIFIC_EAPOL | RTMP_PACKET_SPECIFIC_DHCP | RTMP_PACKET_SPECIFIC_WAI))
+
+//VLAN
+#define RTMP_SET_PACKET_VLAN(_p, _flg)                                                                                                         \
+                       do{                                                                                                                                                             \
+                               if (_flg)                                                                                                                                       \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_VLAN);             \
+                               else                                                                                                                                            \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_VLAN);    \
+                       }while(0)
+#define RTMP_GET_PACKET_VLAN(_p)               (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_VLAN)
+
+//LLC/SNAP
+#define RTMP_SET_PACKET_LLCSNAP(_p, _flg)                                                                                                      \
+                       do{                                                                                                                                                             \
+                               if (_flg)                                                                                                                                       \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_LLCSNAP);          \
+                               else                                                                                                                                            \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_LLCSNAP);         \
+                       }while(0)
+
+#define RTMP_GET_PACKET_LLCSNAP(_p)            (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_LLCSNAP)
+
+// IP
+#define RTMP_SET_PACKET_IPV4(_p, _flg)                                                                                                         \
+                       do{                                                                                                                                                             \
+                               if (_flg)                                                                                                                                       \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_IPV4);             \
+                               else                                                                                                                                            \
+                                       (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_IPV4);    \
+                       }while(0)
+
+#define RTMP_GET_PACKET_IPV4(_p)               (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_IPV4)
+
+#endif
+
+
+// If this flag is set, it indicates that this EAPoL frame MUST be clear.
+#define RTMP_SET_PACKET_CLEAR_EAP_FRAME(_p, _flg)   (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12] = _flg)
+#define RTMP_GET_PACKET_CLEAR_EAP_FRAME(_p)         (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12])
+
+#define RTMP_SET_PACKET_5VT(_p, _flg)   (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22] = _flg)
+#define RTMP_GET_PACKET_5VT(_p)         (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22])
+
+
+#ifdef CONFIG_5VT_ENHANCE
+#define BRIDGE_TAG 0x35564252    // depends on 5VT define in br_input.c
+#endif
+
+
+#define NDIS_SET_PACKET_STATUS(_p, _status)
+
+
+#define GET_SG_LIST_FROM_PACKET(_p, _sc)       \
+    rt_get_sg_list_from_packet(_p, _sc)
+
+
+#define NdisMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length)
+#define NdisZeroMemory(Destination, Length)         memset(Destination, 0, Length)
+#define NdisFillMemory(Destination, Length, Fill)   memset(Destination, Fill, Length)
+#define NdisEqualMemory(Source1, Source2, Length)   (!memcmp(Source1, Source2, Length))
+#define RTMPEqualMemory(Source1, Source2, Length)      (!memcmp(Source1, Source2, Length))
+
+
+#define RTMP_INC_REF(_A)               0
+#define RTMP_DEC_REF(_A)               0
+#define RTMP_GET_REF(_A)               0
+
+
+
+/*
+ * ULONG
+ * RTMP_GetPhysicalAddressLow(
+ *   IN NDIS_PHYSICAL_ADDRESS  PhysicalAddress);
+ */
+#define RTMP_GetPhysicalAddressLow(PhysicalAddress)            (PhysicalAddress)
+
+/*
+ * ULONG
+ * RTMP_GetPhysicalAddressHigh(
+ *   IN NDIS_PHYSICAL_ADDRESS  PhysicalAddress);
+ */
+#define RTMP_GetPhysicalAddressHigh(PhysicalAddress)           (0)
+
+/*
+ * VOID
+ * RTMP_SetPhysicalAddressLow(
+ *   IN NDIS_PHYSICAL_ADDRESS  PhysicalAddress,
+ *   IN ULONG  Value);
+ */
+#define RTMP_SetPhysicalAddressLow(PhysicalAddress, Value)     \
+                       PhysicalAddress = Value;
+
+/*
+ * VOID
+ * RTMP_SetPhysicalAddressHigh(
+ *   IN NDIS_PHYSICAL_ADDRESS  PhysicalAddress,
+ *   IN ULONG  Value);
+ */
+#define RTMP_SetPhysicalAddressHigh(PhysicalAddress, Value)
+
+
+//CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx);
+#define QUEUE_ENTRY_TO_PACKET(pEntry) \
+       (PNDIS_PACKET)(pEntry)
+
+#define PACKET_TO_QUEUE_ENTRY(pPacket) \
+       (PQUEUE_ENTRY)(pPacket)
+
+
+#ifndef CONTAINING_RECORD
+#define CONTAINING_RECORD(address, type, field)                        \
+((type *)((PCHAR)(address) - offsetof(type, field)))
+#endif
+
+
+#define RELEASE_NDIS_PACKET(_pAd, _pPacket, _Status)                    \
+{                                                                       \
+        RTMPFreeNdisPacket(_pAd, _pPacket);                             \
+}
+
+
+#define SWITCH_PhyAB(_pAA, _pBB)    \
+{                                                                           \
+    ULONG      AABasePaHigh;                           \
+    ULONG      AABasePaLow;                           \
+    ULONG      BBBasePaHigh;                           \
+    ULONG      BBBasePaLow;                           \
+    BBBasePaHigh = RTMP_GetPhysicalAddressHigh(_pBB);                                                 \
+    BBBasePaLow = RTMP_GetPhysicalAddressLow(_pBB);                                                 \
+    AABasePaHigh = RTMP_GetPhysicalAddressHigh(_pAA);                                                 \
+    AABasePaLow = RTMP_GetPhysicalAddressLow(_pAA);                                                 \
+    RTMP_SetPhysicalAddressHigh(_pAA, BBBasePaHigh);                                                 \
+    RTMP_SetPhysicalAddressLow(_pAA, BBBasePaLow);                                                 \
+    RTMP_SetPhysicalAddressHigh(_pBB, AABasePaHigh);                                                 \
+    RTMP_SetPhysicalAddressLow(_pBB, AABasePaLow);                                                 \
+}
+
+
+#define NdisWriteErrorLogEntry(_a, _b, _c, _d)
+#define NdisMAllocateMapRegisters(_a, _b, _c, _d, _e)          NDIS_STATUS_SUCCESS
+
+
+#define NdisAcquireSpinLock            RTMP_SEM_LOCK
+#define NdisReleaseSpinLock            RTMP_SEM_UNLOCK
+
+static inline void NdisGetSystemUpTime(ULONG *time)
+{
+       *time = jiffies;
+}
+
+//pPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx);
+#define QUEUE_ENTRY_TO_PKT(pEntry) \
+               ((PNDIS_PACKET) (pEntry))
+
+int rt28xx_packet_xmit(struct sk_buff *skb);
+
+
+
+void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify);
+
+
diff --git a/drivers/staging/rt2870/rt_main_dev.c b/drivers/staging/rt2870/rt_main_dev.c
new file mode 100644 (file)
index 0000000..16cace7
--- /dev/null
@@ -0,0 +1,1863 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    rt_main_dev.c
+
+    Abstract:
+    Create and register network interface.
+
+    Revision History:
+    Who         When            What
+    --------    ----------      ----------------------------------------------
+       Sample          Mar/21/07               Merge RT2870 and RT2860 drivers.
+*/
+
+#include "rt_config.h"
+
+#define FORTY_MHZ_INTOLERANT_INTERVAL  (60*1000) // 1 min
+
+#ifdef MULTIPLE_CARD_SUPPORT
+// record whether the card in the card list is used in the card file
+UINT8  MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD];
+// record used card mac address in the card list
+static UINT8  MC_CardMac[MAX_NUM_OF_MULTIPLE_CARD][6];
+#endif // MULTIPLE_CARD_SUPPORT //
+
+/*---------------------------------------------------------------------*/
+/* Private Variables Used                                              */
+/*---------------------------------------------------------------------*/
+//static RALINK_TIMER_STRUCT     PeriodicTimer;
+
+char *mac = "";                   // default 00:00:00:00:00:00
+char *hostname = "";
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
+MODULE_PARM (mac, "s");
+#else
+module_param (mac, charp, 0);
+#endif
+MODULE_PARM_DESC (mac, "rt28xx: wireless mac addr");
+
+
+/*---------------------------------------------------------------------*/
+/* Prototypes of Functions Used                                        */
+/*---------------------------------------------------------------------*/
+#ifdef DOT11_N_SUPPORT
+extern BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num);
+extern void ba_reordering_resource_release(PRTMP_ADAPTER pAd);
+#endif // DOT11_N_SUPPORT //
+extern NDIS_STATUS NICLoadRateSwitchingParams(IN PRTMP_ADAPTER pAd);
+
+
+// public function prototype
+INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
+                                                       IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
+
+// private function prototype
+static int rt28xx_init(IN struct net_device *net_dev);
+INT rt28xx_send_packets(IN struct sk_buff *skb_p, IN struct net_device *net_dev);
+
+#if LINUX_VERSION_CODE <= 0x20402      // Red Hat 7.1
+struct net_device *alloc_netdev(
+       int sizeof_priv,
+       const char *mask,
+       void (*setup)(struct net_device *));
+#endif // LINUX_VERSION_CODE //
+
+static void CfgInitHook(PRTMP_ADAPTER pAd);
+//static BOOLEAN RT28XXAvailRANameAssign(IN CHAR *name_p);
+
+#ifdef CONFIG_STA_SUPPORT
+extern const struct iw_handler_def rt28xx_iw_handler_def;
+#endif // CONFIG_STA_SUPPORT //
+
+#if WIRELESS_EXT >= 12
+// This function will be called when query /proc
+struct iw_statistics *rt28xx_get_wireless_stats(
+    IN struct net_device *net_dev);
+#endif
+
+struct net_device_stats *RT28xx_get_ether_stats(
+    IN  struct net_device *net_dev);
+
+/*
+========================================================================
+Routine Description:
+    Close raxx interface.
+
+Arguments:
+       *net_dev                        the raxx interface pointer
+
+Return Value:
+    0                                  Open OK
+       otherwise                       Open Fail
+
+Note:
+       1. if open fail, kernel will not call the close function.
+       2. Free memory for
+               (1) Mlme Memory Handler:                MlmeHalt()
+               (2) TX & RX:                                    RTMPFreeTxRxRingMemory()
+               (3) BA Reordering:                              ba_reordering_resource_release()
+========================================================================
+*/
+int MainVirtualIF_close(IN struct net_device *net_dev)
+{
+    RTMP_ADAPTER *pAd = net_dev->priv;
+
+       // Sanity check for pAd
+       if (pAd == NULL)
+               return 0; // close ok
+
+       netif_carrier_off(pAd->net_dev);
+       netif_stop_queue(pAd->net_dev);
+
+
+
+       VIRTUAL_IF_DOWN(pAd);
+
+       RT_MOD_DEC_USE_COUNT();
+
+       return 0; // close ok
+}
+
+/*
+========================================================================
+Routine Description:
+    Open raxx interface.
+
+Arguments:
+       *net_dev                        the raxx interface pointer
+
+Return Value:
+    0                                  Open OK
+       otherwise                       Open Fail
+
+Note:
+       1. if open fail, kernel will not call the close function.
+       2. Free memory for
+               (1) Mlme Memory Handler:                MlmeHalt()
+               (2) TX & RX:                                    RTMPFreeTxRxRingMemory()
+               (3) BA Reordering:                              ba_reordering_resource_release()
+========================================================================
+*/
+int MainVirtualIF_open(IN struct net_device *net_dev)
+{
+    RTMP_ADAPTER *pAd = net_dev->priv;
+
+       // Sanity check for pAd
+       if (pAd == NULL)
+               return 0; // close ok
+
+       if (VIRTUAL_IF_UP(pAd) != 0)
+               return -1;
+
+       // increase MODULE use count
+       RT_MOD_INC_USE_COUNT();
+
+       netif_start_queue(net_dev);
+       netif_carrier_on(net_dev);
+       netif_wake_queue(net_dev);
+
+       return 0;
+}
+
+/*
+========================================================================
+Routine Description:
+    Close raxx interface.
+
+Arguments:
+       *net_dev                        the raxx interface pointer
+
+Return Value:
+    0                                  Open OK
+       otherwise                       Open Fail
+
+Note:
+       1. if open fail, kernel will not call the close function.
+       2. Free memory for
+               (1) Mlme Memory Handler:                MlmeHalt()
+               (2) TX & RX:                                    RTMPFreeTxRxRingMemory()
+               (3) BA Reordering:                              ba_reordering_resource_release()
+========================================================================
+*/
+int rt28xx_close(IN PNET_DEV dev)
+{
+       struct net_device * net_dev = (struct net_device *)dev;
+    RTMP_ADAPTER       *pAd = net_dev->priv;
+       BOOLEAN                 Cancelled = FALSE;
+       UINT32                  i = 0;
+#ifdef RT2870
+       DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup);
+       DECLARE_WAITQUEUE(wait, current);
+
+       //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
+#endif // RT2870 //
+
+
+    DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n"));
+
+       // Sanity check for pAd
+       if (pAd == NULL)
+               return 0; // close ok
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+
+               // If dirver doesn't wake up firmware here,
+               // NICLoadFirmware will hang forever when interface is up again.
+               if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+        {
+                   AsicForceWakeup(pAd, TRUE);
+        }
+
+#ifdef QOS_DLS_SUPPORT
+               // send DLS-TEAR_DOWN message,
+               if (pAd->CommonCfg.bDLSCapable)
+               {
+                       UCHAR i;
+
+                       // tear down local dls table entry
+                       for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+                       {
+                               if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+                               {
+                                       RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+                                       pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
+                                       pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                               }
+                       }
+
+                       // tear down peer dls table entry
+                       for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+                       {
+                               if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+                               {
+                                       RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+                                       pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+                                       pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                               }
+                       }
+                       RT28XX_MLME_HANDLER(pAd);
+               }
+#endif // QOS_DLS_SUPPORT //
+
+               if (INFRA_ON(pAd) &&
+                       (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+               {
+                       MLME_DISASSOC_REQ_STRUCT        DisReq;
+                       MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+
+                       COPY_MAC_ADDR(DisReq.Addr, pAd->CommonCfg.Bssid);
+                       DisReq.Reason =  REASON_DEAUTH_STA_LEAVING;
+
+                       MsgElem->Machine = ASSOC_STATE_MACHINE;
+                       MsgElem->MsgType = MT2_MLME_DISASSOC_REQ;
+                       MsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT);
+                       NdisMoveMemory(MsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT));
+
+                       // Prevent to connect AP again in STAMlmePeriodicExec
+                       pAd->MlmeAux.AutoReconnectSsidLen= 32;
+                       NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
+
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC;
+                       MlmeDisassocReqAction(pAd, MsgElem);
+                       kfree(MsgElem);
+
+                       RTMPusecDelay(1000);
+               }
+
+#ifdef RT2870
+       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
+#endif // RT2870 //
+
+#ifdef CCX_SUPPORT
+               RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &Cancelled);
+#endif
+
+               RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled);
+               RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+               {
+                       union iwreq_data    wrqu;
+                       // send wireless event to wpa_supplicant for infroming interface down.
+                       memset(&wrqu, 0, sizeof(wrqu));
+                       wrqu.data.flags = RT_INTERFACE_DOWN;
+                       wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+               }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+               MlmeRadioOff(pAd);
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+
+       for (i = 0 ; i < NUM_OF_TX_RING; i++)
+       {
+               while (pAd->DeQueueRunning[i] == TRUE)
+               {
+                       printk("Waiting for TxQueue[%d] done..........\n", i);
+                       RTMPusecDelay(1000);
+               }
+       }
+
+#ifdef RT2870
+       // ensure there are no more active urbs.
+       add_wait_queue (&unlink_wakeup, &wait);
+       pAd->wait = &unlink_wakeup;
+
+       // maybe wait for deletions to finish.
+       i = 0;
+       //while((i < 25) && atomic_read(&pAd->PendingRx) > 0)
+       while(i < 25)
+       {
+               unsigned long IrqFlags;
+
+               RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+               if (pAd->PendingRx == 0)
+               {
+                       RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+                       break;
+               }
+               RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
+               msleep(UNLINK_TIMEOUT_MS);      //Time in millisecond
+#else
+               RTMPusecDelay(UNLINK_TIMEOUT_MS*1000);  //Time in microsecond
+#endif
+               i++;
+       }
+       pAd->wait = NULL;
+       remove_wait_queue (&unlink_wakeup, &wait);
+#endif // RT2870 //
+
+       //RTUSBCleanUpMLMEWaitQueue(pAd);       /*not used in RT28xx*/
+
+
+#ifdef RT2870
+       // We need clear timerQ related structure before exits of the timer thread.
+       RT2870_TimerQ_Exit(pAd);
+       // Close kernel threads or tasklets
+       RT28xxThreadTerminate(pAd);
+#endif // RT2870 //
+
+       // Stop Mlme state machine
+       MlmeHalt(pAd);
+
+       // Close kernel threads or tasklets
+       kill_thread_task(pAd);
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               MacTableReset(pAd);
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+
+       MeasureReqTabExit(pAd);
+       TpcReqTabExit(pAd);
+
+
+
+
+       // Free Ring or USB buffers
+       RTMPFreeTxRxRingMemory(pAd);
+
+       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+
+#ifdef DOT11_N_SUPPORT
+       // Free BA reorder resource
+       ba_reordering_resource_release(pAd);
+#endif // DOT11_N_SUPPORT //
+
+#ifdef RT2870
+#ifdef INF_AMAZON_SE
+       if (pAd->UsbVendorReqBuf)
+               os_free_mem(pAd, pAd->UsbVendorReqBuf);
+#endif // INF_AMAZON_SE //
+#endif // RT2870 //
+
+       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP);
+
+       return 0; // close ok
+} /* End of rt28xx_close */
+
+static int rt28xx_init(IN struct net_device *net_dev)
+{
+       PRTMP_ADAPTER                   pAd = (PRTMP_ADAPTER)net_dev->priv;
+       UINT                                    index;
+       UCHAR                                   TmpPhy;
+       NDIS_STATUS                             Status;
+       UINT32          MacCsr0 = 0;
+
+#ifdef RT2870
+#ifdef INF_AMAZON_SE
+       init_MUTEX(&(pAd->UsbVendorReq_semaphore));
+       os_alloc_mem(pAd, (PUCHAR)&pAd->UsbVendorReqBuf, MAX_PARAM_BUFFER_SIZE - 1);
+       if (pAd->UsbVendorReqBuf == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Allocate vendor request temp buffer failed!\n"));
+               goto err0;
+       }
+#endif // INF_AMAZON_SE //
+#endif // RT2870 //
+
+#ifdef DOT11_N_SUPPORT
+       // Allocate BA Reordering memory
+       ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM);
+#endif // DOT11_N_SUPPORT //
+
+       // Make sure MAC gets ready.
+       index = 0;
+       do
+       {
+               RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0);
+               pAd->MACVersion = MacCsr0;
+
+               if ((pAd->MACVersion != 0x00) && (pAd->MACVersion != 0xFFFFFFFF))
+                       break;
+
+               RTMPusecDelay(10);
+       } while (index++ < 100);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0  [ Ver:Rev=0x%08x]\n", pAd->MACVersion));
+
+       // Disable DMA
+       RT28XXDMADisable(pAd);
+
+
+       // Load 8051 firmware
+       Status = NICLoadFirmware(pAd);
+       if (Status != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status));
+               goto err1;
+       }
+
+       NICLoadRateSwitchingParams(pAd);
+
+       // Disable interrupts here which is as soon as possible
+       // This statement should never be true. We might consider to remove it later
+
+       Status = RTMPAllocTxRxRingMemory(pAd);
+       if (Status != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT_ERR(("RTMPAllocDMAMemory failed, Status[=0x%08x]\n", Status));
+               goto err1;
+       }
+
+       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
+
+       // initialize MLME
+       //
+
+       Status = MlmeInit(pAd);
+       if (Status != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status));
+               goto err2;
+       }
+
+       // Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default
+       //
+       UserCfgInit(pAd);
+
+#ifdef RT2870
+       // We need init timerQ related structure before create the timer thread.
+       RT2870_TimerQ_Init(pAd);
+#endif // RT2870 //
+
+       RT28XX_TASK_THREAD_INIT(pAd, Status);
+       if (Status != NDIS_STATUS_SUCCESS)
+               goto err1;
+
+//     COPY_MAC_ADDR(pAd->ApCfg.MBSSID[apidx].Bssid, netif->hwaddr);
+//     pAd->bForcePrintTX = TRUE;
+
+       CfgInitHook(pAd);
+
+
+#ifdef BLOCK_NET_IF
+       initblockQueueTab(pAd);
+#endif // BLOCK_NET_IF //
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               NdisAllocateSpinLock(&pAd->MacTabLock);
+#endif // CONFIG_STA_SUPPORT //
+
+       MeasureReqTabInit(pAd);
+       TpcReqTabInit(pAd);
+
+       //
+       // Init the hardware, we need to init asic before read registry, otherwise mac register will be reset
+       //
+       Status = NICInitializeAdapter(pAd, TRUE);
+       if (Status != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", Status));
+               if (Status != NDIS_STATUS_SUCCESS)
+               goto err3;
+       }
+
+       // Read parameters from Config File
+       Status = RTMPReadParametersHook(pAd);
+
+       printk("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode);
+       if (Status != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT_ERR(("NICReadRegParameters failed, Status[=0x%08x]\n",Status));
+               goto err4;
+       }
+
+#ifdef RT2870
+       pAd->CommonCfg.bMultipleIRP = FALSE;
+
+       if (pAd->CommonCfg.bMultipleIRP)
+               pAd->CommonCfg.NumOfBulkInIRP = RX_RING_SIZE;
+       else
+               pAd->CommonCfg.NumOfBulkInIRP = 1;
+#endif // RT2870 //
+
+
+       //Init Ba Capability parameters.
+//     RT28XX_BA_INIT(pAd);
+#ifdef DOT11_N_SUPPORT
+       pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
+       pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable;
+       pAd->CommonCfg.DesiredHtPhy.AmsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize;
+       pAd->CommonCfg.DesiredHtPhy.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode;
+       // UPdata to HT IE
+       pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode;
+       pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize;
+       pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
+#endif // DOT11_N_SUPPORT //
+
+       // after reading Registry, we now know if in AP mode or STA mode
+
+       // Load 8051 firmware; crash when FW image not existent
+       // Status = NICLoadFirmware(pAd);
+       // if (Status != NDIS_STATUS_SUCCESS)
+       //    break;
+
+       printk("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode);
+
+       // We should read EEPROM for all cases.  rt2860b
+       NICReadEEPROMParameters(pAd, mac);
+#ifdef CONFIG_STA_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+
+       printk("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode);
+
+       NICInitAsicFromEEPROM(pAd); //rt2860b
+
+       // Set PHY to appropriate mode
+       TmpPhy = pAd->CommonCfg.PhyMode;
+       pAd->CommonCfg.PhyMode = 0xff;
+       RTMPSetPhyMode(pAd, TmpPhy);
+#ifdef DOT11_N_SUPPORT
+       SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+
+       // No valid channels.
+       if (pAd->ChannelListNum == 0)
+       {
+               printk("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n");
+               goto err4;
+       }
+
+#ifdef DOT11_N_SUPPORT
+       printk("MCS Set = %02x %02x %02x %02x %02x\n", pAd->CommonCfg.HtCapability.MCSSet[0],
+           pAd->CommonCfg.HtCapability.MCSSet[1], pAd->CommonCfg.HtCapability.MCSSet[2],
+           pAd->CommonCfg.HtCapability.MCSSet[3], pAd->CommonCfg.HtCapability.MCSSet[4]);
+#endif // DOT11_N_SUPPORT //
+
+#ifdef RT2870
+    //Init RT30xx RFRegisters after read RFIC type from EEPROM
+       NICInitRT30xxRFRegisters(pAd);
+#endif // RT2870 //
+
+#if 0
+       // Patch cardbus controller if EEPROM said so.
+       if (pAd->bTest1 == FALSE)
+               RTMPPatchCardBus(pAd);
+#endif
+
+
+//             APInitialize(pAd);
+
+#ifdef IKANOS_VX_1X0
+       VR_IKANOS_FP_Init(pAd->ApCfg.BssidNum, pAd->PermanentAddress);
+#endif // IKANOS_VX_1X0 //
+
+               //
+       // Initialize RF register to default value
+       //
+       AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+       AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+
+       // 8051 firmware require the signal during booting time.
+       AsicSendCommandToMcu(pAd, 0x72, 0xFF, 0x00, 0x00);
+
+       if (pAd && (Status != NDIS_STATUS_SUCCESS))
+       {
+               //
+               // Undo everything if it failed
+               //
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+               {
+//                     NdisMDeregisterInterrupt(&pAd->Interrupt);
+                       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
+               }
+//             RTMPFreeAdapter(pAd); // we will free it in disconnect()
+       }
+       else if (pAd)
+       {
+               // Microsoft HCT require driver send a disconnect event after driver initialization.
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+//             pAd->IndicateMediaState = NdisMediaStateDisconnected;
+               RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
+
+               DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n"));
+
+
+#ifdef RT2870
+               RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS);
+               RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
+
+               //
+               // Support multiple BulkIn IRP,
+               // the value on pAd->CommonCfg.NumOfBulkInIRP may be large than 1.
+               //
+               for(index=0; index<pAd->CommonCfg.NumOfBulkInIRP; index++)
+               {
+                       RTUSBBulkReceive(pAd);
+                       DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkReceive!\n" ));
+               }
+#endif // RT2870 //
+       }// end of else
+
+
+       DBGPRINT_S(Status, ("<==== RTMPInitialize, Status=%x\n", Status));
+
+       return TRUE;
+
+
+err4:
+err3:
+       MlmeHalt(pAd);
+err2:
+       RTMPFreeTxRxRingMemory(pAd);
+//     RTMPFreeAdapter(pAd);
+err1:
+
+#ifdef DOT11_N_SUPPORT
+       os_free_mem(pAd, pAd->mpdu_blk_pool.mem); // free BA pool
+#endif // DOT11_N_SUPPORT //
+       RT28XX_IRQ_RELEASE(net_dev);
+
+       // shall not set priv to NULL here because the priv didn't been free yet.
+       //net_dev->priv = 0;
+#ifdef INF_AMAZON_SE
+err0:
+#endif // INF_AMAZON_SE //
+       printk("!!! %s Initialized fail !!!\n", RT28xx_CHIP_NAME);
+       return FALSE;
+} /* End of rt28xx_init */
+
+
+/*
+========================================================================
+Routine Description:
+    Open raxx interface.
+
+Arguments:
+       *net_dev                        the raxx interface pointer
+
+Return Value:
+    0                                  Open OK
+       otherwise                       Open Fail
+
+Note:
+========================================================================
+*/
+int rt28xx_open(IN PNET_DEV dev)
+{
+       struct net_device * net_dev = (struct net_device *)dev;
+       PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)net_dev->priv;
+       int retval = 0;
+       POS_COOKIE pObj;
+
+
+       // Sanity check for pAd
+       if (pAd == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -1;
+       }
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+       if (pAd->OpMode == OPMODE_AP)
+       {
+               CW_MAX_IN_BITS = 6;
+       }
+       else if (pAd->OpMode == OPMODE_STA)
+       {
+               CW_MAX_IN_BITS = 10;
+       }
+
+#if WIRELESS_EXT >= 12
+       if (net_dev->priv_flags == INT_MAIN)
+       {
+               if (pAd->OpMode == OPMODE_AP)
+                       net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_ap_iw_handler_def;
+               else if (pAd->OpMode == OPMODE_STA)
+                       net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_iw_handler_def;
+       }
+#endif // WIRELESS_EXT >= 12 //
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+
+       // Init
+       pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+       // reset Adapter flags
+       RTMP_CLEAR_FLAGS(pAd);
+
+       // Request interrupt service routine for PCI device
+       // register the interrupt routine with the os
+       RT28XX_IRQ_REQUEST(net_dev);
+
+
+       // Init BssTab & ChannelInfo tabbles for auto channel select.
+
+
+       // Chip & other init
+       if (rt28xx_init(net_dev) == FALSE)
+               goto err;
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               NdisZeroMemory(pAd->StaCfg.dev_name, 16);
+               NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name));
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       // Set up the Mac address
+       NdisMoveMemory(net_dev->dev_addr, (void *) pAd->CurrentAddress, 6);
+
+       // Init IRQ parameters
+       RT28XX_IRQ_INIT(pAd);
+
+       // Various AP function init
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+               {
+                       union iwreq_data    wrqu;
+                       // send wireless event to wpa_supplicant for infroming interface down.
+                       memset(&wrqu, 0, sizeof(wrqu));
+                       wrqu.data.flags = RT_INTERFACE_UP;
+                       wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+               }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       // Enable Interrupt
+       RT28XX_IRQ_ENABLE(pAd);
+
+       // Now Enable RxTx
+       RTMPEnableRxTx(pAd);
+       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP);
+
+       {
+       UINT32 reg = 0;
+       RTMP_IO_READ32(pAd, 0x1300, &reg);  // clear garbage interrupts
+       printk("0x1300 = %08x\n", reg);
+       }
+
+       {
+//     u32 reg;
+//     u8  byte;
+//     u16 tmp;
+
+//     RTMP_IO_READ32(pAd, XIFS_TIME_CFG, &reg);
+
+//     tmp = 0x0805;
+//     reg  = (reg & 0xffff0000) | tmp;
+//     RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, reg);
+
+       }
+
+#if 0
+       /*
+        * debugging helper
+        *              show the size of main table in Adapter structure
+        *              MacTab  -- 185K
+        *              BATable -- 137K
+        *              Total   -- 385K  !!!!! (5/26/2006)
+        */
+       printk("sizeof(pAd->MacTab) = %ld\n", sizeof(pAd->MacTab));
+       printk("sizeof(pAd->AccessControlList) = %ld\n", sizeof(pAd->AccessControlList));
+       printk("sizeof(pAd->ApCfg) = %ld\n", sizeof(pAd->ApCfg));
+       printk("sizeof(pAd->BATable) = %ld\n", sizeof(pAd->BATable));
+       BUG();
+#endif
+
+#ifdef CONFIG_STA_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+
+       return (retval);
+
+err:
+       return (-1);
+} /* End of rt28xx_open */
+
+
+/* Must not be called for mdev and apdev */
+static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER pAd)
+{
+       NDIS_STATUS Status;
+       INT     i=0;
+       CHAR    slot_name[IFNAMSIZ];
+       struct net_device   *device;
+
+
+       //ether_setup(dev);
+       dev->hard_start_xmit = rt28xx_send_packets;
+
+#ifdef IKANOS_VX_1X0
+       dev->hard_start_xmit = IKANOS_DataFramesTx;
+#endif // IKANOS_VX_1X0 //
+
+//     dev->set_multicast_list = ieee80211_set_multicast_list;
+//     dev->change_mtu = ieee80211_change_mtu;
+#ifdef CONFIG_STA_SUPPORT
+#if WIRELESS_EXT >= 12
+       if (pAd->OpMode == OPMODE_STA)
+       {
+               dev->wireless_handlers = &rt28xx_iw_handler_def;
+       }
+#endif //WIRELESS_EXT >= 12
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+#if WIRELESS_EXT >= 12
+       if (pAd->OpMode == OPMODE_AP)
+       {
+               dev->wireless_handlers = &rt28xx_ap_iw_handler_def;
+       }
+#endif //WIRELESS_EXT >= 12
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+#if WIRELESS_EXT < 21
+               dev->get_wireless_stats = rt28xx_get_wireless_stats;
+#endif
+       dev->get_stats = RT28xx_get_ether_stats;
+       dev->open = MainVirtualIF_open; //rt28xx_open;
+       dev->stop = MainVirtualIF_close; //rt28xx_close;
+//     dev->uninit = ieee80211_if_reinit;
+//     dev->destructor = ieee80211_if_free;
+       dev->priv_flags = INT_MAIN;
+       dev->do_ioctl = rt28xx_ioctl;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+    dev->validate_addr = NULL;
+#endif
+       // find available device name
+       for (i = 0; i < 8; i++)
+       {
+#ifdef MULTIPLE_CARD_SUPPORT
+               if (pAd->MC_RowID >= 0)
+                       sprintf(slot_name, "ra%02d_%d", pAd->MC_RowID, i);
+               else
+#endif // MULTIPLE_CARD_SUPPORT //
+               sprintf(slot_name, "ra%d", i);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+        device = dev_get_by_name(dev_net(dev), slot_name);
+#else
+        device = dev_get_by_name(dev->nd_net, slot_name);
+#endif
+#else
+               device = dev_get_by_name(slot_name);
+#endif
+               if (device != NULL) dev_put(device);
+#else
+               for (device = dev_base; device != NULL; device = device->next)
+               {
+                       if (strncmp(device->name, slot_name, 4) == 0)
+                               break;
+               }
+#endif
+               if(device == NULL)
+                       break;
+       }
+
+       if(i == 8)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("No available slot name\n"));
+               Status = NDIS_STATUS_FAILURE;
+       }
+       else
+       {
+#ifdef MULTIPLE_CARD_SUPPORT
+               if (pAd->MC_RowID >= 0)
+               sprintf(dev->name, "ra%02d_%d", pAd->MC_RowID, i);
+               else
+#endif // MULTIPLE_CARD_SUPPORT //
+               sprintf(dev->name, "ra%d", i);
+               Status = NDIS_STATUS_SUCCESS;
+       }
+
+       return Status;
+
+}
+
+
+#ifdef MULTIPLE_CARD_SUPPORT
+/*
+========================================================================
+Routine Description:
+    Get card profile path.
+
+Arguments:
+    pAd
+
+Return Value:
+    TRUE               - Find a card profile
+       FALSE           - use default profile
+
+Note:
+========================================================================
+*/
+extern INT RTMPGetKeyParameter(
+    IN  PCHAR   key,
+    OUT PCHAR   dest,
+    IN  INT     destsize,
+    IN  PCHAR   buffer);
+
+BOOLEAN RTMP_CardInfoRead(
+       IN      PRTMP_ADAPTER pAd)
+{
+#define MC_SELECT_CARDID               0       /* use CARD ID (0 ~ 31) to identify different cards */
+#define MC_SELECT_MAC                  1       /* use CARD MAC to identify different cards */
+#define MC_SELECT_CARDTYPE             2       /* use CARD type (abgn or bgn) to identify different cards */
+
+#define LETTER_CASE_TRANSLATE(txt_p, card_id)                  \
+       {       UINT32 _len; char _char;                                                \
+               for(_len=0; _len<strlen(card_id); _len++) {             \
+                       _char = *(txt_p + _len);                                        \
+                       if (('A' <= _char) && (_char <= 'Z'))           \
+                               *(txt_p+_len) = 'a'+(_char-'A');                \
+               } }
+
+       struct file *srcf;
+       INT retval, orgfsuid, orgfsgid;
+       mm_segment_t orgfs;
+       CHAR *buffer, *tmpbuf, card_id_buf[30], RFIC_word[30];
+       BOOLEAN flg_match_ok = FALSE;
+       INT32 card_select_method;
+       INT32 card_free_id, card_nouse_id, card_same_mac_id, card_match_id;
+       EEPROM_ANTENNA_STRUC antenna;
+       USHORT addr01, addr23, addr45;
+       UINT8 mac[6];
+       UINT32 data, card_index;
+       UCHAR *start_ptr;
+
+
+       // init
+       buffer = kmalloc(MAX_INI_BUFFER_SIZE, MEM_ALLOC_FLAG);
+       if (buffer == NULL)
+        return FALSE;
+
+       tmpbuf = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+       if(tmpbuf == NULL)
+       {
+               kfree(buffer);
+        return NDIS_STATUS_FAILURE;
+       }
+
+       orgfsuid = current->fsuid;
+       orgfsgid = current->fsgid;
+       current->fsuid = current->fsgid = 0;
+    orgfs = get_fs();
+    set_fs(KERNEL_DS);
+
+       // get RF IC type
+       RTMP_IO_READ32(pAd, E2PROM_CSR, &data);
+
+       if ((data & 0x30) == 0)
+               pAd->EEPROMAddressNum = 6;      // 93C46
+       else if ((data & 0x30) == 0x10)
+               pAd->EEPROMAddressNum = 8;      // 93C66
+       else
+               pAd->EEPROMAddressNum = 8;      // 93C86
+
+       //antenna.word = RTMP_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET);
+       RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, antenna.word);
+
+       if ((antenna.field.RfIcType == RFIC_2850) ||
+               (antenna.field.RfIcType == RFIC_2750))
+       {
+               /* ABGN card */
+               strcpy(RFIC_word, "abgn");
+       }
+       else
+       {
+               /* BGN card */
+               strcpy(RFIC_word, "bgn");
+       }
+
+       // get MAC address
+       //addr01 = RTMP_EEPROM_READ16(pAd, 0x04);
+       //addr23 = RTMP_EEPROM_READ16(pAd, 0x06);
+       //addr45 = RTMP_EEPROM_READ16(pAd, 0x08);
+       RT28xx_EEPROM_READ16(pAd, 0x04, addr01);
+       RT28xx_EEPROM_READ16(pAd, 0x06, addr23);
+       RT28xx_EEPROM_READ16(pAd, 0x08, addr45);
+
+       mac[0] = (UCHAR)(addr01 & 0xff);
+       mac[1] = (UCHAR)(addr01 >> 8);
+       mac[2] = (UCHAR)(addr23 & 0xff);
+       mac[3] = (UCHAR)(addr23 >> 8);
+       mac[4] = (UCHAR)(addr45 & 0xff);
+       mac[5] = (UCHAR)(addr45 >> 8);
+
+       // open card information file
+       srcf = filp_open(CARD_INFO_PATH, O_RDONLY, 0);
+       if (IS_ERR(srcf))
+       {
+               /* card information file does not exist */
+                       DBGPRINT(RT_DEBUG_TRACE,
+                               ("--> Error %ld opening %s\n", -PTR_ERR(srcf), CARD_INFO_PATH));
+               return FALSE;
+       }
+
+       if (srcf->f_op && srcf->f_op->read)
+       {
+               /* card information file exists so reading the card information */
+               memset(buffer, 0x00, MAX_INI_BUFFER_SIZE);
+               retval = srcf->f_op->read(srcf, buffer, MAX_INI_BUFFER_SIZE, &srcf->f_pos);
+               if (retval < 0)
+               {
+                       /* read fail */
+                               DBGPRINT(RT_DEBUG_TRACE,
+                                       ("--> Read %s error %d\n", CARD_INFO_PATH, -retval));
+               }
+               else
+               {
+                       /* get card selection method */
+                       memset(tmpbuf, 0x00, MAX_PARAM_BUFFER_SIZE);
+                       card_select_method = MC_SELECT_CARDTYPE; // default
+
+                       if (RTMPGetKeyParameter("SELECT", tmpbuf, 256, buffer))
+                       {
+                               if (strcmp(tmpbuf, "CARDID") == 0)
+                                       card_select_method = MC_SELECT_CARDID;
+                               else if (strcmp(tmpbuf, "MAC") == 0)
+                                       card_select_method = MC_SELECT_MAC;
+                               else if (strcmp(tmpbuf, "CARDTYPE") == 0)
+                                       card_select_method = MC_SELECT_CARDTYPE;
+                       }
+
+                       DBGPRINT(RT_DEBUG_TRACE,
+                                       ("MC> Card Selection = %d\n", card_select_method));
+
+                       // init
+                       card_free_id = -1;
+                       card_nouse_id = -1;
+                       card_same_mac_id = -1;
+                       card_match_id = -1;
+
+                       // search current card information records
+                       for(card_index=0;
+                               card_index<MAX_NUM_OF_MULTIPLE_CARD;
+                               card_index++)
+                       {
+                               if ((*(UINT32 *)&MC_CardMac[card_index][0] == 0) &&
+                                       (*(UINT16 *)&MC_CardMac[card_index][4] == 0))
+                               {
+                                       // MAC is all-0 so the entry is available
+                                       MC_CardUsed[card_index] = 0;
+
+                                       if (card_free_id < 0)
+                                               card_free_id = card_index; // 1st free entry
+                               }
+                               else
+                               {
+                                       if (memcmp(MC_CardMac[card_index], mac, 6) == 0)
+                                       {
+                                               // we find the entry with same MAC
+                                               if (card_same_mac_id < 0)
+                                                       card_same_mac_id = card_index; // 1st same entry
+                                       }
+                                       else
+                                       {
+                                               // MAC is not all-0 but used flag == 0
+                                               if ((MC_CardUsed[card_index] == 0) &&
+                                                       (card_nouse_id < 0))
+                                               {
+                                                       card_nouse_id = card_index; // 1st available entry
+                                               }
+                                       }
+                               }
+                       }
+
+                       DBGPRINT(RT_DEBUG_TRACE,
+                                       ("MC> Free = %d, Same = %d, NOUSE = %d\n",
+                                       card_free_id, card_same_mac_id, card_nouse_id));
+
+                       if ((card_same_mac_id >= 0) &&
+                               ((card_select_method == MC_SELECT_CARDID) ||
+                               (card_select_method == MC_SELECT_CARDTYPE)))
+                       {
+                               // same MAC entry is found
+                               card_match_id = card_same_mac_id;
+
+                               if (card_select_method == MC_SELECT_CARDTYPE)
+                               {
+                                       // for CARDTYPE
+                                       sprintf(card_id_buf, "%02dCARDTYPE%s",
+                                                       card_match_id, RFIC_word);
+
+                                       if ((start_ptr=rtstrstruncasecmp(buffer, card_id_buf)) != NULL)
+                                       {
+                                               // we found the card ID
+                                               LETTER_CASE_TRANSLATE(start_ptr, card_id_buf);
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               // the card is 1st plug-in, try to find the match card profile
+                               switch(card_select_method)
+                               {
+                                       case MC_SELECT_CARDID: // CARDID
+                                       default:
+                                               if (card_free_id >= 0)
+                                                       card_match_id = card_free_id;
+                                               else
+                                                       card_match_id = card_nouse_id;
+                                               break;
+
+                                       case MC_SELECT_MAC: // MAC
+                                               sprintf(card_id_buf, "MAC%02x:%02x:%02x:%02x:%02x:%02x",
+                                                               mac[0], mac[1], mac[2],
+                                                               mac[3], mac[4], mac[5]);
+
+                                               /* try to find the key word in the card file */
+                                               if ((start_ptr=rtstrstruncasecmp(buffer, card_id_buf)) != NULL)
+                                               {
+                                                       LETTER_CASE_TRANSLATE(start_ptr, card_id_buf);
+
+                                                       /* get the row ID (2 ASCII characters) */
+                                                       start_ptr -= 2;
+                                                       card_id_buf[0] = *(start_ptr);
+                                                       card_id_buf[1] = *(start_ptr+1);
+                                                       card_id_buf[2] = 0x00;
+
+                                                       card_match_id = simple_strtol(card_id_buf, 0, 10);
+                                               }
+                                               break;
+
+                                       case MC_SELECT_CARDTYPE: // CARDTYPE
+                                               card_nouse_id = -1;
+
+                                               for(card_index=0;
+                                                       card_index<MAX_NUM_OF_MULTIPLE_CARD;
+                                                       card_index++)
+                                               {
+                                                       sprintf(card_id_buf, "%02dCARDTYPE%s",
+                                                                       card_index, RFIC_word);
+
+                                                       if ((start_ptr=rtstrstruncasecmp(buffer,
+                                                                                                               card_id_buf)) != NULL)
+                                                       {
+                                                               LETTER_CASE_TRANSLATE(start_ptr, card_id_buf);
+
+                                                               if (MC_CardUsed[card_index] == 0)
+                                                               {
+                                                                       /* current the card profile is not used */
+                                                                       if ((*(UINT32 *)&MC_CardMac[card_index][0] == 0) &&
+                                                                               (*(UINT16 *)&MC_CardMac[card_index][4] == 0))
+                                                                       {
+                                                                               // find it and no previous card use it
+                                                                               card_match_id = card_index;
+                                                                               break;
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               // ever a card use it
+                                                                               if (card_nouse_id < 0)
+                                                                                       card_nouse_id = card_index;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+
+                                               // if not find a free one, use the available one
+                                               if (card_match_id < 0)
+                                                       card_match_id = card_nouse_id;
+                                               break;
+                               }
+                       }
+
+                       if (card_match_id >= 0)
+                       {
+                               // make up search keyword
+                               switch(card_select_method)
+                               {
+                                       case MC_SELECT_CARDID: // CARDID
+                                               sprintf(card_id_buf, "%02dCARDID", card_match_id);
+                                               break;
+
+                                       case MC_SELECT_MAC: // MAC
+                                               sprintf(card_id_buf,
+                                                               "%02dmac%02x:%02x:%02x:%02x:%02x:%02x",
+                                                               card_match_id,
+                                                               mac[0], mac[1], mac[2],
+                                                               mac[3], mac[4], mac[5]);
+                                               break;
+
+                                       case MC_SELECT_CARDTYPE: // CARDTYPE
+                                       default:
+                                               sprintf(card_id_buf, "%02dcardtype%s",
+                                                               card_match_id, RFIC_word);
+                                               break;
+                               }
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("Search Keyword = %s\n", card_id_buf));
+
+                               // read card file path
+                               if (RTMPGetKeyParameter(card_id_buf, tmpbuf, 256, buffer))
+                               {
+                                       if (strlen(tmpbuf) < sizeof(pAd->MC_FileName))
+                                       {
+                                               // backup card information
+                                               pAd->MC_RowID = card_match_id; /* base 0 */
+                                               MC_CardUsed[card_match_id] = 1;
+                                               memcpy(MC_CardMac[card_match_id], mac, sizeof(mac));
+
+                                               // backup card file path
+                                               NdisMoveMemory(pAd->MC_FileName, tmpbuf , strlen(tmpbuf));
+                                               pAd->MC_FileName[strlen(tmpbuf)] = '\0';
+                                               flg_match_ok = TRUE;
+
+                                               DBGPRINT(RT_DEBUG_TRACE,
+                                                               ("Card Profile Name = %s\n", pAd->MC_FileName));
+                                       }
+                                       else
+                                       {
+                                               DBGPRINT(RT_DEBUG_ERROR,
+                                                               ("Card Profile Name length too large!\n"));
+                                       }
+                               }
+                               else
+                               {
+                                       DBGPRINT(RT_DEBUG_ERROR,
+                                                       ("Can not find search key word in card.dat!\n"));
+                               }
+
+                               if ((flg_match_ok != TRUE) &&
+                                       (card_match_id < MAX_NUM_OF_MULTIPLE_CARD))
+                               {
+                                       MC_CardUsed[card_match_id] = 0;
+                                       memset(MC_CardMac[card_match_id], 0, sizeof(mac));
+                               }
+                       } // if (card_match_id >= 0)
+               }
+       }
+
+       // close file
+       retval = filp_close(srcf, NULL);
+       set_fs(orgfs);
+       current->fsuid = orgfsuid;
+       current->fsgid = orgfsgid;
+       kfree(buffer);
+       kfree(tmpbuf);
+       return flg_match_ok;
+}
+#endif // MULTIPLE_CARD_SUPPORT //
+
+
+/*
+========================================================================
+Routine Description:
+    Probe RT28XX chipset.
+
+Arguments:
+    _dev_p                             Point to the PCI or USB device
+       _dev_id_p                       Point to the PCI or USB device ID
+
+Return Value:
+    0                                  Probe OK
+       -ENODEV                         Probe Fail
+
+Note:
+========================================================================
+*/
+INT __devinit   rt28xx_probe(
+    IN  void *_dev_p,
+    IN  void *_dev_id_p,
+       IN  UINT argc,
+       OUT PRTMP_ADAPTER *ppAd)
+{
+    struct  net_device *net_dev;
+    PRTMP_ADAPTER       pAd = (PRTMP_ADAPTER) NULL;
+    INT                 status;
+       PVOID                           handle;
+#ifdef RT2870
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
+       struct usb_device *dev_p = (struct usb_device *)_dev_p;
+#else
+       struct usb_interface *intf = (struct usb_interface *)_dev_p;
+       struct usb_device *dev_p = interface_to_usbdev(intf);
+
+       dev_p = usb_get_dev(dev_p);
+#endif // LINUX_VERSION_CODE //
+#endif // RT2870 //
+
+
+#ifdef CONFIG_STA_SUPPORT
+    DBGPRINT(RT_DEBUG_TRACE, ("STA Driver version-%s\n", STA_DRIVER_VERSION));
+#endif // CONFIG_STA_SUPPORT //
+
+       // Check chipset vendor/product ID
+//     if (RT28XXChipsetCheck(_dev_p) == FALSE)
+//             goto err_out;
+
+#if LINUX_VERSION_CODE <= 0x20402       // Red Hat 7.1
+    net_dev = alloc_netdev(sizeof(PRTMP_ADAPTER), "eth%d", ether_setup);
+#else
+    net_dev = alloc_etherdev(sizeof(PRTMP_ADAPTER));
+#endif
+    if (net_dev == NULL)
+    {
+        printk("alloc_netdev failed\n");
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+               module_put(THIS_MODULE);
+#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+#else
+               MOD_DEC_USE_COUNT;
+#endif
+        goto err_out;
+    }
+
+// sample
+//     if (rt_ieee80211_if_setup(net_dev) != NDIS_STATUS_SUCCESS)
+//             goto err_out;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    SET_MODULE_OWNER(net_dev);
+#endif
+
+       netif_stop_queue(net_dev);
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+/* for supporting Network Manager */
+/* Set the sysfs physical device reference for the network logical device
+ * if set prior to registration will cause a symlink during initialization.
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+    SET_NETDEV_DEV(net_dev, &(dev_p->dev));
+#endif
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+       // Allocate RTMP_ADAPTER miniport adapter structure
+       handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL);
+       RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p);
+
+       status = RTMPAllocAdapterBlock(handle, &pAd);
+       if (status != NDIS_STATUS_SUCCESS)
+               goto err_out_free_netdev;
+
+       net_dev->priv = (PVOID)pAd;
+    pAd->net_dev = net_dev; // must be before RT28XXNetDevInit()
+
+       RT28XXNetDevInit(_dev_p, net_dev, pAd);
+
+#ifdef CONFIG_STA_SUPPORT
+    pAd->StaCfg.OriDevType = net_dev->type;
+#endif // CONFIG_STA_SUPPORT //
+
+       // Find and assign a free interface name, raxx
+//     RT28XXAvailRANameAssign(net_dev->name);
+
+       // Post config
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+       if (RT28XXProbePostConfig(_dev_p, pAd, argc) == FALSE)
+               goto err_out_unmap;
+#else
+       if (RT28XXProbePostConfig(_dev_p, pAd, 0) == FALSE)
+               goto err_out_unmap;
+#endif // LINUX_VERSION_CODE //
+
+#ifdef CONFIG_STA_SUPPORT
+       pAd->OpMode = OPMODE_STA;
+#endif // CONFIG_STA_SUPPORT //
+
+
+#ifdef MULTIPLE_CARD_SUPPORT
+       // find its profile path
+       pAd->MC_RowID = -1; // use default profile path
+       RTMP_CardInfoRead(pAd);
+
+       if (pAd->MC_RowID == -1)
+#ifdef CONFIG_STA_SUPPORT
+               strcpy(pAd->MC_FileName, STA_PROFILE_PATH);
+#endif // CONFIG_STA_SUPPORT //
+
+       DBGPRINT(RT_DEBUG_TRACE,
+                       ("MC> ROW = %d, PATH = %s\n", pAd->MC_RowID, pAd->MC_FileName));
+#endif // MULTIPLE_CARD_SUPPORT //
+
+       // sample move
+       if (rt_ieee80211_if_setup(net_dev, pAd) != NDIS_STATUS_SUCCESS)
+               goto err_out_unmap;
+
+    // Register this device
+    status = register_netdev(net_dev);
+    if (status)
+        goto err_out_unmap;
+
+    // Set driver data
+       RT28XX_DRVDATA_SET(_dev_p);
+
+
+
+       *ppAd = pAd;
+    return 0; // probe ok
+
+
+       /* --------------------------- ERROR HANDLE --------------------------- */
+err_out_unmap:
+       RTMPFreeAdapter(pAd);
+       RT28XX_UNMAP();
+
+err_out_free_netdev:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+    free_netdev(net_dev);
+#else
+       kfree(net_dev);
+#endif
+
+err_out:
+       RT28XX_PUT_DEVICE(dev_p);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+       return (LONG)NULL;
+#else
+    return -ENODEV; /* probe fail */
+#endif // LINUX_VERSION_CODE //
+} /* End of rt28xx_probe */
+
+
+/*
+========================================================================
+Routine Description:
+    The entry point for Linux kernel sent packet to our driver.
+
+Arguments:
+    sk_buff *skb               the pointer refer to a sk_buffer.
+
+Return Value:
+    0
+
+Note:
+       This function is the entry point of Tx Path for Os delivery packet to
+       our driver. You only can put OS-depened & STA/AP common handle procedures
+       in here.
+========================================================================
+*/
+int rt28xx_packet_xmit(struct sk_buff *skb)
+{
+       struct net_device *net_dev = skb->dev;
+       PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) net_dev->priv;
+       int status = 0;
+       PNDIS_PACKET pPacket = (PNDIS_PACKET) skb;
+
+       /* RT2870STA does this in RTMPSendPackets() */
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+       {
+               RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_RESOURCES);
+               return 0;
+       }
+#endif // RALINK_ATE //
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               // Drop send request since we are in monitor mode
+               if (MONITOR_ON(pAd))
+               {
+                       RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+                       goto done;
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+        // EapolStart size is 18
+       if (skb->len < 14)
+       {
+               //printk("bad packet size: %d\n", pkt->len);
+               hex_dump("bad packet", skb->data, skb->len);
+               RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+               goto done;
+       }
+
+#if 0
+//     if ((pkt->data[0] & 0x1) == 0)
+       {
+               //hex_dump(__FUNCTION__, pkt->data, pkt->len);
+               printk("pPacket = %x\n", pPacket);
+       }
+#endif
+
+       RTMP_SET_PACKET_5VT(pPacket, 0);
+//     MiniportMMRequest(pAd, pkt->data, pkt->len);
+#ifdef CONFIG_5VT_ENHANCE
+    if (*(int*)(skb->cb) == BRIDGE_TAG) {
+               RTMP_SET_PACKET_5VT(pPacket, 1);
+    }
+#endif
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+
+               STASendPackets((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1);
+       }
+
+#endif // CONFIG_STA_SUPPORT //
+
+       status = 0;
+done:
+
+       return status;
+}
+
+
+/*
+========================================================================
+Routine Description:
+    Send a packet to WLAN.
+
+Arguments:
+    skb_p           points to our adapter
+    dev_p           which WLAN network interface
+
+Return Value:
+    0: transmit successfully
+    otherwise: transmit fail
+
+Note:
+========================================================================
+*/
+INT rt28xx_send_packets(
+       IN struct sk_buff               *skb_p,
+       IN struct net_device    *net_dev)
+{
+    RTMP_ADAPTER *pAd = net_dev->priv;
+
+       if (!(net_dev->flags & IFF_UP))
+       {
+               RELEASE_NDIS_PACKET(pAd, (PNDIS_PACKET)skb_p, NDIS_STATUS_FAILURE);
+               return 0;
+       }
+
+       NdisZeroMemory((PUCHAR)&skb_p->cb[CB_OFF], 15);
+       RTMP_SET_PACKET_NET_DEVICE_MBSSID(skb_p, MAIN_MBSSID);
+
+       return rt28xx_packet_xmit(skb_p);
+} /* End of MBSS_VirtualIF_PacketSend */
+
+
+
+
+#if LINUX_VERSION_CODE <= 0x20402      // Red Hat 7.1
+//static struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *)) //sample
+struct net_device *alloc_netdev(
+       int sizeof_priv,
+       const char *mask,
+       void (*setup)(struct net_device *))
+{
+    struct net_device  *dev;
+    INT                                        alloc_size;
+
+
+    /* ensure 32-byte alignment of the private area */
+    alloc_size = sizeof (*dev) + sizeof_priv + 31;
+
+    dev = (struct net_device *) kmalloc(alloc_size, GFP_KERNEL);
+    if (dev == NULL)
+    {
+        DBGPRINT(RT_DEBUG_ERROR,
+                               ("alloc_netdev: Unable to allocate device memory.\n"));
+        return NULL;
+    }
+
+    memset(dev, 0, alloc_size);
+
+    if (sizeof_priv)
+        dev->priv = (void *) (((long)(dev + 1) + 31) & ~31);
+
+    setup(dev);
+    strcpy(dev->name, mask);
+
+    return dev;
+}
+#endif // LINUX_VERSION_CODE //
+
+
+void CfgInitHook(PRTMP_ADAPTER pAd)
+{
+       pAd->bBroadComHT = TRUE;
+} /* End of CfgInitHook */
+
+
+#if 0  // Not used now, should keep it in our source tree??
+/*
+========================================================================
+Routine Description:
+    Find and assign a free interface name (raxx).
+
+Arguments:
+    *name_p                            the interface name pointer
+
+Return Value:
+       TRUE                            OK
+       FALSE                           FAIL
+
+Note:
+========================================================================
+*/
+static BOOLEAN RT28XXAvailRANameAssign(
+       IN CHAR                 *name_p)
+{
+    CHAR                               slot_name[IFNAMSIZ];
+    struct net_device  *device;
+       UINT32                          if_id;
+
+
+    for(if_id=0; if_id<8; if_id++)
+    {
+        sprintf(slot_name, "ra%d", if_id);
+
+        for(device=dev_base; device!=NULL; device=device->next)
+        {
+            if (strncmp(device->name, slot_name, 4) == 0)
+                break;
+        }
+
+        if (device == NULL)
+                       break;
+    }
+
+    if (if_id == 8)
+    {
+        DBGPRINT(RT_DEBUG_ERROR, ("No available slot name\n"));
+        return FALSE;
+    }
+
+    sprintf(name_p, "ra%d", if_id);
+       return TRUE;
+} /* End of RT28XXAvailRANameAssign */
+#endif
+
+#if WIRELESS_EXT >= 12
+// This function will be called when query /proc
+struct iw_statistics *rt28xx_get_wireless_stats(
+    IN struct net_device *net_dev)
+{
+       PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) net_dev->priv;
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_get_wireless_stats --->\n"));
+
+       pAd->iw_stats.status = 0; // Status - device dependent for now
+
+       // link quality
+       pAd->iw_stats.qual.qual = ((pAd->Mlme.ChannelQuality * 12)/10 + 10);
+       if(pAd->iw_stats.qual.qual > 100)
+               pAd->iw_stats.qual.qual = 100;
+
+#ifdef CONFIG_STA_SUPPORT
+       if (pAd->OpMode == OPMODE_STA)
+               pAd->iw_stats.qual.level = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
+#endif // CONFIG_STA_SUPPORT //
+
+       pAd->iw_stats.qual.noise = pAd->BbpWriteLatch[66]; // noise level (dBm)
+
+       pAd->iw_stats.qual.noise += 256 - 143;
+       pAd->iw_stats.qual.updated = 1;     // Flags to know if updated
+#ifdef IW_QUAL_DBM
+       pAd->iw_stats.qual.updated |= IW_QUAL_DBM;      // Level + Noise are dBm
+#endif // IW_QUAL_DBM //
+
+       pAd->iw_stats.discard.nwid = 0;     // Rx : Wrong nwid/essid
+       pAd->iw_stats.miss.beacon = 0;      // Missed beacons/superframe
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<--- rt28xx_get_wireless_stats\n"));
+       return &pAd->iw_stats;
+} /* End of rt28xx_get_wireless_stats */
+#endif // WIRELESS_EXT //
+
+
+
+void tbtt_tasklet(unsigned long data)
+{
+#define MAX_TX_IN_TBTT         (16)
+
+}
+
+INT rt28xx_ioctl(
+       IN      struct net_device       *net_dev,
+       IN      OUT     struct ifreq    *rq,
+       IN      INT                                     cmd)
+{
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+       RTMP_ADAPTER    *pAd = NULL;
+       INT                             ret = 0;
+
+       if (net_dev->priv_flags == INT_MAIN)
+       {
+               pAd = net_dev->priv;
+       }
+       else
+       {
+               pVirtualAd = net_dev->priv;
+               pAd = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAd == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+       {
+               ret = rt28xx_sta_ioctl(net_dev, rq, cmd);
+       }
+#endif // CONFIG_STA_SUPPORT //
+
+       return ret;
+}
+
+/*
+    ========================================================================
+
+    Routine Description:
+        return ethernet statistics counter
+
+    Arguments:
+        net_dev                     Pointer to net_device
+
+    Return Value:
+        net_device_stats*
+
+    Note:
+
+    ========================================================================
+*/
+struct net_device_stats *RT28xx_get_ether_stats(
+    IN  struct net_device *net_dev)
+{
+    RTMP_ADAPTER *pAd = NULL;
+
+       if (net_dev)
+               pAd = net_dev->priv;
+
+       if (pAd)
+       {
+
+               pAd->stats.rx_packets = pAd->WlanCounters.ReceivedFragmentCount.QuadPart;
+               pAd->stats.tx_packets = pAd->WlanCounters.TransmittedFragmentCount.QuadPart;
+
+               pAd->stats.rx_bytes = pAd->RalinkCounters.ReceivedByteCount;
+               pAd->stats.tx_bytes = pAd->RalinkCounters.TransmittedByteCount;
+
+               pAd->stats.rx_errors = pAd->Counters8023.RxErrors;
+               pAd->stats.tx_errors = pAd->Counters8023.TxErrors;
+
+               pAd->stats.rx_dropped = 0;
+               pAd->stats.tx_dropped = 0;
+
+           pAd->stats.multicast = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart;   // multicast packets received
+           pAd->stats.collisions = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions;  // Collision packets
+
+           pAd->stats.rx_length_errors = 0;
+           pAd->stats.rx_over_errors = pAd->Counters8023.RxNoBuffer;                   // receiver ring buff overflow
+           pAd->stats.rx_crc_errors = 0;//pAd->WlanCounters.FCSErrorCount;     // recved pkt with crc error
+           pAd->stats.rx_frame_errors = pAd->Counters8023.RcvAlignmentErrors;          // recv'd frame alignment error
+           pAd->stats.rx_fifo_errors = pAd->Counters8023.RxNoBuffer;                   // recv'r fifo overrun
+           pAd->stats.rx_missed_errors = 0;                                            // receiver missed packet
+
+           // detailed tx_errors
+           pAd->stats.tx_aborted_errors = 0;
+           pAd->stats.tx_carrier_errors = 0;
+           pAd->stats.tx_fifo_errors = 0;
+           pAd->stats.tx_heartbeat_errors = 0;
+           pAd->stats.tx_window_errors = 0;
+
+           // for cslip etc
+           pAd->stats.rx_compressed = 0;
+           pAd->stats.tx_compressed = 0;
+
+               return &pAd->stats;
+       }
+       else
+       return NULL;
+}
+
diff --git a/drivers/staging/rt2870/rt_profile.c b/drivers/staging/rt2870/rt_profile.c
new file mode 100644 (file)
index 0000000..3e360c6
--- /dev/null
@@ -0,0 +1,2016 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#include "rt_config.h"
+
+#ifdef DOT11_N_SUPPORT
+static void HTParametersHook(
+       IN      PRTMP_ADAPTER pAd,
+       IN      CHAR              *pValueStr,
+       IN      CHAR              *pInput);
+#endif // DOT11_N_SUPPORT //
+
+#define ETH_MAC_ADDR_STR_LEN 17  // in format of xx:xx:xx:xx:xx:xx
+
+// We assume the s1 is a sting, s2 is a memory space with 6 bytes. and content of s1 will be changed.
+BOOLEAN rtstrmactohex(char *s1, char *s2)
+{
+       int i = 0;
+       char *ptokS = s1, *ptokE = s1;
+
+       if (strlen(s1) != ETH_MAC_ADDR_STR_LEN)
+               return FALSE;
+
+       while((*ptokS) != '\0')
+       {
+               if((ptokE = strchr(ptokS, ':')) != NULL)
+                       *ptokE++ = '\0';
+               if ((strlen(ptokS) != 2) || (!isxdigit(*ptokS)) || (!isxdigit(*(ptokS+1))))
+                       break; // fail
+               AtoH(ptokS, &s2[i++], 1);
+               ptokS = ptokE;
+               if (i == 6)
+                       break; // parsing finished
+       }
+
+       return ( i == 6 ? TRUE : FALSE);
+
+}
+
+
+// we assume the s1 and s2 both are strings.
+BOOLEAN rtstrcasecmp(char *s1, char *s2)
+{
+       char *p1 = s1, *p2 = s2;
+
+       if (strlen(s1) != strlen(s2))
+               return FALSE;
+
+       while(*p1 != '\0')
+       {
+               if((*p1 != *p2) && ((*p1 ^ *p2) != 0x20))
+                       return FALSE;
+               p1++;
+               p2++;
+       }
+
+       return TRUE;
+}
+
+// we assume the s1 (buffer) and s2 (key) both are strings.
+char * rtstrstruncasecmp(char * s1, char * s2)
+{
+       INT l1, l2, i;
+       char temp1, temp2;
+
+       l2 = strlen(s2);
+       if (!l2)
+               return (char *) s1;
+
+       l1 = strlen(s1);
+
+       while (l1 >= l2)
+       {
+               l1--;
+
+               for(i=0; i<l2; i++)
+               {
+                       temp1 = *(s1+i);
+                       temp2 = *(s2+i);
+
+                       if (('a' <= temp1) && (temp1 <= 'z'))
+                               temp1 = 'A'+(temp1-'a');
+                       if (('a' <= temp2) && (temp2 <= 'z'))
+                               temp2 = 'A'+(temp2-'a');
+
+                       if (temp1 != temp2)
+                               break;
+               }
+
+               if (i == l2)
+                       return (char *) s1;
+
+               s1++;
+       }
+
+       return NULL; // not found
+}
+
+//add by kathy
+
+ /**
+  * strstr - Find the first substring in a %NUL terminated string
+  * @s1: The string to be searched
+  * @s2: The string to search for
+  */
+char * rtstrstr(const char * s1,const char * s2)
+{
+       INT l1, l2;
+
+       l2 = strlen(s2);
+       if (!l2)
+               return (char *) s1;
+
+       l1 = strlen(s1);
+
+       while (l1 >= l2)
+       {
+               l1--;
+               if (!memcmp(s1,s2,l2))
+                       return (char *) s1;
+               s1++;
+       }
+
+       return NULL;
+}
+
+/**
+ * rstrtok - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ * * WARNING: strtok is deprecated, use strsep instead. However strsep is not compatible with old architecture.
+ */
+char * __rstrtok;
+char * rstrtok(char * s,const char * ct)
+{
+       char *sbegin, *send;
+
+       sbegin  = s ? s : __rstrtok;
+       if (!sbegin)
+       {
+               return NULL;
+       }
+
+       sbegin += strspn(sbegin,ct);
+       if (*sbegin == '\0')
+       {
+               __rstrtok = NULL;
+               return( NULL );
+       }
+
+       send = strpbrk( sbegin, ct);
+       if (send && *send != '\0')
+               *send++ = '\0';
+
+       __rstrtok = send;
+
+       return (sbegin);
+}
+
+/**
+ * delimitcnt - return the count of a given delimiter in a given string.
+ * @s: The string to be searched.
+ * @ct: The delimiter to search for.
+ * Notice : We suppose the delimiter is a single-char string(for example : ";").
+ */
+INT delimitcnt(char * s,const char * ct)
+{
+       INT count = 0;
+       /* point to the beginning of the line */
+       const char *token = s;
+
+       for ( ;; )
+       {
+               token = strpbrk(token, ct); /* search for delimiters */
+
+        if ( token == NULL )
+               {
+                       /* advanced to the terminating null character */
+                       break;
+               }
+               /* skip the delimiter */
+           ++token;
+
+               /*
+                * Print the found text: use len with %.*s to specify field width.
+                */
+
+               /* accumulate delimiter count */
+           ++count;
+       }
+    return count;
+}
+
+/*
+  * converts the Internet host address from the standard numbers-and-dots notation
+  * into binary data.
+  * returns nonzero if the address is valid, zero if not.
+  */
+int rtinet_aton(const char *cp, unsigned int *addr)
+{
+       unsigned int    val;
+       int             base, n;
+       char            c;
+       unsigned int    parts[4];
+       unsigned int    *pp = parts;
+
+       for (;;)
+    {
+         /*
+          * Collect number up to ``.''.
+          * Values are specified as for C:
+          *    0x=hex, 0=octal, other=decimal.
+          */
+         val = 0;
+         base = 10;
+         if (*cp == '0')
+         {
+             if (*++cp == 'x' || *cp == 'X')
+                 base = 16, cp++;
+             else
+                 base = 8;
+         }
+         while ((c = *cp) != '\0')
+         {
+             if (isdigit((unsigned char) c))
+             {
+                 val = (val * base) + (c - '0');
+                 cp++;
+                 continue;
+             }
+             if (base == 16 && isxdigit((unsigned char) c))
+             {
+                 val = (val << 4) +
+                     (c + 10 - (islower((unsigned char) c) ? 'a' : 'A'));
+                 cp++;
+                 continue;
+             }
+             break;
+         }
+         if (*cp == '.')
+         {
+             /*
+              * Internet format: a.b.c.d a.b.c   (with c treated as 16-bits)
+              * a.b     (with b treated as 24 bits)
+              */
+             if (pp >= parts + 3 || val > 0xff)
+                 return 0;
+             *pp++ = val, cp++;
+         }
+         else
+             break;
+     }
+
+     /*
+      * Check for trailing junk.
+      */
+     while (*cp)
+         if (!isspace((unsigned char) *cp++))
+             return 0;
+
+     /*
+      * Concoct the address according to the number of parts specified.
+      */
+     n = pp - parts + 1;
+     switch (n)
+     {
+
+         case 1:         /* a -- 32 bits */
+             break;
+
+         case 2:         /* a.b -- 8.24 bits */
+             if (val > 0xffffff)
+                 return 0;
+             val |= parts[0] << 24;
+             break;
+
+         case 3:         /* a.b.c -- 8.8.16 bits */
+             if (val > 0xffff)
+                 return 0;
+             val |= (parts[0] << 24) | (parts[1] << 16);
+             break;
+
+         case 4:         /* a.b.c.d -- 8.8.8.8 bits */
+             if (val > 0xff)
+                 return 0;
+             val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+             break;
+     }
+
+     *addr = htonl(val);
+     return 1;
+
+}
+
+/*
+    ========================================================================
+
+    Routine Description:
+        Find key section for Get key parameter.
+
+    Arguments:
+        buffer                      Pointer to the buffer to start find the key section
+        section                     the key of the secion to be find
+
+    Return Value:
+        NULL                        Fail
+        Others                      Success
+    ========================================================================
+*/
+PUCHAR  RTMPFindSection(
+    IN  PCHAR   buffer)
+{
+    CHAR temp_buf[32];
+    PUCHAR  ptr;
+
+    strcpy(temp_buf, "Default");
+
+    if((ptr = rtstrstr(buffer, temp_buf)) != NULL)
+            return (ptr+strlen("\n"));
+        else
+            return NULL;
+}
+
+/*
+    ========================================================================
+
+    Routine Description:
+        Get key parameter.
+
+    Arguments:
+        key                         Pointer to key string
+        dest                        Pointer to destination
+        destsize                    The datasize of the destination
+        buffer                      Pointer to the buffer to start find the key
+
+    Return Value:
+        TRUE                        Success
+        FALSE                       Fail
+
+    Note:
+        This routine get the value with the matched key (case case-sensitive)
+    ========================================================================
+*/
+INT RTMPGetKeyParameter(
+    IN  PCHAR   key,
+    OUT PCHAR   dest,
+    IN  INT     destsize,
+    IN  PCHAR   buffer)
+{
+    UCHAR *temp_buf1 = NULL;
+    UCHAR *temp_buf2 = NULL;
+    CHAR *start_ptr;
+    CHAR *end_ptr;
+    CHAR *ptr;
+    CHAR *offset = 0;
+    INT  len;
+
+       //temp_buf1 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+       os_alloc_mem(NULL, &temp_buf1, MAX_PARAM_BUFFER_SIZE);
+
+       if(temp_buf1 == NULL)
+        return (FALSE);
+
+       //temp_buf2 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+       os_alloc_mem(NULL, &temp_buf2, MAX_PARAM_BUFFER_SIZE);
+       if(temp_buf2 == NULL)
+       {
+               os_free_mem(NULL, temp_buf1);
+        return (FALSE);
+       }
+
+    //find section
+    if((offset = RTMPFindSection(buffer)) == NULL)
+    {
+       os_free_mem(NULL, temp_buf1);
+       os_free_mem(NULL, temp_buf2);
+        return (FALSE);
+    }
+
+    strcpy(temp_buf1, "\n");
+    strcat(temp_buf1, key);
+    strcat(temp_buf1, "=");
+
+    //search key
+    if((start_ptr=rtstrstr(offset, temp_buf1))==NULL)
+    {
+               os_free_mem(NULL, temp_buf1);
+       os_free_mem(NULL, temp_buf2);
+        return (FALSE);
+    }
+
+    start_ptr+=strlen("\n");
+    if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL)
+       end_ptr=start_ptr+strlen(start_ptr);
+
+    if (end_ptr<start_ptr)
+    {
+               os_free_mem(NULL, temp_buf1);
+       os_free_mem(NULL, temp_buf2);
+        return (FALSE);
+    }
+
+    NdisMoveMemory(temp_buf2, start_ptr, end_ptr-start_ptr);
+    temp_buf2[end_ptr-start_ptr]='\0';
+    len = strlen(temp_buf2);
+    strcpy(temp_buf1, temp_buf2);
+    if((start_ptr=rtstrstr(temp_buf1, "=")) == NULL)
+    {
+               os_free_mem(NULL, temp_buf1);
+       os_free_mem(NULL, temp_buf2);
+        return (FALSE);
+    }
+
+    strcpy(temp_buf2, start_ptr+1);
+    ptr = temp_buf2;
+    //trim space or tab
+    while(*ptr != 0x00)
+    {
+        if( (*ptr == ' ') || (*ptr == '\t') )
+            ptr++;
+        else
+           break;
+    }
+
+    len = strlen(ptr);
+    memset(dest, 0x00, destsize);
+    strncpy(dest, ptr, len >= destsize ?  destsize: len);
+
+       os_free_mem(NULL, temp_buf1);
+    os_free_mem(NULL, temp_buf2);
+    return TRUE;
+}
+
+/*
+    ========================================================================
+
+    Routine Description:
+        Get key parameter.
+
+    Arguments:
+        key                         Pointer to key string
+        dest                        Pointer to destination
+        destsize                    The datasize of the destination
+        buffer                      Pointer to the buffer to start find the key
+
+    Return Value:
+        TRUE                        Success
+        FALSE                       Fail
+
+    Note:
+        This routine get the value with the matched key (case case-sensitive).
+        It is called for parsing SSID and any key string.
+    ========================================================================
+*/
+INT RTMPGetCriticalParameter(
+    IN  PCHAR   key,
+    OUT PCHAR   dest,
+    IN  INT     destsize,
+    IN  PCHAR   buffer)
+{
+    UCHAR *temp_buf1 = NULL;
+    UCHAR *temp_buf2 = NULL;
+    CHAR *start_ptr;
+    CHAR *end_ptr;
+    CHAR *ptr;
+    CHAR *offset = 0;
+    INT  len;
+
+       //temp_buf1 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+       os_alloc_mem(NULL, &temp_buf1, MAX_PARAM_BUFFER_SIZE);
+
+       if(temp_buf1 == NULL)
+        return (FALSE);
+
+       //temp_buf2 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+       os_alloc_mem(NULL, &temp_buf2, MAX_PARAM_BUFFER_SIZE);
+       if(temp_buf2 == NULL)
+       {
+               os_free_mem(NULL, temp_buf1);
+        return (FALSE);
+       }
+
+    //find section
+    if((offset = RTMPFindSection(buffer)) == NULL)
+    {
+       os_free_mem(NULL, temp_buf1);
+       os_free_mem(NULL, temp_buf2);
+        return (FALSE);
+    }
+
+    strcpy(temp_buf1, "\n");
+    strcat(temp_buf1, key);
+    strcat(temp_buf1, "=");
+
+    //search key
+    if((start_ptr=rtstrstr(offset, temp_buf1))==NULL)
+    {
+               os_free_mem(NULL, temp_buf1);
+       os_free_mem(NULL, temp_buf2);
+        return (FALSE);
+    }
+
+    start_ptr+=strlen("\n");
+    if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL)
+       end_ptr=start_ptr+strlen(start_ptr);
+
+    if (end_ptr<start_ptr)
+    {
+               os_free_mem(NULL, temp_buf1);
+       os_free_mem(NULL, temp_buf2);
+        return (FALSE);
+    }
+
+    NdisMoveMemory(temp_buf2, start_ptr, end_ptr-start_ptr);
+    temp_buf2[end_ptr-start_ptr]='\0';
+    len = strlen(temp_buf2);
+    strcpy(temp_buf1, temp_buf2);
+    if((start_ptr=rtstrstr(temp_buf1, "=")) == NULL)
+    {
+               os_free_mem(NULL, temp_buf1);
+       os_free_mem(NULL, temp_buf2);
+        return (FALSE);
+    }
+
+    strcpy(temp_buf2, start_ptr+1);
+    ptr = temp_buf2;
+
+    //trim tab
+    /* We cannot trim space(' ') for SSID and key string. */
+    while(*ptr != 0x00)
+    {
+        //if( (*ptr == ' ') || (*ptr == '\t') )
+        if( (*ptr == '\t') )
+            ptr++;
+        else
+           break;
+    }
+
+    len = strlen(ptr);
+    memset(dest, 0x00, destsize);
+    strncpy(dest, ptr, len >= destsize ?  destsize: len);
+
+       os_free_mem(NULL, temp_buf1);
+    os_free_mem(NULL, temp_buf2);
+    return TRUE;
+}
+
+/*
+    ========================================================================
+
+    Routine Description:
+        Get multiple key parameter.
+
+    Arguments:
+        key                         Pointer to key string
+        dest                        Pointer to destination
+        destsize                    The datasize of the destination
+        buffer                      Pointer to the buffer to start find the key
+
+    Return Value:
+        TRUE                        Success
+        FALSE                       Fail
+
+    Note:
+        This routine get the value with the matched key (case case-sensitive)
+    ========================================================================
+*/
+INT RTMPGetKeyParameterWithOffset(
+    IN  PCHAR   key,
+    OUT PCHAR   dest,
+    OUT        USHORT  *end_offset,
+    IN  INT     destsize,
+    IN  PCHAR   buffer,
+    IN BOOLEAN bTrimSpace)
+{
+    UCHAR *temp_buf1 = NULL;
+    UCHAR *temp_buf2 = NULL;
+    CHAR *start_ptr;
+    CHAR *end_ptr;
+    CHAR *ptr;
+    CHAR *offset = 0;
+    INT  len;
+
+       if (*end_offset >= MAX_INI_BUFFER_SIZE)
+               return (FALSE);
+
+       os_alloc_mem(NULL, &temp_buf1, MAX_PARAM_BUFFER_SIZE);
+
+       if(temp_buf1 == NULL)
+        return (FALSE);
+
+       os_alloc_mem(NULL, &temp_buf2, MAX_PARAM_BUFFER_SIZE);
+       if(temp_buf2 == NULL)
+       {
+               os_free_mem(NULL, temp_buf1);
+        return (FALSE);
+       }
+
+    //find section
+       if(*end_offset == 0)
+    {
+               if ((offset = RTMPFindSection(buffer)) == NULL)
+               {
+                       os_free_mem(NULL, temp_buf1);
+               os_free_mem(NULL, temp_buf2);
+           return (FALSE);
+               }
+    }
+       else
+               offset = buffer + (*end_offset);
+
+    strcpy(temp_buf1, "\n");
+    strcat(temp_buf1, key);
+    strcat(temp_buf1, "=");
+
+    //search key
+    if((start_ptr=rtstrstr(offset, temp_buf1))==NULL)
+    {
+               os_free_mem(NULL, temp_buf1);
+       os_free_mem(NULL, temp_buf2);
+        return (FALSE);
+    }
+
+    start_ptr+=strlen("\n");
+    if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL)
+       end_ptr=start_ptr+strlen(start_ptr);
+
+    if (end_ptr<start_ptr)
+    {
+               os_free_mem(NULL, temp_buf1);
+       os_free_mem(NULL, temp_buf2);
+        return (FALSE);
+    }
+
+       *end_offset = end_ptr - buffer;
+
+    NdisMoveMemory(temp_buf2, start_ptr, end_ptr-start_ptr);
+    temp_buf2[end_ptr-start_ptr]='\0';
+    len = strlen(temp_buf2);
+    strcpy(temp_buf1, temp_buf2);
+    if((start_ptr=rtstrstr(temp_buf1, "=")) == NULL)
+    {
+               os_free_mem(NULL, temp_buf1);
+       os_free_mem(NULL, temp_buf2);
+        return (FALSE);
+    }
+
+    strcpy(temp_buf2, start_ptr+1);
+    ptr = temp_buf2;
+    //trim space or tab
+    while(*ptr != 0x00)
+    {
+        if((bTrimSpace && (*ptr == ' ')) || (*ptr == '\t') )
+            ptr++;
+        else
+           break;
+    }
+
+    len = strlen(ptr);
+    memset(dest, 0x00, destsize);
+    strncpy(dest, ptr, len >= destsize ?  destsize: len);
+
+       os_free_mem(NULL, temp_buf1);
+    os_free_mem(NULL, temp_buf2);
+    return TRUE;
+}
+
+
+static int rtmp_parse_key_buffer_from_file(IN  PRTMP_ADAPTER pAd,IN  char *buffer,IN  ULONG KeyType,IN  INT BSSIdx,IN  INT KeyIdx)
+{
+       PUCHAR          keybuff;
+       INT                     i = BSSIdx, idx = KeyIdx;
+       ULONG           KeyLen;
+       UCHAR           CipherAlg = CIPHER_WEP64;
+
+       keybuff = buffer;
+       KeyLen = strlen(keybuff);
+
+       if (KeyType == 1)
+       {//Ascii
+               if( (KeyLen == 5) || (KeyLen == 13))
+               {
+                       pAd->SharedKey[i][idx].KeyLen = KeyLen;
+                       NdisMoveMemory(pAd->SharedKey[i][idx].Key, keybuff, KeyLen);
+                       if (KeyLen == 5)
+                               CipherAlg = CIPHER_WEP64;
+                       else
+                               CipherAlg = CIPHER_WEP128;
+                       pAd->SharedKey[i][idx].CipherAlg = CipherAlg;
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Key%dStr=%s and type=%s\n", i, idx+1, keybuff, (KeyType == 0) ? "Hex":"Ascii"));
+                       return 1;
+               }
+               else
+               {//Invalid key length
+                       DBGPRINT(RT_DEBUG_ERROR, ("Key%dStr is Invalid key length! KeyLen = %ld!\n", idx+1, KeyLen));
+                       return 0;
+               }
+       }
+       else
+       {//Hex type
+               if( (KeyLen == 10) || (KeyLen == 26))
+               {
+                       pAd->SharedKey[i][idx].KeyLen = KeyLen / 2;
+                       AtoH(keybuff, pAd->SharedKey[i][idx].Key, KeyLen / 2);
+                       if (KeyLen == 10)
+                               CipherAlg = CIPHER_WEP64;
+                       else
+                               CipherAlg = CIPHER_WEP128;
+                       pAd->SharedKey[i][idx].CipherAlg = CipherAlg;
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Key%dStr=%s and type=%s\n", i, idx+1, keybuff, (KeyType == 0) ? "Hex":"Ascii"));
+                       return 1;
+               }
+               else
+               {//Invalid key length
+                       DBGPRINT(RT_DEBUG_ERROR, ("I/F(ra%d) Key%dStr is Invalid key length! KeyLen = %ld!\n", i, idx+1, KeyLen));
+                       return 0;
+               }
+       }
+}
+static void rtmp_read_key_parms_from_file(IN  PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer)
+{
+       char            tok_str[16];
+       PUCHAR          macptr;
+       INT                     i = 0, idx;
+       ULONG           KeyType[MAX_MBSSID_NUM];
+       ULONG           KeyIdx;
+
+       NdisZeroMemory(KeyType, MAX_MBSSID_NUM);
+
+       //DefaultKeyID
+       if(RTMPGetKeyParameter("DefaultKeyID", tmpbuf, 25, buffer))
+       {
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       KeyIdx = simple_strtol(tmpbuf, 0, 10);
+                       if((KeyIdx >= 1 ) && (KeyIdx <= 4))
+                               pAd->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1);
+                       else
+                               pAd->StaCfg.DefaultKeyId = 0;
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyID(0~3)=%d\n", pAd->StaCfg.DefaultKeyId));
+               }
+#endif // CONFIG_STA_SUPPORT //
+       }
+
+
+       for (idx = 0; idx < 4; idx++)
+       {
+               sprintf(tok_str, "Key%dType", idx + 1);
+               //Key1Type
+               if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer))
+               {
+                   for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+                   {
+                           KeyType[i] = simple_strtol(macptr, 0, 10);
+                   }
+
+#ifdef CONFIG_STA_SUPPORT
+                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                       {
+                               sprintf(tok_str, "Key%dStr", idx + 1);
+                               if (RTMPGetCriticalParameter(tok_str, tmpbuf, 128, buffer))
+                               {
+                                       rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[BSS0], BSS0, idx);
+                               }
+                       }
+#endif // CONFIG_STA_SUPPORT //
+               }
+       }
+}
+
+
+#ifdef CONFIG_STA_SUPPORT
+static void rtmp_read_sta_wmm_parms_from_file(IN  PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer)
+{
+       PUCHAR                                  macptr;
+       INT                                             i=0;
+       BOOLEAN                                 bWmmEnable = FALSE;
+
+       //WmmCapable
+       if(RTMPGetKeyParameter("WmmCapable", tmpbuf, 32, buffer))
+       {
+               if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable
+               {
+                       pAd->CommonCfg.bWmmCapable = TRUE;
+                       bWmmEnable = TRUE;
+               }
+               else //Disable
+               {
+                       pAd->CommonCfg.bWmmCapable = FALSE;
+               }
+
+               DBGPRINT(RT_DEBUG_TRACE, ("WmmCapable=%d\n", pAd->CommonCfg.bWmmCapable));
+       }
+
+#ifdef QOS_DLS_SUPPORT
+       //DLSCapable
+       if(RTMPGetKeyParameter("DLSCapable", tmpbuf, 32, buffer))
+       {
+               if(simple_strtol(tmpbuf, 0, 10) != 0)  //Enable
+               {
+                       pAd->CommonCfg.bDLSCapable = TRUE;
+               }
+               else //Disable
+               {
+                       pAd->CommonCfg.bDLSCapable = FALSE;
+               }
+
+               DBGPRINT(RT_DEBUG_TRACE, ("bDLSCapable=%d\n", pAd->CommonCfg.bDLSCapable));
+       }
+#endif // QOS_DLS_SUPPORT //
+
+       //AckPolicy for AC_BK, AC_BE, AC_VI, AC_VO
+       if(RTMPGetKeyParameter("AckPolicy", tmpbuf, 32, buffer))
+       {
+               for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+               {
+                       pAd->CommonCfg.AckPolicy[i] = (UCHAR)simple_strtol(macptr, 0, 10);
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("AckPolicy[%d]=%d\n", i, pAd->CommonCfg.AckPolicy[i]));
+               }
+       }
+
+       if (bWmmEnable)
+       {
+               //APSDCapable
+               if(RTMPGetKeyParameter("APSDCapable", tmpbuf, 10, buffer))
+               {
+                       if(simple_strtol(tmpbuf, 0, 10) != 0)  //Enable
+                               pAd->CommonCfg.bAPSDCapable = TRUE;
+                       else
+                               pAd->CommonCfg.bAPSDCapable = FALSE;
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("APSDCapable=%d\n", pAd->CommonCfg.bAPSDCapable));
+               }
+
+               //APSDAC for AC_BE, AC_BK, AC_VI, AC_VO
+               if(RTMPGetKeyParameter("APSDAC", tmpbuf, 32, buffer))
+               {
+                       BOOLEAN apsd_ac[4];
+
+                       for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+                       {
+                               apsd_ac[i] = (BOOLEAN)simple_strtol(macptr, 0, 10);
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("APSDAC%d  %d\n", i,  apsd_ac[i]));
+                       }
+
+                       pAd->CommonCfg.bAPSDAC_BE = apsd_ac[0];
+                       pAd->CommonCfg.bAPSDAC_BK = apsd_ac[1];
+                       pAd->CommonCfg.bAPSDAC_VI = apsd_ac[2];
+                       pAd->CommonCfg.bAPSDAC_VO = apsd_ac[3];
+               }
+       }
+
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+NDIS_STATUS    RTMPReadParametersHook(
+       IN      PRTMP_ADAPTER pAd)
+{
+       PUCHAR                                  src = NULL;
+       struct file                             *srcf;
+       INT                                     retval, orgfsuid, orgfsgid;
+       mm_segment_t                    orgfs;
+       CHAR                                    *buffer;
+       CHAR                                    *tmpbuf;
+       ULONG                                   RtsThresh;
+       ULONG                                   FragThresh;
+#ifdef CONFIG_STA_SUPPORT
+       UCHAR                   keyMaterial[40];
+#endif // CONFIG_STA_SUPPORT //
+
+
+       PUCHAR                                  macptr;
+       INT                                             i = 0;
+
+       buffer = kmalloc(MAX_INI_BUFFER_SIZE, MEM_ALLOC_FLAG);
+       if(buffer == NULL)
+        return NDIS_STATUS_FAILURE;
+
+       tmpbuf = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+       if(tmpbuf == NULL)
+       {
+               kfree(buffer);
+        return NDIS_STATUS_FAILURE;
+       }
+
+#ifdef CONFIG_STA_SUPPORT
+       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               src = STA_PROFILE_PATH;
+#endif // CONFIG_STA_SUPPORT //
+#ifdef MULTIPLE_CARD_SUPPORT
+       src = pAd->MC_FileName;
+#endif // MULTIPLE_CARD_SUPPORT //
+
+       // Save uid and gid used for filesystem access.
+       // Set user and group to 0 (root)
+       orgfsuid = current->fsuid;
+       orgfsgid = current->fsgid;
+       current->fsuid=current->fsgid = 0;
+    orgfs = get_fs();
+    set_fs(KERNEL_DS);
+
+       if (src && *src)
+       {
+               srcf = filp_open(src, O_RDONLY, 0);
+               if (IS_ERR(srcf))
+               {
+                       DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld opening %s\n", -PTR_ERR(srcf),src));
+               }
+               else
+               {
+                       // The object must have a read method
+                       if (srcf->f_op && srcf->f_op->read)
+                       {
+                               memset(buffer, 0x00, MAX_INI_BUFFER_SIZE);
+                               retval=srcf->f_op->read(srcf, buffer, MAX_INI_BUFFER_SIZE, &srcf->f_pos);
+                               if (retval < 0)
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("--> Read %s error %d\n", src, -retval));
+                               }
+                               else
+                               {
+                                       // set file parameter to portcfg
+                                       //CountryRegion
+                                       if(RTMPGetKeyParameter("CountryRegion", tmpbuf, 25, buffer))
+                                       {
+                                               pAd->CommonCfg.CountryRegion = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+                                               DBGPRINT(RT_DEBUG_TRACE, ("CountryRegion=%d\n", pAd->CommonCfg.CountryRegion));
+                                       }
+                                       //CountryRegionABand
+                                       if(RTMPGetKeyParameter("CountryRegionABand", tmpbuf, 25, buffer))
+                                       {
+                                               pAd->CommonCfg.CountryRegionForABand= (UCHAR) simple_strtol(tmpbuf, 0, 10);
+                                               DBGPRINT(RT_DEBUG_TRACE, ("CountryRegionABand=%d\n", pAd->CommonCfg.CountryRegionForABand));
+                                       }
+                                       //CountryCode
+                                       if(RTMPGetKeyParameter("CountryCode", tmpbuf, 25, buffer))
+                                       {
+                                               NdisMoveMemory(pAd->CommonCfg.CountryCode, tmpbuf , 2);
+#ifdef CONFIG_STA_SUPPORT
+#ifdef EXT_BUILD_CHANNEL_LIST
+                                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                                       NdisMoveMemory(pAd->StaCfg.StaOriCountryCode, tmpbuf , 2);
+#endif // EXT_BUILD_CHANNEL_LIST //
+#endif // CONFIG_STA_SUPPORT //
+                                               if (strlen(pAd->CommonCfg.CountryCode) != 0)
+                                               {
+                                                       pAd->CommonCfg.bCountryFlag = TRUE;
+                                               }
+                                               DBGPRINT(RT_DEBUG_TRACE, ("CountryCode=%s\n", pAd->CommonCfg.CountryCode));
+                                       }
+                                       //ChannelGeography
+                                       if(RTMPGetKeyParameter("ChannelGeography", tmpbuf, 25, buffer))
+                                       {
+                                               UCHAR Geography = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+                                               if (Geography <= BOTH)
+                                               {
+                                                       pAd->CommonCfg.Geography = Geography;
+                                                       pAd->CommonCfg.CountryCode[2] =
+                                                               (pAd->CommonCfg.Geography == BOTH) ? ' ' : ((pAd->CommonCfg.Geography == IDOR) ? 'I' : 'O');
+#ifdef CONFIG_STA_SUPPORT
+#ifdef EXT_BUILD_CHANNEL_LIST
+                                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                                       pAd->StaCfg.StaOriGeography = pAd->CommonCfg.Geography;
+#endif // EXT_BUILD_CHANNEL_LIST //
+#endif // CONFIG_STA_SUPPORT //
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("ChannelGeography=%d\n", pAd->CommonCfg.Geography));
+                                               }
+                                       }
+                                       else
+                                       {
+                                               pAd->CommonCfg.Geography = BOTH;
+                                               pAd->CommonCfg.CountryCode[2] = ' ';
+                                       }
+
+
+#ifdef CONFIG_STA_SUPPORT
+                                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                       {
+                                               //SSID
+                                               if (RTMPGetCriticalParameter("SSID", tmpbuf, 256, buffer))
+                                               {
+                                                       if (strlen(tmpbuf) <= 32)
+                                                       {
+                                                               pAd->CommonCfg.SsidLen = (UCHAR) strlen(tmpbuf);
+                                                               NdisZeroMemory(pAd->CommonCfg.Ssid, NDIS_802_11_LENGTH_SSID);
+                                                               NdisMoveMemory(pAd->CommonCfg.Ssid, tmpbuf, pAd->CommonCfg.SsidLen);
+                                                               pAd->MlmeAux.AutoReconnectSsidLen = pAd->CommonCfg.SsidLen;
+                                                               NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, NDIS_802_11_LENGTH_SSID);
+                                                               NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, tmpbuf, pAd->MlmeAux.AutoReconnectSsidLen);
+                                                               pAd->MlmeAux.SsidLen = pAd->CommonCfg.SsidLen;
+                                                               NdisZeroMemory(pAd->MlmeAux.Ssid, NDIS_802_11_LENGTH_SSID);
+                                                               NdisMoveMemory(pAd->MlmeAux.Ssid, tmpbuf, pAd->MlmeAux.SsidLen);
+                                                               DBGPRINT(RT_DEBUG_TRACE, ("%s::(SSID=%s)\n", __FUNCTION__, tmpbuf));
+                                                       }
+                                               }
+                                       }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+                                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                       {
+                                               //NetworkType
+                                               if (RTMPGetKeyParameter("NetworkType", tmpbuf, 25, buffer))
+                                               {
+                                                       pAd->bConfigChanged = TRUE;
+                                                       if (strcmp(tmpbuf, "Adhoc") == 0)
+                                                               pAd->StaCfg.BssType = BSS_ADHOC;
+                                                       else //Default Infrastructure mode
+                                                               pAd->StaCfg.BssType = BSS_INFRA;
+                                                       // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key
+                                                       pAd->StaCfg.WpaState = SS_NOTUSE;
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("%s::(NetworkType=%d)\n", __FUNCTION__, pAd->StaCfg.BssType));
+                                               }
+                                       }
+#endif // CONFIG_STA_SUPPORT //
+                                       //Channel
+                                       if(RTMPGetKeyParameter("Channel", tmpbuf, 10, buffer))
+                                       {
+                                               pAd->CommonCfg.Channel = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+                                               DBGPRINT(RT_DEBUG_TRACE, ("Channel=%d\n", pAd->CommonCfg.Channel));
+                                       }
+                                       //WirelessMode
+                                       if(RTMPGetKeyParameter("WirelessMode", tmpbuf, 10, buffer))
+                                       {
+                                               int value  = 0, maxPhyMode = PHY_11G;
+
+#ifdef DOT11_N_SUPPORT
+                                               maxPhyMode = PHY_11N_5G;
+#endif // DOT11_N_SUPPORT //
+
+                                               value = simple_strtol(tmpbuf, 0, 10);
+
+                                               if (value <= maxPhyMode)
+                                               {
+                                                       pAd->CommonCfg.PhyMode = value;
+                                               }
+                                               DBGPRINT(RT_DEBUG_TRACE, ("PhyMode=%d\n", pAd->CommonCfg.PhyMode));
+                                       }
+                    //BasicRate
+                                       if(RTMPGetKeyParameter("BasicRate", tmpbuf, 10, buffer))
+                                       {
+                                               pAd->CommonCfg.BasicRateBitmap = (ULONG) simple_strtol(tmpbuf, 0, 10);
+                                               DBGPRINT(RT_DEBUG_TRACE, ("BasicRate=%ld\n", pAd->CommonCfg.BasicRateBitmap));
+                                       }
+                                       //BeaconPeriod
+                                       if(RTMPGetKeyParameter("BeaconPeriod", tmpbuf, 10, buffer))
+                                       {
+                                               pAd->CommonCfg.BeaconPeriod = (USHORT) simple_strtol(tmpbuf, 0, 10);
+                                               DBGPRINT(RT_DEBUG_TRACE, ("BeaconPeriod=%d\n", pAd->CommonCfg.BeaconPeriod));
+                                       }
+                    //TxPower
+                                       if(RTMPGetKeyParameter("TxPower", tmpbuf, 10, buffer))
+                                       {
+                                               pAd->CommonCfg.TxPowerPercentage = (ULONG) simple_strtol(tmpbuf, 0, 10);
+#ifdef CONFIG_STA_SUPPORT
+                                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                                       pAd->CommonCfg.TxPowerDefault = pAd->CommonCfg.TxPowerPercentage;
+#endif // CONFIG_STA_SUPPORT //
+                                               DBGPRINT(RT_DEBUG_TRACE, ("TxPower=%ld\n", pAd->CommonCfg.TxPowerPercentage));
+                                       }
+                                       //BGProtection
+                                       if(RTMPGetKeyParameter("BGProtection", tmpbuf, 10, buffer))
+                                       {
+                                               switch (simple_strtol(tmpbuf, 0, 10))
+                                               {
+                                                       case 1: //Always On
+                                                               pAd->CommonCfg.UseBGProtection = 1;
+                                                               break;
+                                                       case 2: //Always OFF
+                                                               pAd->CommonCfg.UseBGProtection = 2;
+                                                               break;
+                                                       case 0: //AUTO
+                                                       default:
+                                                               pAd->CommonCfg.UseBGProtection = 0;
+                                                               break;
+                                               }
+                                               DBGPRINT(RT_DEBUG_TRACE, ("BGProtection=%ld\n", pAd->CommonCfg.UseBGProtection));
+                                       }
+                                       //OLBCDetection
+                                       if(RTMPGetKeyParameter("DisableOLBC", tmpbuf, 10, buffer))
+                                       {
+                                               switch (simple_strtol(tmpbuf, 0, 10))
+                                               {
+                                                       case 1: //disable OLBC Detection
+                                                               pAd->CommonCfg.DisableOLBCDetect = 1;
+                                                               break;
+                                                       case 0: //enable OLBC Detection
+                                                               pAd->CommonCfg.DisableOLBCDetect = 0;
+                                                               break;
+                                                       default:
+                                                               pAd->CommonCfg.DisableOLBCDetect= 0;
+                                                               break;
+                                               }
+                                               DBGPRINT(RT_DEBUG_TRACE, ("OLBCDetection=%ld\n", pAd->CommonCfg.DisableOLBCDetect));
+                                       }
+                                       //TxPreamble
+                                       if(RTMPGetKeyParameter("TxPreamble", tmpbuf, 10, buffer))
+                                       {
+                                               switch (simple_strtol(tmpbuf, 0, 10))
+                                               {
+                                                       case Rt802_11PreambleShort:
+                                                               pAd->CommonCfg.TxPreamble = Rt802_11PreambleShort;
+                                                               break;
+                                                       case Rt802_11PreambleLong:
+                                                       default:
+                                                               pAd->CommonCfg.TxPreamble = Rt802_11PreambleLong;
+                                                               break;
+                                               }
+                                               DBGPRINT(RT_DEBUG_TRACE, ("TxPreamble=%ld\n", pAd->CommonCfg.TxPreamble));
+                                       }
+                                       //RTSThreshold
+                                       if(RTMPGetKeyParameter("RTSThreshold", tmpbuf, 10, buffer))
+                                       {
+                                               RtsThresh = simple_strtol(tmpbuf, 0, 10);
+                                               if( (RtsThresh >= 1) && (RtsThresh <= MAX_RTS_THRESHOLD) )
+                                                       pAd->CommonCfg.RtsThreshold  = (USHORT)RtsThresh;
+                                               else
+                                                       pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD;
+
+                                               DBGPRINT(RT_DEBUG_TRACE, ("RTSThreshold=%d\n", pAd->CommonCfg.RtsThreshold));
+                                       }
+                                       //FragThreshold
+                                       if(RTMPGetKeyParameter("FragThreshold", tmpbuf, 10, buffer))
+                                       {
+                                               FragThresh = simple_strtol(tmpbuf, 0, 10);
+                                               pAd->CommonCfg.bUseZeroToDisableFragment = FALSE;
+
+                                               if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD)
+                                               { //illegal FragThresh so we set it to default
+                                                       pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;
+                                                       pAd->CommonCfg.bUseZeroToDisableFragment = TRUE;
+                                               }
+                                               else if (FragThresh % 2 == 1)
+                                               {
+                                                       // The length of each fragment shall always be an even number of octets, except for the last fragment
+                                                       // of an MSDU or MMPDU, which may be either an even or an odd number of octets.
+                                                       pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1);
+                                               }
+                                               else
+                                               {
+                                                       pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh;
+                                               }
+                                               //pAd->CommonCfg.AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
+                                               DBGPRINT(RT_DEBUG_TRACE, ("FragThreshold=%d\n", pAd->CommonCfg.FragmentThreshold));
+                                       }
+                                       //TxBurst
+                                       if(RTMPGetKeyParameter("TxBurst", tmpbuf, 10, buffer))
+                                       {
+//#ifdef WIFI_TEST
+//                                             pAd->CommonCfg.bEnableTxBurst = FALSE;
+//#else
+                                               if(simple_strtol(tmpbuf, 0, 10) != 0)  //Enable
+                                                       pAd->CommonCfg.bEnableTxBurst = TRUE;
+                                               else //Disable
+                                                       pAd->CommonCfg.bEnableTxBurst = FALSE;
+//#endif
+                                               DBGPRINT(RT_DEBUG_TRACE, ("TxBurst=%d\n", pAd->CommonCfg.bEnableTxBurst));
+                                       }
+
+#ifdef AGGREGATION_SUPPORT
+                                       //PktAggregate
+                                       if(RTMPGetKeyParameter("PktAggregate", tmpbuf, 10, buffer))
+                                       {
+                                               if(simple_strtol(tmpbuf, 0, 10) != 0)  //Enable
+                                                       pAd->CommonCfg.bAggregationCapable = TRUE;
+                                               else //Disable
+                                                       pAd->CommonCfg.bAggregationCapable = FALSE;
+#ifdef PIGGYBACK_SUPPORT
+                                               pAd->CommonCfg.bPiggyBackCapable = pAd->CommonCfg.bAggregationCapable;
+#endif // PIGGYBACK_SUPPORT //
+                                               DBGPRINT(RT_DEBUG_TRACE, ("PktAggregate=%d\n", pAd->CommonCfg.bAggregationCapable));
+                                       }
+#else
+                                       pAd->CommonCfg.bAggregationCapable = FALSE;
+                                       pAd->CommonCfg.bPiggyBackCapable = FALSE;
+#endif // AGGREGATION_SUPPORT //
+
+                                       // WmmCapable
+
+#ifdef CONFIG_STA_SUPPORT
+                                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                               rtmp_read_sta_wmm_parms_from_file(pAd, tmpbuf, buffer);
+#endif // CONFIG_STA_SUPPORT //
+
+                                       //ShortSlot
+                                       if(RTMPGetKeyParameter("ShortSlot", tmpbuf, 10, buffer))
+                                       {
+                                               if(simple_strtol(tmpbuf, 0, 10) != 0)  //Enable
+                                                       pAd->CommonCfg.bUseShortSlotTime = TRUE;
+                                               else //Disable
+                                                       pAd->CommonCfg.bUseShortSlotTime = FALSE;
+
+                                               DBGPRINT(RT_DEBUG_TRACE, ("ShortSlot=%d\n", pAd->CommonCfg.bUseShortSlotTime));
+                                       }
+                                       //IEEE80211H
+                                       if(RTMPGetKeyParameter("IEEE80211H", tmpbuf, 10, buffer))
+                                       {
+                                           for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+                                           {
+                                               if(simple_strtol(macptr, 0, 10) != 0)  //Enable
+                                                       pAd->CommonCfg.bIEEE80211H = TRUE;
+                                               else //Disable
+                                                       pAd->CommonCfg.bIEEE80211H = FALSE;
+
+                                               DBGPRINT(RT_DEBUG_TRACE, ("IEEE80211H=%d\n", pAd->CommonCfg.bIEEE80211H));
+                                           }
+                                       }
+                                       //CSPeriod
+                                       if(RTMPGetKeyParameter("CSPeriod", tmpbuf, 10, buffer))
+                                       {
+                                           if(simple_strtol(tmpbuf, 0, 10) != 0)
+                                                       pAd->CommonCfg.RadarDetect.CSPeriod = simple_strtol(tmpbuf, 0, 10);
+                                               else
+                                                       pAd->CommonCfg.RadarDetect.CSPeriod = 0;
+
+                                               DBGPRINT(RT_DEBUG_TRACE, ("CSPeriod=%d\n", pAd->CommonCfg.RadarDetect.CSPeriod));
+                                       }
+
+                                       //RDRegion
+                                       if(RTMPGetKeyParameter("RDRegion", tmpbuf, 128, buffer))
+                                       {
+                                               if ((strncmp(tmpbuf, "JAP_W53", 7) == 0) || (strncmp(tmpbuf, "jap_w53", 7) == 0))
+                                               {
+                                                       pAd->CommonCfg.RadarDetect.RDDurRegion = JAP_W53;
+                                                       pAd->CommonCfg.RadarDetect.DfsSessionTime = 15;
+                                               }
+                                               else if ((strncmp(tmpbuf, "JAP_W56", 7) == 0) || (strncmp(tmpbuf, "jap_w56", 7) == 0))
+                                               {
+                                                       pAd->CommonCfg.RadarDetect.RDDurRegion = JAP_W56;
+                                                       pAd->CommonCfg.RadarDetect.DfsSessionTime = 13;
+                                               }
+                                               else if ((strncmp(tmpbuf, "JAP", 3) == 0) || (strncmp(tmpbuf, "jap", 3) == 0))
+                                               {
+                                                       pAd->CommonCfg.RadarDetect.RDDurRegion = JAP;
+                                                       pAd->CommonCfg.RadarDetect.DfsSessionTime = 5;
+                                               }
+                                               else  if ((strncmp(tmpbuf, "FCC", 3) == 0) || (strncmp(tmpbuf, "fcc", 3) == 0))
+                                               {
+                                                       pAd->CommonCfg.RadarDetect.RDDurRegion = FCC;
+                                                       pAd->CommonCfg.RadarDetect.DfsSessionTime = 5;
+                                               }
+                                               else if ((strncmp(tmpbuf, "CE", 2) == 0) || (strncmp(tmpbuf, "ce", 2) == 0))
+                                               {
+                                                       pAd->CommonCfg.RadarDetect.RDDurRegion = CE;
+                                                       pAd->CommonCfg.RadarDetect.DfsSessionTime = 13;
+                                               }
+                                               else
+                                               {
+                                                       pAd->CommonCfg.RadarDetect.RDDurRegion = CE;
+                                                       pAd->CommonCfg.RadarDetect.DfsSessionTime = 13;
+                                               }
+
+                                               DBGPRINT(RT_DEBUG_TRACE, ("RDRegion=%d\n", pAd->CommonCfg.RadarDetect.RDDurRegion));
+                                       }
+                                       else
+                                       {
+                                               pAd->CommonCfg.RadarDetect.RDDurRegion = CE;
+                                               pAd->CommonCfg.RadarDetect.DfsSessionTime = 13;
+                                       }
+
+                                       //WirelessEvent
+                                       if(RTMPGetKeyParameter("WirelessEvent", tmpbuf, 10, buffer))
+                                       {
+#if WIRELESS_EXT >= 15
+                                           if(simple_strtol(tmpbuf, 0, 10) != 0)
+                                                       pAd->CommonCfg.bWirelessEvent = simple_strtol(tmpbuf, 0, 10);
+                                               else
+                                                       pAd->CommonCfg.bWirelessEvent = 0;      // disable
+#else
+                                               pAd->CommonCfg.bWirelessEvent = 0;      // disable
+#endif
+                                               DBGPRINT(RT_DEBUG_TRACE, ("WirelessEvent=%d\n", pAd->CommonCfg.bWirelessEvent));
+                                       }
+                                       if(RTMPGetKeyParameter("WiFiTest", tmpbuf, 10, buffer))
+                                       {
+                                           if(simple_strtol(tmpbuf, 0, 10) != 0)
+                                                       pAd->CommonCfg.bWiFiTest= simple_strtol(tmpbuf, 0, 10);
+                                               else
+                                                       pAd->CommonCfg.bWiFiTest = 0;   // disable
+
+                                               DBGPRINT(RT_DEBUG_TRACE, ("WiFiTest=%d\n", pAd->CommonCfg.bWiFiTest));
+                                       }
+                                       //AuthMode
+                                       if(RTMPGetKeyParameter("AuthMode", tmpbuf, 128, buffer))
+                                       {
+#ifdef CONFIG_STA_SUPPORT
+                                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                               {
+                                                       if ((strcmp(tmpbuf, "WEPAUTO") == 0) || (strcmp(tmpbuf, "wepauto") == 0))
+                                                           pAd->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch;
+                                                       else if ((strcmp(tmpbuf, "SHARED") == 0) || (strcmp(tmpbuf, "shared") == 0))
+                                                           pAd->StaCfg.AuthMode = Ndis802_11AuthModeShared;
+                                                       else if ((strcmp(tmpbuf, "WPAPSK") == 0) || (strcmp(tmpbuf, "wpapsk") == 0))
+                                                           pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK;
+                                                       else if ((strcmp(tmpbuf, "WPANONE") == 0) || (strcmp(tmpbuf, "wpanone") == 0))
+                                                           pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPANone;
+                                                       else if ((strcmp(tmpbuf, "WPA2PSK") == 0) || (strcmp(tmpbuf, "wpa2psk") == 0))
+                                                           pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK;
+#ifdef WPA_SUPPLICANT_SUPPORT
+                                                       else if ((strcmp(tmpbuf, "WPA") == 0) || (strcmp(tmpbuf, "wpa") == 0))
+                                                           pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA;
+                                                       else if ((strcmp(tmpbuf, "WPA2") == 0) || (strcmp(tmpbuf, "wpa2") == 0))
+                                                           pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2;
+#endif // WPA_SUPPLICANT_SUPPORT //
+                                                       else
+                                                           pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+
+                                                       pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __FUNCTION__, pAd->StaCfg.WepStatus));
+                                               }
+#endif // CONFIG_STA_SUPPORT //
+                                       }
+                                       //EncrypType
+                                       if(RTMPGetKeyParameter("EncrypType", tmpbuf, 128, buffer))
+                                       {
+
+#ifdef CONFIG_STA_SUPPORT
+                                               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                               {
+                                                       if ((strcmp(tmpbuf, "WEP") == 0) || (strcmp(tmpbuf, "wep") == 0))
+                                                               pAd->StaCfg.WepStatus   = Ndis802_11WEPEnabled;
+                                                       else if ((strcmp(tmpbuf, "TKIP") == 0) || (strcmp(tmpbuf, "tkip") == 0))
+                                                               pAd->StaCfg.WepStatus   = Ndis802_11Encryption2Enabled;
+                                                       else if ((strcmp(tmpbuf, "AES") == 0) || (strcmp(tmpbuf, "aes") == 0))
+                                                               pAd->StaCfg.WepStatus   = Ndis802_11Encryption3Enabled;
+                                                       else
+                                                               pAd->StaCfg.WepStatus   = Ndis802_11WEPDisabled;
+
+                                                       // Update all wepstatus related
+                                                       pAd->StaCfg.PairCipher          = pAd->StaCfg.WepStatus;
+                                                       pAd->StaCfg.GroupCipher         = pAd->StaCfg.WepStatus;
+                                                       pAd->StaCfg.OrigWepStatus       = pAd->StaCfg.WepStatus;
+                                                       pAd->StaCfg.bMixCipher          = FALSE;
+
+                                                       //RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0);
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __FUNCTION__, pAd->StaCfg.WepStatus));
+                                               }
+#endif // CONFIG_STA_SUPPORT //
+                                       }
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+                                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                       {
+                                               if(RTMPGetCriticalParameter("WPAPSK", tmpbuf, 512, buffer))
+                                               {
+                                                       int     err=0;
+
+                                                       tmpbuf[strlen(tmpbuf)] = '\0'; // make STA can process .$^& for WPAPSK input
+
+                                                       if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) &&
+                                                               (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) &&
+                                                               (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone)
+                                                               )
+                                                       {
+                                                               err = 1;
+                                                       }
+                                                       else if ((strlen(tmpbuf) >= 8) && (strlen(tmpbuf) < 64))
+                                                       {
+                                                               PasswordHash((char *)tmpbuf, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, keyMaterial);
+                                                               NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32);
+
+                                                       }
+                                                       else if (strlen(tmpbuf) == 64)
+                                                       {
+                                                               AtoH(tmpbuf, keyMaterial, 32);
+                                                               NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32);
+                                                       }
+                                                       else
+                                                       {
+                                                               err = 1;
+                                                               DBGPRINT(RT_DEBUG_ERROR, ("%s::(WPAPSK key-string required 8 ~ 64 characters!)\n", __FUNCTION__));
+                                                       }
+
+                                                       if (err == 0)
+                                                       {
+                                                               if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+                                                                       (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+                                                               {
+                                                                       // Start STA supplicant state machine
+                                                                       pAd->StaCfg.WpaState = SS_START;
+                                                               }
+                                                               else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+                                                               {
+       /*
+                                                                       NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
+                                                                       pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
+                                                                       NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pAd->StaCfg.PMK, LEN_TKIP_EK);
+                                                                       NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_RXMICK);
+                                                                       NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_TXMICK);
+
+                                                                       // Decide its ChiperAlg
+                                                                       if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+                                                                               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
+                                                                       else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
+                                                                               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
+                                                                       else
+                                                                               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE;
+       */
+                                                                       pAd->StaCfg.WpaState = SS_NOTUSE;
+                                                               }
+
+                                                               DBGPRINT(RT_DEBUG_TRACE, ("%s::(WPAPSK=%s)\n", __FUNCTION__, tmpbuf));
+                                                       }
+                                               }
+                                       }
+#endif // CONFIG_STA_SUPPORT //
+
+                                       //DefaultKeyID, KeyType, KeyStr
+                                       rtmp_read_key_parms_from_file(pAd, tmpbuf, buffer);
+
+
+                                       //HSCounter
+                                       /*if(RTMPGetKeyParameter("HSCounter", tmpbuf, 10, buffer))
+                                       {
+                                               switch (simple_strtol(tmpbuf, 0, 10))
+                                               {
+                                                       case 1: //Enable
+                                                               pAd->CommonCfg.bEnableHSCounter = TRUE;
+                                                               break;
+                                                       case 0: //Disable
+                                                       default:
+                                                               pAd->CommonCfg.bEnableHSCounter = FALSE;
+                                                               break;
+                                               }
+                                               DBGPRINT(RT_DEBUG_TRACE, "HSCounter=%d\n", pAd->CommonCfg.bEnableHSCounter);
+                                       }*/
+
+#ifdef DOT11_N_SUPPORT
+                                       HTParametersHook(pAd, tmpbuf, buffer);
+#endif // DOT11_N_SUPPORT //
+
+
+#ifdef CARRIER_DETECTION_SUPPORT
+                                               //CarrierDetect
+                                               if(RTMPGetKeyParameter("CarrierDetect", tmpbuf, 128, buffer))
+                                               {
+                                                       if ((strncmp(tmpbuf, "0", 1) == 0))
+                                                               pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+                                                       else if ((strncmp(tmpbuf, "1", 1) == 0))
+                                                               pAd->CommonCfg.CarrierDetect.Enable = TRUE;
+                                                       else
+                                                               pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("CarrierDetect.Enable=%d\n", pAd->CommonCfg.CarrierDetect.Enable));
+                                               }
+                                               else
+                                                       pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+#endif // CARRIER_DETECTION_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+                                       IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+                                       {
+                                               //PSMode
+                                               if (RTMPGetKeyParameter("PSMode", tmpbuf, 10, buffer))
+                                               {
+                                                       if (pAd->StaCfg.BssType == BSS_INFRA)
+                                                       {
+                                                               if ((strcmp(tmpbuf, "MAX_PSP") == 0) || (strcmp(tmpbuf, "max_psp") == 0))
+                                                               {
+                                                                       // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+                                                                       // to exclude certain situations.
+                                                                       //         MlmeSetPsm(pAd, PWR_SAVE);
+                                                                       OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
+                                                                       if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
+                                                                               pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP;
+                                                                       pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP;
+                                                                       pAd->StaCfg.DefaultListenCount = 5;
+                                                               }
+                                                               else if ((strcmp(tmpbuf, "Fast_PSP") == 0) || (strcmp(tmpbuf, "fast_psp") == 0)
+                                                                       || (strcmp(tmpbuf, "FAST_PSP") == 0))
+                                                               {
+                                                                       // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+                                                                       // to exclude certain situations.
+                                                                       //         MlmeSetPsmBit(pAd, PWR_SAVE);
+                                                                       OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
+                                                                       if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
+                                                                               pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP;
+                                                                       pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP;
+                                                                       pAd->StaCfg.DefaultListenCount = 3;
+                                                               }
+                                                               else if ((strcmp(tmpbuf, "Legacy_PSP") == 0) || (strcmp(tmpbuf, "legacy_psp") == 0)
+                                                                       || (strcmp(tmpbuf, "LEGACY_PSP") == 0))
+                                                               {
+                                                                       // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+                                                                       // to exclude certain situations.
+                                                                       //         MlmeSetPsmBit(pAd, PWR_SAVE);
+                                                                       OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
+                                                                       if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
+                                                                               pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP;
+                                                                       pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP;
+                                                                       pAd->StaCfg.DefaultListenCount = 3;
+                                                               }
+                                                               else
+                                                               { //Default Ndis802_11PowerModeCAM
+                                                                       // clear PSM bit immediately
+                                                                       MlmeSetPsmBit(pAd, PWR_ACTIVE);
+                                                                       OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
+                                                                       if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
+                                                                               pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM;
+                                                                       pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM;
+                                                               }
+                                                               DBGPRINT(RT_DEBUG_TRACE, ("PSMode=%ld\n", pAd->StaCfg.WindowsPowerMode));
+                                                       }
+                                               }
+                                               // FastRoaming
+                                               if (RTMPGetKeyParameter("FastRoaming", tmpbuf, 32, buffer))
+                                               {
+                                                       if (simple_strtol(tmpbuf, 0, 10) == 0)
+                                                               pAd->StaCfg.bFastRoaming = FALSE;
+                                                       else
+                                                               pAd->StaCfg.bFastRoaming = TRUE;
+
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("FastRoaming=%d\n", pAd->StaCfg.bFastRoaming));
+                                               }
+                                               // RoamThreshold
+                                               if (RTMPGetKeyParameter("RoamThreshold", tmpbuf, 32, buffer))
+                                               {
+                                                       long lInfo = simple_strtol(tmpbuf, 0, 10);
+
+                                                       if (lInfo > 90 || lInfo < 60)
+                                                               pAd->StaCfg.dBmToRoam = -70;
+                                                       else
+                                                               pAd->StaCfg.dBmToRoam = (CHAR)(-1)*lInfo;
+
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("RoamThreshold=%d  dBm\n", pAd->StaCfg.dBmToRoam));
+                                               }
+
+                                               if(RTMPGetKeyParameter("TGnWifiTest", tmpbuf, 10, buffer))
+                                               {
+                                                       if(simple_strtol(tmpbuf, 0, 10) == 0)
+                                                               pAd->StaCfg.bTGnWifiTest = FALSE;
+                                                       else
+                                                               pAd->StaCfg.bTGnWifiTest = TRUE;
+                                                               DBGPRINT(RT_DEBUG_TRACE, ("TGnWifiTest=%d\n", pAd->StaCfg.bTGnWifiTest));
+                                               }
+                                       }
+#endif // CONFIG_STA_SUPPORT //
+
+
+
+                               }
+                       }
+                       else
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("--> %s does not have a write method\n", src));
+                       }
+
+                       retval=filp_close(srcf,NULL);
+
+                       if (retval)
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src));
+                       }
+               }
+       }
+
+       set_fs(orgfs);
+       current->fsuid = orgfsuid;
+       current->fsgid = orgfsgid;
+
+       kfree(buffer);
+       kfree(tmpbuf);
+
+       return (NDIS_STATUS_SUCCESS);
+}
+
+#ifdef DOT11_N_SUPPORT
+static void    HTParametersHook(
+       IN      PRTMP_ADAPTER pAd,
+       IN      CHAR              *pValueStr,
+       IN      CHAR              *pInput)
+{
+
+       INT Value;
+
+    if (RTMPGetKeyParameter("HT_PROTECT", pValueStr, 25, pInput))
+    {
+        Value = simple_strtol(pValueStr, 0, 10);
+        if (Value == 0)
+        {
+            pAd->CommonCfg.bHTProtect = FALSE;
+        }
+        else
+        {
+            pAd->CommonCfg.bHTProtect = TRUE;
+        }
+        DBGPRINT(RT_DEBUG_TRACE, ("HT: Protection  = %s\n", (Value==0) ? "Disable" : "Enable"));
+    }
+
+    if (RTMPGetKeyParameter("HT_MIMOPSEnable", pValueStr, 25, pInput))
+    {
+        Value = simple_strtol(pValueStr, 0, 10);
+        if (Value == 0)
+        {
+            pAd->CommonCfg.bMIMOPSEnable = FALSE;
+        }
+        else
+        {
+            pAd->CommonCfg.bMIMOPSEnable = TRUE;
+        }
+        DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPSEnable  = %s\n", (Value==0) ? "Disable" : "Enable"));
+    }
+
+
+    if (RTMPGetKeyParameter("HT_MIMOPSMode", pValueStr, 25, pInput))
+    {
+        Value = simple_strtol(pValueStr, 0, 10);
+        if (Value > MMPS_ENABLE)
+        {
+                       pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE;
+        }
+        else
+        {
+            //TODO: add mimo power saving mechanism
+            pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE;
+                       //pAd->CommonCfg.BACapability.field.MMPSmode = Value;
+        }
+        DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPS Mode  = %d\n", Value));
+    }
+
+    if (RTMPGetKeyParameter("HT_BADecline", pValueStr, 25, pInput))
+    {
+        Value = simple_strtol(pValueStr, 0, 10);
+        if (Value == 0)
+        {
+            pAd->CommonCfg.bBADecline = FALSE;
+        }
+        else
+        {
+            pAd->CommonCfg.bBADecline = TRUE;
+        }
+        DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Decline  = %s\n", (Value==0) ? "Disable" : "Enable"));
+    }
+
+
+    if (RTMPGetKeyParameter("HT_DisableReordering", pValueStr, 25, pInput))
+    {
+        Value = simple_strtol(pValueStr, 0, 10);
+        if (Value == 0)
+        {
+            pAd->CommonCfg.bDisableReordering = FALSE;
+        }
+        else
+        {
+            pAd->CommonCfg.bDisableReordering = TRUE;
+        }
+        DBGPRINT(RT_DEBUG_TRACE, ("HT: DisableReordering  = %s\n", (Value==0) ? "Disable" : "Enable"));
+    }
+
+    if (RTMPGetKeyParameter("HT_AutoBA", pValueStr, 25, pInput))
+    {
+        Value = simple_strtol(pValueStr, 0, 10);
+        if (Value == 0)
+        {
+            pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+        }
+        else
+        {
+            pAd->CommonCfg.BACapability.field.AutoBA = TRUE;
+        }
+        pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA;
+        DBGPRINT(RT_DEBUG_TRACE, ("HT: Auto BA  = %s\n", (Value==0) ? "Disable" : "Enable"));
+    }
+
+       // Tx_+HTC frame
+    if (RTMPGetKeyParameter("HT_HTC", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+               if (Value == 0)
+               {
+                       pAd->HTCEnable = FALSE;
+               }
+               else
+               {
+                       pAd->HTCEnable = TRUE;
+               }
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx +HTC frame = %s\n", (Value==0) ? "Disable" : "Enable"));
+       }
+
+       // Enable HT Link Adaptation Control
+       if (RTMPGetKeyParameter("HT_LinkAdapt", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+               if (Value == 0)
+               {
+                       pAd->bLinkAdapt = FALSE;
+               }
+               else
+               {
+                       pAd->HTCEnable = TRUE;
+                       pAd->bLinkAdapt = TRUE;
+               }
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: Link Adaptation Control = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)"));
+       }
+
+       // Reverse Direction Mechanism
+    if (RTMPGetKeyParameter("HT_RDG", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+               if (Value == 0)
+               {
+                       pAd->CommonCfg.bRdg = FALSE;
+               }
+               else
+               {
+                       pAd->HTCEnable = TRUE;
+            pAd->CommonCfg.bRdg = TRUE;
+               }
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: RDG = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)"));
+       }
+
+
+
+
+       // Tx A-MSUD ?
+    if (RTMPGetKeyParameter("HT_AMSDU", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+               if (Value == 0)
+               {
+                       pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE;
+               }
+               else
+               {
+            pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE;
+               }
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable"));
+       }
+
+       // MPDU Density
+    if (RTMPGetKeyParameter("HT_MpduDensity", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+               if (Value <=7 && Value >= 0)
+               {
+                       pAd->CommonCfg.BACapability.field.MpduDensity = Value;
+                       DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d\n", Value));
+               }
+               else
+               {
+                       pAd->CommonCfg.BACapability.field.MpduDensity = 4;
+                       DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d (Default)\n", 4));
+               }
+       }
+
+       // Max Rx BA Window Size
+    if (RTMPGetKeyParameter("HT_BAWinSize", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+
+               if (Value >=1 && Value <= 64)
+               {
+                       pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value;
+                       pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value;
+                       DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = %d\n", Value));
+               }
+               else
+               {
+            pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64;
+                       pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64;
+                       DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = 64 (Defualt)\n"));
+               }
+
+       }
+
+       // Guard Interval
+       if (RTMPGetKeyParameter("HT_GI", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+
+               if (Value == GI_400)
+               {
+                       pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400;
+               }
+               else
+               {
+                       pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800;
+               }
+
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: Guard Interval = %s\n", (Value==GI_400) ? "400" : "800" ));
+       }
+
+       // HT Operation Mode : Mixed Mode , Green Field
+       if (RTMPGetKeyParameter("HT_OpMode", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+
+               if (Value == HTMODE_GF)
+               {
+
+                       pAd->CommonCfg.RegTransmitSetting.field.HTMODE  = HTMODE_GF;
+               }
+               else
+               {
+                       pAd->CommonCfg.RegTransmitSetting.field.HTMODE  = HTMODE_MM;
+               }
+
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: Operate Mode = %s\n", (Value==HTMODE_GF) ? "Green Field" : "Mixed Mode" ));
+       }
+
+       // Fixed Tx mode : CCK, OFDM
+       if (RTMPGetKeyParameter("FixedTxMode", pValueStr, 25, pInput))
+       {
+               UCHAR   fix_tx_mode;
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       fix_tx_mode = FIXED_TXMODE_HT;
+
+                       if (strcmp(pValueStr, "OFDM") == 0 || strcmp(pValueStr, "ofdm") == 0)
+                       {
+                               fix_tx_mode = FIXED_TXMODE_OFDM;
+                       }
+                       else if (strcmp(pValueStr, "CCK") == 0 || strcmp(pValueStr, "cck") == 0)
+                       {
+                       fix_tx_mode = FIXED_TXMODE_CCK;
+                       }
+                       else if (strcmp(pValueStr, "HT") == 0 || strcmp(pValueStr, "ht") == 0)
+                       {
+                       fix_tx_mode = FIXED_TXMODE_HT;
+               }
+               else
+               {
+                               Value = simple_strtol(pValueStr, 0, 10);
+                               // 1 : CCK
+                               // 2 : OFDM
+                               // otherwise : HT
+                               if (Value == FIXED_TXMODE_CCK || Value == FIXED_TXMODE_OFDM)
+                                       fix_tx_mode = Value;
+                               else
+                                       fix_tx_mode = FIXED_TXMODE_HT;
+               }
+
+                       pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Fixed Tx Mode = %d\n", fix_tx_mode));
+
+               }
+#endif // CONFIG_STA_SUPPORT //
+       }
+
+
+       // Channel Width
+       if (RTMPGetKeyParameter("HT_BW", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+
+               if (Value == BW_40)
+               {
+                       pAd->CommonCfg.RegTransmitSetting.field.BW  = BW_40;
+               }
+               else
+               {
+            pAd->CommonCfg.RegTransmitSetting.field.BW  = BW_20;
+               }
+
+#ifdef MCAST_RATE_SPECIFIC
+               pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW;
+#endif // MCAST_RATE_SPECIFIC //
+
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: Channel Width = %s\n", (Value==BW_40) ? "40 MHz" : "20 MHz" ));
+       }
+
+       if (RTMPGetKeyParameter("HT_EXTCHA", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+
+               if (Value == 0)
+               {
+
+                       pAd->CommonCfg.RegTransmitSetting.field.EXTCHA  = EXTCHA_BELOW;
+               }
+               else
+               {
+            pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+               }
+
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: Ext Channel = %s\n", (Value==0) ? "BELOW" : "ABOVE" ));
+       }
+
+       // MSC
+       if (RTMPGetKeyParameter("HT_MCS", pValueStr, 50, pInput))
+       {
+
+#ifdef CONFIG_STA_SUPPORT
+               IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+               {
+                       Value = simple_strtol(pValueStr, 0, 10);
+
+//                     if ((Value >= 0 && Value <= 15) || (Value == 32))
+                       if ((Value >= 0 && Value <= 23) || (Value == 32)) // 3*3
+               {
+                               pAd->StaCfg.DesiredTransmitSetting.field.MCS  = Value;
+                               pAd->StaCfg.bAutoTxRateSwitch = FALSE;
+                               DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = %d\n", pAd->StaCfg.DesiredTransmitSetting.field.MCS));
+               }
+               else
+               {
+                               pAd->StaCfg.DesiredTransmitSetting.field.MCS  = MCS_AUTO;
+                               pAd->StaCfg.bAutoTxRateSwitch = TRUE;
+                               DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = AUTO\n"));
+               }
+       }
+#endif // CONFIG_STA_SUPPORT //
+       }
+
+       // STBC
+    if (RTMPGetKeyParameter("HT_STBC", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+               if (Value == STBC_USE)
+               {
+                       pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE;
+               }
+               else
+               {
+                       pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE;
+               }
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: STBC = %d\n", pAd->CommonCfg.RegTransmitSetting.field.STBC));
+       }
+
+       // 40_Mhz_Intolerant
+       if (RTMPGetKeyParameter("HT_40MHZ_INTOLERANT", pValueStr, 25, pInput))
+       {
+               Value = simple_strtol(pValueStr, 0, 10);
+               if (Value == 0)
+               {
+                       pAd->CommonCfg.bForty_Mhz_Intolerant = FALSE;
+               }
+               else
+               {
+                       pAd->CommonCfg.bForty_Mhz_Intolerant = TRUE;
+               }
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: 40MHZ INTOLERANT = %d\n", pAd->CommonCfg.bForty_Mhz_Intolerant));
+       }
+       //HT_TxStream
+       if(RTMPGetKeyParameter("HT_TxStream", pValueStr, 10, pInput))
+       {
+               switch (simple_strtol(pValueStr, 0, 10))
+               {
+                       case 1:
+                               pAd->CommonCfg.TxStream = 1;
+                               break;
+                       case 2:
+                               pAd->CommonCfg.TxStream = 2;
+                               break;
+                       case 3: // 3*3
+                       default:
+                               pAd->CommonCfg.TxStream = 3;
+
+                               if (pAd->MACVersion < RALINK_2883_VERSION)
+                                       pAd->CommonCfg.TxStream = 2; // only 2 tx streams for RT2860 series
+                               break;
+               }
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx Stream = %d\n", pAd->CommonCfg.TxStream));
+       }
+       //HT_RxStream
+       if(RTMPGetKeyParameter("HT_RxStream", pValueStr, 10, pInput))
+       {
+               switch (simple_strtol(pValueStr, 0, 10))
+               {
+                       case 1:
+                               pAd->CommonCfg.RxStream = 1;
+                               break;
+                       case 2:
+                               pAd->CommonCfg.RxStream = 2;
+                               break;
+                       case 3:
+                       default:
+                               pAd->CommonCfg.RxStream = 3;
+
+                               if (pAd->MACVersion < RALINK_2883_VERSION)
+                                       pAd->CommonCfg.RxStream = 2; // only 2 rx streams for RT2860 series
+                               break;
+               }
+               DBGPRINT(RT_DEBUG_TRACE, ("HT: Rx Stream = %d\n", pAd->CommonCfg.RxStream));
+       }
+
+}
+#endif // DOT11_N_SUPPORT //
+
diff --git a/drivers/staging/rt2870/rtmp.h b/drivers/staging/rt2870/rtmp.h
new file mode 100644 (file)
index 0000000..c2a4784
--- /dev/null
@@ -0,0 +1,7586 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    rtmp.h
+
+    Abstract:
+    Miniport generic portion header file
+
+    Revision History:
+    Who         When          What
+    --------    ----------    ----------------------------------------------
+    Paul Lin    2002-08-01    created
+    James Tan   2002-09-06    modified (Revise NTCRegTable)
+    John Chang  2004-09-06    modified for RT2600
+*/
+#ifndef __RTMP_H__
+#define __RTMP_H__
+
+#include "link_list.h"
+#include "spectrum_def.h"
+
+
+#ifdef CONFIG_STA_SUPPORT
+#include "aironet.h"
+#endif // CONFIG_STA_SUPPORT //
+
+//#define DBG          1
+
+//#define DBG_DIAGNOSE         1
+
+#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT)
+#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd)       if(_pAd->OpMode == OPMODE_AP)
+#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd)      if(_pAd->OpMode == OPMODE_STA)
+#else
+#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd)
+#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd)
+#endif
+
+#define VIRTUAL_IF_INC(__pAd) ((__pAd)->VirtualIfCnt++)
+#define VIRTUAL_IF_DEC(__pAd) ((__pAd)->VirtualIfCnt--)
+#define VIRTUAL_IF_NUM(__pAd) ((__pAd)->VirtualIfCnt)
+
+#ifdef RT2870
+////////////////////////////////////////////////////////////////////////////
+// The TX_BUFFER structure forms the transmitted USB packet to the device
+////////////////////////////////////////////////////////////////////////////
+typedef struct __TX_BUFFER{
+       union   {
+               UCHAR                   WirelessPacket[TX_BUFFER_NORMSIZE];
+               HEADER_802_11   NullFrame;
+               PSPOLL_FRAME    PsPollPacket;
+               RTS_FRAME               RTSFrame;
+       }field;
+       UCHAR                   Aggregation[4];  //Buffer for save Aggregation size.
+} TX_BUFFER, *PTX_BUFFER;
+
+typedef struct __HTTX_BUFFER{
+       union   {
+               UCHAR                   WirelessPacket[MAX_TXBULK_SIZE];
+               HEADER_802_11   NullFrame;
+               PSPOLL_FRAME    PsPollPacket;
+               RTS_FRAME               RTSFrame;
+       }field;
+       UCHAR                   Aggregation[4];  //Buffer for save Aggregation size.
+} HTTX_BUFFER, *PHTTX_BUFFER;
+
+
+// used to track driver-generated write irps
+typedef struct _TX_CONTEXT
+{
+       PVOID                   pAd;            //Initialized in MiniportInitialize
+       PURB                    pUrb;                   //Initialized in MiniportInitialize
+       PIRP                    pIrp;                   //used to cancel pending bulk out.
+                                                                       //Initialized in MiniportInitialize
+       PTX_BUFFER              TransferBuffer; //Initialized in MiniportInitialize
+       ULONG                   BulkOutSize;
+       UCHAR                   BulkOutPipeId;
+       UCHAR                   SelfIdx;
+       BOOLEAN                 InUse;
+       BOOLEAN                 bWaitingBulkOut; // at least one packet is in this TxContext, ready for making IRP anytime.
+       BOOLEAN                 bFullForBulkOut; // all tx buffer are full , so waiting for tx bulkout.
+       BOOLEAN                 IRPPending;
+       BOOLEAN                 LastOne;
+       BOOLEAN                 bAggregatible;
+       UCHAR                   Header_802_3[LENGTH_802_3];
+       UCHAR                   Rsv[2];
+       ULONG                   DataOffset;
+       UINT                    TxRate;
+       dma_addr_t              data_dma;               // urb dma on linux
+
+}      TX_CONTEXT, *PTX_CONTEXT, **PPTX_CONTEXT;
+
+
+// used to track driver-generated write irps
+typedef struct _HT_TX_CONTEXT
+{
+       PVOID                   pAd;            //Initialized in MiniportInitialize
+       PURB                    pUrb;                   //Initialized in MiniportInitialize
+       PIRP                    pIrp;                   //used to cancel pending bulk out.
+                                                                       //Initialized in MiniportInitialize
+       PHTTX_BUFFER    TransferBuffer; //Initialized in MiniportInitialize
+       ULONG                   BulkOutSize;    // Indicate the total bulk-out size in bytes in one bulk-transmission
+       UCHAR                   BulkOutPipeId;
+       BOOLEAN                 IRPPending;
+       BOOLEAN                 LastOne;
+       BOOLEAN                 bCurWriting;
+       BOOLEAN                 bRingEmpty;
+       BOOLEAN                 bCopySavePad;
+       UCHAR                   SavedPad[8];
+       UCHAR                   Header_802_3[LENGTH_802_3];
+       ULONG                   CurWritePosition;               // Indicate the buffer offset which packet will be inserted start from.
+       ULONG                   CurWriteRealPos;                // Indicate the buffer offset which packet now are writing to.
+       ULONG                   NextBulkOutPosition;    // Indicate the buffer start offset of a bulk-transmission
+       ULONG                   ENextBulkOutPosition;   // Indicate the buffer end offset of a bulk-transmission
+       UINT                    TxRate;
+       dma_addr_t              data_dma;               // urb dma on linux
+}      HT_TX_CONTEXT, *PHT_TX_CONTEXT, **PPHT_TX_CONTEXT;
+
+
+//
+// Structure to keep track of receive packets and buffers to indicate
+// receive data to the protocol.
+//
+typedef struct _RX_CONTEXT
+{
+       PUCHAR                          TransferBuffer;
+       PVOID                           pAd;
+       PIRP                            pIrp;//used to cancel pending bulk in.
+       PURB                            pUrb;
+       //These 2 Boolean shouldn't both be 1 at the same time.
+       ULONG                           BulkInOffset;   // number of packets waiting for reordering .
+//     BOOLEAN                         ReorderInUse;   // At least one packet in this buffer are in reordering buffer and wait for receive indication
+       BOOLEAN                         bRxHandling;    // Notify this packet is being process now.
+       BOOLEAN                         InUse;                  // USB Hardware Occupied. Wait for USB HW to put packet.
+       BOOLEAN                         Readable;               // Receive Complete back. OK for driver to indicate receiving packet.
+       BOOLEAN                         IRPPending;             // TODO: To be removed
+       atomic_t                        IrpLock;
+       NDIS_SPIN_LOCK          RxContextLock;
+       dma_addr_t                      data_dma;               // urb dma on linux
+}      RX_CONTEXT, *PRX_CONTEXT;
+#endif // RT2870 //
+
+
+//
+//  NDIS Version definitions
+//
+#ifdef  NDIS50_MINIPORT
+#define RTMP_NDIS_MAJOR_VERSION     5
+#define RTMP_NDIS_MINOR_VERSION     0
+#endif
+
+#ifdef  NDIS51_MINIPORT
+#define RTMP_NDIS_MAJOR_VERSION     5
+#define RTMP_NDIS_MINOR_VERSION     1
+#endif
+
+extern  char    NIC_VENDOR_DESC[];
+extern  int     NIC_VENDOR_DESC_LEN;
+
+extern  unsigned char   SNAP_AIRONET[];
+extern  unsigned char   CipherSuiteCiscoCCKM[];
+extern  unsigned char   CipherSuiteCiscoCCKMLen;
+extern unsigned char   CipherSuiteCiscoCCKM24[];
+extern unsigned char   CipherSuiteCiscoCCKM24Len;
+extern  unsigned char   CipherSuiteCCXTkip[];
+extern  unsigned char   CipherSuiteCCXTkipLen;
+extern  unsigned char   CISCO_OUI[];
+extern  UCHAR  BaSizeArray[4];
+
+extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN];
+extern UCHAR MULTICAST_ADDR[MAC_ADDR_LEN];
+extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN];
+extern ULONG BIT32[32];
+extern UCHAR BIT8[8];
+extern char* CipherName[];
+extern char* MCSToMbps[];
+extern UCHAR    RxwiMCSToOfdmRate[12];
+extern UCHAR SNAP_802_1H[6];
+extern UCHAR SNAP_BRIDGE_TUNNEL[6];
+extern UCHAR SNAP_AIRONET[8];
+extern UCHAR CKIP_LLC_SNAP[8];
+extern UCHAR EAPOL_LLC_SNAP[8];
+extern UCHAR EAPOL[2];
+extern UCHAR IPX[2];
+extern UCHAR APPLE_TALK[2];
+extern UCHAR RateIdToPlcpSignal[12]; // see IEEE802.11a-1999 p.14
+extern UCHAR    OfdmRateToRxwiMCS[];
+extern UCHAR OfdmSignalToRateId[16] ;
+extern UCHAR default_cwmin[4];
+extern UCHAR default_cwmax[4];
+extern UCHAR default_sta_aifsn[4];
+extern UCHAR MapUserPriorityToAccessCategory[8];
+
+extern USHORT RateUpPER[];
+extern USHORT RateDownPER[];
+extern UCHAR  Phy11BNextRateDownward[];
+extern UCHAR  Phy11BNextRateUpward[];
+extern UCHAR  Phy11BGNextRateDownward[];
+extern UCHAR  Phy11BGNextRateUpward[];
+extern UCHAR  Phy11ANextRateDownward[];
+extern UCHAR  Phy11ANextRateUpward[];
+extern CHAR   RssiSafeLevelForTxRate[];
+extern UCHAR  RateIdToMbps[];
+extern USHORT RateIdTo500Kbps[];
+
+extern UCHAR  CipherSuiteWpaNoneTkip[];
+extern UCHAR  CipherSuiteWpaNoneTkipLen;
+
+extern UCHAR  CipherSuiteWpaNoneAes[];
+extern UCHAR  CipherSuiteWpaNoneAesLen;
+
+extern UCHAR  SsidIe;
+extern UCHAR  SupRateIe;
+extern UCHAR  ExtRateIe;
+
+#ifdef DOT11_N_SUPPORT
+extern UCHAR  HtCapIe;
+extern UCHAR  AddHtInfoIe;
+extern UCHAR  NewExtChanIe;
+#ifdef DOT11N_DRAFT3
+extern UCHAR  ExtHtCapIe;
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+extern UCHAR  ErpIe;
+extern UCHAR  DsIe;
+extern UCHAR  TimIe;
+extern UCHAR  WpaIe;
+extern UCHAR  Wpa2Ie;
+extern UCHAR  IbssIe;
+extern UCHAR  Ccx2Ie;
+
+extern UCHAR  WPA_OUI[];
+extern UCHAR  RSN_OUI[];
+extern UCHAR  WME_INFO_ELEM[];
+extern UCHAR  WME_PARM_ELEM[];
+extern UCHAR  Ccx2QosInfo[];
+extern UCHAR  Ccx2IeInfo[];
+extern UCHAR  RALINK_OUI[];
+extern UCHAR  PowerConstraintIE[];
+
+
+extern UCHAR  RateSwitchTable[];
+extern UCHAR  RateSwitchTable11B[];
+extern UCHAR  RateSwitchTable11G[];
+extern UCHAR  RateSwitchTable11BG[];
+
+#ifdef DOT11_N_SUPPORT
+extern UCHAR  RateSwitchTable11BGN1S[];
+extern UCHAR  RateSwitchTable11BGN2S[];
+extern UCHAR  RateSwitchTable11BGN2SForABand[];
+extern UCHAR  RateSwitchTable11N1S[];
+extern UCHAR  RateSwitchTable11N2S[];
+extern UCHAR  RateSwitchTable11N2SForABand[];
+
+#ifdef CONFIG_STA_SUPPORT
+extern UCHAR  PRE_N_HT_OUI[];
+#endif // CONFIG_STA_SUPPORT //
+#endif // DOT11_N_SUPPORT //
+
+#define        MAXSEQ          (0xFFF)
+
+#ifdef RALINK_ATE
+typedef        struct _ATE_INFO {
+       UCHAR   Mode;
+       CHAR    TxPower0;
+       CHAR    TxPower1;
+       CHAR    TxAntennaSel;
+       CHAR    RxAntennaSel;
+       TXWI_STRUC  TxWI;         // TXWI
+       USHORT  QID;
+       UCHAR   Addr1[MAC_ADDR_LEN];
+       UCHAR   Addr2[MAC_ADDR_LEN];
+       UCHAR   Addr3[MAC_ADDR_LEN];
+       UCHAR   Channel;
+       UINT32  TxLength;
+       UINT32  TxCount;
+       UINT32  TxDoneCount; // Tx DMA Done
+       UINT32  RFFreqOffset;
+       BOOLEAN bRxFer;
+       BOOLEAN bQATxStart; // Have compiled QA in and use it to ATE tx.
+       BOOLEAN bQARxStart;     // Have compiled QA in and use it to ATE rx.
+       UINT32  RxTotalCnt;
+       UINT32  RxCntPerSec;
+
+       CHAR    LastSNR0;             // last received SNR
+       CHAR    LastSNR1;             // last received SNR for 2nd  antenna
+       CHAR    LastRssi0;            // last received RSSI
+       CHAR    LastRssi1;            // last received RSSI for 2nd  antenna
+       CHAR    LastRssi2;            // last received RSSI for 3rd  antenna
+       CHAR    AvgRssi0;             // last 8 frames' average RSSI
+       CHAR    AvgRssi1;             // last 8 frames' average RSSI
+       CHAR    AvgRssi2;             // last 8 frames' average RSSI
+       SHORT   AvgRssi0X8;           // sum of last 8 frames' RSSI
+       SHORT   AvgRssi1X8;           // sum of last 8 frames' RSSI
+       SHORT   AvgRssi2X8;           // sum of last 8 frames' RSSI
+
+       UINT32  NumOfAvgRssiSample;
+
+#ifdef RALINK_28xx_QA
+       // Tx frame
+#ifdef RT2870
+       /* not used in RT2860 */
+       TXINFO_STRUC            TxInfo; // TxInfo
+#endif // RT2870 //
+       USHORT          HLen; // Header Length
+       USHORT          PLen; // Pattern Length
+       UCHAR           Header[32]; // Header buffer
+       UCHAR           Pattern[32]; // Pattern buffer
+       USHORT          DLen; // Data Length
+       USHORT          seq;
+       UINT32          CID;
+       THREAD_PID              AtePid;
+       // counters
+       UINT32          U2M;
+       UINT32          OtherData;
+       UINT32          Beacon;
+       UINT32          OtherCount;
+       UINT32          TxAc0;
+       UINT32          TxAc1;
+       UINT32          TxAc2;
+       UINT32          TxAc3;
+       UINT32          TxHCCA;
+       UINT32          TxMgmt;
+       UINT32          RSSI0;
+       UINT32          RSSI1;
+       UINT32          RSSI2;
+       UINT32          SNR0;
+       UINT32          SNR1;
+       // control
+       //UINT32                Repeat; // Tx Cpu count
+       UCHAR           TxStatus; // task Tx status // 0 --> task is idle, 1 --> task is running
+#endif // RALINK_28xx_QA //
+}      ATE_INFO, *PATE_INFO;
+
+#ifdef RALINK_28xx_QA
+struct ate_racfghdr {
+       UINT32          magic_no;
+       USHORT          command_type;
+       USHORT          command_id;
+       USHORT          length;
+       USHORT          sequence;
+       USHORT          status;
+       UCHAR           data[2046];
+}  __attribute__((packed));
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+#ifdef DOT11_N_SUPPORT
+struct reordering_mpdu
+{
+       struct reordering_mpdu  *next;
+       PNDIS_PACKET                    pPacket;                /* coverted to 802.3 frame */
+       int                                             Sequence;               /* sequence number of MPDU */
+       BOOLEAN                                 bAMSDU;
+};
+
+struct reordering_list
+{
+       struct reordering_mpdu *next;
+       int     qlen;
+};
+
+struct reordering_mpdu_pool
+{
+       PVOID                                   mem;
+       NDIS_SPIN_LOCK                  lock;
+       struct reordering_list  freelist;
+};
+#endif // DOT11_N_SUPPORT //
+
+typedef struct         _RSSI_SAMPLE {
+       CHAR                    LastRssi0;             // last received RSSI
+       CHAR                    LastRssi1;             // last received RSSI
+       CHAR                    LastRssi2;             // last received RSSI
+       CHAR                    AvgRssi0;
+       CHAR                    AvgRssi1;
+       CHAR                    AvgRssi2;
+       SHORT                   AvgRssi0X8;
+       SHORT                   AvgRssi1X8;
+       SHORT                   AvgRssi2X8;
+} RSSI_SAMPLE;
+
+//
+//  Queue structure and macros
+//
+typedef struct  _QUEUE_ENTRY    {
+       struct _QUEUE_ENTRY     *Next;
+}   QUEUE_ENTRY, *PQUEUE_ENTRY;
+
+// Queue structure
+typedef struct  _QUEUE_HEADER   {
+       PQUEUE_ENTRY    Head;
+       PQUEUE_ENTRY    Tail;
+       ULONG           Number;
+}   QUEUE_HEADER, *PQUEUE_HEADER;
+
+#define InitializeQueueHeader(QueueHeader)              \
+{                                                       \
+       (QueueHeader)->Head = (QueueHeader)->Tail = NULL;   \
+       (QueueHeader)->Number = 0;                          \
+}
+
+#define RemoveHeadQueue(QueueHeader)                \
+(QueueHeader)->Head;                                \
+{                                                   \
+       PQUEUE_ENTRY pNext;                             \
+       if ((QueueHeader)->Head != NULL)                                \
+       {                                                                                               \
+               pNext = (QueueHeader)->Head->Next;          \
+               (QueueHeader)->Head = pNext;                \
+               if (pNext == NULL)                          \
+                       (QueueHeader)->Tail = NULL;             \
+               (QueueHeader)->Number--;                    \
+       }                                                                                               \
+}
+
+#define InsertHeadQueue(QueueHeader, QueueEntry)            \
+{                                                           \
+               ((PQUEUE_ENTRY)QueueEntry)->Next = (QueueHeader)->Head; \
+               (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry);       \
+               if ((QueueHeader)->Tail == NULL)                        \
+                       (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry);   \
+               (QueueHeader)->Number++;                                \
+}
+
+#define InsertTailQueue(QueueHeader, QueueEntry)                \
+{                                                               \
+       ((PQUEUE_ENTRY)QueueEntry)->Next = NULL;                    \
+       if ((QueueHeader)->Tail)                                    \
+               (QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(QueueEntry); \
+       else                                                        \
+               (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry);       \
+       (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry);           \
+       (QueueHeader)->Number++;                                    \
+}
+
+//
+//  Macros for flag and ref count operations
+//
+#define RTMP_SET_FLAG(_M, _F)       ((_M)->Flags |= (_F))
+#define RTMP_CLEAR_FLAG(_M, _F)     ((_M)->Flags &= ~(_F))
+#define RTMP_CLEAR_FLAGS(_M)        ((_M)->Flags = 0)
+#define RTMP_TEST_FLAG(_M, _F)      (((_M)->Flags & (_F)) != 0)
+#define RTMP_TEST_FLAGS(_M, _F)     (((_M)->Flags & (_F)) == (_F))
+
+#define OPSTATUS_SET_FLAG(_pAd, _F)     ((_pAd)->CommonCfg.OpStatusFlags |= (_F))
+#define OPSTATUS_CLEAR_FLAG(_pAd, _F)   ((_pAd)->CommonCfg.OpStatusFlags &= ~(_F))
+#define OPSTATUS_TEST_FLAG(_pAd, _F)    (((_pAd)->CommonCfg.OpStatusFlags & (_F)) != 0)
+
+#define CLIENT_STATUS_SET_FLAG(_pEntry,_F)      ((_pEntry)->ClientStatusFlags |= (_F))
+#define CLIENT_STATUS_CLEAR_FLAG(_pEntry,_F)    ((_pEntry)->ClientStatusFlags &= ~(_F))
+#define CLIENT_STATUS_TEST_FLAG(_pEntry,_F)     (((_pEntry)->ClientStatusFlags & (_F)) != 0)
+
+#define RX_FILTER_SET_FLAG(_pAd, _F)    ((_pAd)->CommonCfg.PacketFilter |= (_F))
+#define RX_FILTER_CLEAR_FLAG(_pAd, _F)  ((_pAd)->CommonCfg.PacketFilter &= ~(_F))
+#define RX_FILTER_TEST_FLAG(_pAd, _F)   (((_pAd)->CommonCfg.PacketFilter & (_F)) != 0)
+
+#ifdef CONFIG_STA_SUPPORT
+#define STA_NO_SECURITY_ON(_p)          (_p->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
+#define STA_WEP_ON(_p)                  (_p->StaCfg.WepStatus == Ndis802_11Encryption1Enabled)
+#define STA_TKIP_ON(_p)                 (_p->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)
+#define STA_AES_ON(_p)                  (_p->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+
+#define STA_TGN_WIFI_ON(_p)             (_p->StaCfg.bTGnWifiTest == TRUE)
+#endif // CONFIG_STA_SUPPORT //
+
+#define CKIP_KP_ON(_p)                         ((((_p)->StaCfg.CkipFlag) & 0x10) && ((_p)->StaCfg.bCkipCmicOn == TRUE))
+#define CKIP_CMIC_ON(_p)                       ((((_p)->StaCfg.CkipFlag) & 0x08) && ((_p)->StaCfg.bCkipCmicOn == TRUE))
+
+
+#define INC_RING_INDEX(_idx, _RingSize)    \
+{                                          \
+    (_idx) = (_idx+1) % (_RingSize);       \
+}
+
+#define IS_RT3070(_pAd)                                (((_pAd)->MACVersion & 0xffff0000) == 0x30700000)
+
+#define RING_PACKET_INIT(_TxRing, _idx)    \
+{                                          \
+    _TxRing->Cell[_idx].pNdisPacket = NULL;                              \
+    _TxRing->Cell[_idx].pNextNdisPacket = NULL;                              \
+}
+
+#define TXDT_INIT(_TxD)    \
+{                                          \
+       NdisZeroMemory(_TxD, TXD_SIZE); \
+       _TxD->DMADONE = 1;                              \
+}
+
+//Set last data segment
+#define RING_SET_LASTDS(_TxD, _IsSD0)    \
+{                                          \
+    if (_IsSD0) {_TxD->LastSec0 = 1;}     \
+    else {_TxD->LastSec1 = 1;}     \
+}
+
+// Increase TxTsc value for next transmission
+// TODO:
+// When i==6, means TSC has done one full cycle, do re-keying stuff follow specs
+// Should send a special event microsoft defined to request re-key
+#define INC_TX_TSC(_tsc)                                \
+{                                                       \
+    int i=0;                                            \
+    while (++_tsc[i] == 0x0)                            \
+    {                                                   \
+        i++;                                            \
+        if (i == 6)                                     \
+            break;                                      \
+    }                                                   \
+}
+
+#ifdef DOT11_N_SUPPORT
+// StaActive.SupportedHtPhy.MCSSet is copied from AP beacon.  Don't need to update here.
+#define COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd)                                 \
+{                                                                                       \
+       _pAd->StaActive.SupportedHtPhy.ChannelWidth = _pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth;      \
+       _pAd->StaActive.SupportedHtPhy.MimoPs = _pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs;      \
+       _pAd->StaActive.SupportedHtPhy.GF = _pAd->MlmeAux.HtCapability.HtCapInfo.GF;      \
+       _pAd->StaActive.SupportedHtPhy.ShortGIfor20 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20;      \
+       _pAd->StaActive.SupportedHtPhy.ShortGIfor40 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40;      \
+       _pAd->StaActive.SupportedHtPhy.TxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC;      \
+       _pAd->StaActive.SupportedHtPhy.RxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC;      \
+       _pAd->StaActive.SupportedHtPhy.ExtChanOffset = _pAd->MlmeAux.AddHtInfo.AddHtInfo.ExtChanOffset;      \
+       _pAd->StaActive.SupportedHtPhy.RecomWidth = _pAd->MlmeAux.AddHtInfo.AddHtInfo.RecomWidth;      \
+       _pAd->StaActive.SupportedHtPhy.OperaionMode = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode;      \
+       _pAd->StaActive.SupportedHtPhy.NonGfPresent = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent;      \
+       NdisMoveMemory((_pAd)->MacTab.Content[BSSID_WCID].HTCapability.MCSSet, (_pAd)->StaActive.SupportedPhyInfo.MCSSet, sizeof(UCHAR) * 16);\
+}
+
+#define COPY_AP_HTSETTINGS_FROM_BEACON(_pAd, _pHtCapability)                                 \
+{                                                                                       \
+       _pAd->MacTab.Content[BSSID_WCID].AMsduSize = (UCHAR)(_pHtCapability->HtCapInfo.AMsduSize);      \
+       _pAd->MacTab.Content[BSSID_WCID].MmpsMode= (UCHAR)(_pHtCapability->HtCapInfo.MimoPs);   \
+       _pAd->MacTab.Content[BSSID_WCID].MaxRAmpduFactor = (UCHAR)(_pHtCapability->HtCapParm.MaxRAmpduFactor);  \
+}
+#endif // DOT11_N_SUPPORT //
+
+//
+// BBP & RF are using indirect access. Before write any value into it.
+// We have to make sure there is no outstanding command pending via checking busy bit.
+//
+#define MAX_BUSY_COUNT  100         // Number of retry before failing access BBP & RF indirect register
+//
+
+#ifdef RT2870
+#define RTMP_RF_IO_WRITE32(_A, _V)                 RTUSBWriteRFRegister(_A, _V)
+#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV)   RTUSBReadBBPRegister(_A, _I, _pV)
+#define RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V)   RTUSBWriteBBPRegister(_A, _I, _V)
+
+#define BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V)                    RTUSBWriteBBPRegister(_A, _I, _V)
+#define BBP_IO_READ8_BY_REG_ID(_A, _I, _pV)            RTUSBReadBBPRegister(_A, _I, _pV)
+#endif // RT2870 //
+
+#define     MAP_CHANNEL_ID_TO_KHZ(ch, khz)  {               \
+                switch (ch)                                 \
+                {                                           \
+                    case 1:     khz = 2412000;   break;     \
+                    case 2:     khz = 2417000;   break;     \
+                    case 3:     khz = 2422000;   break;     \
+                    case 4:     khz = 2427000;   break;     \
+                    case 5:     khz = 2432000;   break;     \
+                    case 6:     khz = 2437000;   break;     \
+                    case 7:     khz = 2442000;   break;     \
+                    case 8:     khz = 2447000;   break;     \
+                    case 9:     khz = 2452000;   break;     \
+                    case 10:    khz = 2457000;   break;     \
+                    case 11:    khz = 2462000;   break;     \
+                    case 12:    khz = 2467000;   break;     \
+                    case 13:    khz = 2472000;   break;     \
+                    case 14:    khz = 2484000;   break;     \
+                    case 36:  /* UNII */  khz = 5180000;   break;     \
+                    case 40:  /* UNII */  khz = 5200000;   break;     \
+                    case 44:  /* UNII */  khz = 5220000;   break;     \
+                    case 48:  /* UNII */  khz = 5240000;   break;     \
+                    case 52:  /* UNII */  khz = 5260000;   break;     \
+                    case 56:  /* UNII */  khz = 5280000;   break;     \
+                    case 60:  /* UNII */  khz = 5300000;   break;     \
+                    case 64:  /* UNII */  khz = 5320000;   break;     \
+                    case 149: /* UNII */  khz = 5745000;   break;     \
+                    case 153: /* UNII */  khz = 5765000;   break;     \
+                    case 157: /* UNII */  khz = 5785000;   break;     \
+                    case 161: /* UNII */  khz = 5805000;   break;     \
+                    case 165: /* UNII */  khz = 5825000;   break;     \
+                    case 100: /* HiperLAN2 */  khz = 5500000;   break;     \
+                    case 104: /* HiperLAN2 */  khz = 5520000;   break;     \
+                    case 108: /* HiperLAN2 */  khz = 5540000;   break;     \
+                    case 112: /* HiperLAN2 */  khz = 5560000;   break;     \
+                    case 116: /* HiperLAN2 */  khz = 5580000;   break;     \
+                    case 120: /* HiperLAN2 */  khz = 5600000;   break;     \
+                    case 124: /* HiperLAN2 */  khz = 5620000;   break;     \
+                    case 128: /* HiperLAN2 */  khz = 5640000;   break;     \
+                    case 132: /* HiperLAN2 */  khz = 5660000;   break;     \
+                    case 136: /* HiperLAN2 */  khz = 5680000;   break;     \
+                    case 140: /* HiperLAN2 */  khz = 5700000;   break;     \
+                    case 34:  /* Japan MMAC */   khz = 5170000;   break;   \
+                    case 38:  /* Japan MMAC */   khz = 5190000;   break;   \
+                    case 42:  /* Japan MMAC */   khz = 5210000;   break;   \
+                    case 46:  /* Japan MMAC */   khz = 5230000;   break;   \
+                    case 184: /* Japan */   khz = 4920000;   break;   \
+                    case 188: /* Japan */   khz = 4940000;   break;   \
+                    case 192: /* Japan */   khz = 4960000;   break;   \
+                    case 196: /* Japan */   khz = 4980000;   break;   \
+                    case 208: /* Japan, means J08 */   khz = 5040000;   break;   \
+                    case 212: /* Japan, means J12 */   khz = 5060000;   break;   \
+                    case 216: /* Japan, means J16 */   khz = 5080000;   break;   \
+                    default:    khz = 2412000;   break;     \
+                }                                           \
+            }
+
+#define     MAP_KHZ_TO_CHANNEL_ID(khz, ch)  {               \
+                switch (khz)                                \
+                {                                           \
+                    case 2412000:    ch = 1;     break;     \
+                    case 2417000:    ch = 2;     break;     \
+                    case 2422000:    ch = 3;     break;     \
+                    case 2427000:    ch = 4;     break;     \
+                    case 2432000:    ch = 5;     break;     \
+                    case 2437000:    ch = 6;     break;     \
+                    case 2442000:    ch = 7;     break;     \
+                    case 2447000:    ch = 8;     break;     \
+                    case 2452000:    ch = 9;     break;     \
+                    case 2457000:    ch = 10;    break;     \
+                    case 2462000:    ch = 11;    break;     \
+                    case 2467000:    ch = 12;    break;     \
+                    case 2472000:    ch = 13;    break;     \
+                    case 2484000:    ch = 14;    break;     \
+                    case 5180000:    ch = 36;  /* UNII */  break;     \
+                    case 5200000:    ch = 40;  /* UNII */  break;     \
+                    case 5220000:    ch = 44;  /* UNII */  break;     \
+                    case 5240000:    ch = 48;  /* UNII */  break;     \
+                    case 5260000:    ch = 52;  /* UNII */  break;     \
+                    case 5280000:    ch = 56;  /* UNII */  break;     \
+                    case 5300000:    ch = 60;  /* UNII */  break;     \
+                    case 5320000:    ch = 64;  /* UNII */  break;     \
+                    case 5745000:    ch = 149; /* UNII */  break;     \
+                    case 5765000:    ch = 153; /* UNII */  break;     \
+                    case 5785000:    ch = 157; /* UNII */  break;     \
+                    case 5805000:    ch = 161; /* UNII */  break;     \
+                    case 5825000:    ch = 165; /* UNII */  break;     \
+                    case 5500000:    ch = 100; /* HiperLAN2 */  break;     \
+                    case 5520000:    ch = 104; /* HiperLAN2 */  break;     \
+                    case 5540000:    ch = 108; /* HiperLAN2 */  break;     \
+                    case 5560000:    ch = 112; /* HiperLAN2 */  break;     \
+                    case 5580000:    ch = 116; /* HiperLAN2 */  break;     \
+                    case 5600000:    ch = 120; /* HiperLAN2 */  break;     \
+                    case 5620000:    ch = 124; /* HiperLAN2 */  break;     \
+                    case 5640000:    ch = 128; /* HiperLAN2 */  break;     \
+                    case 5660000:    ch = 132; /* HiperLAN2 */  break;     \
+                    case 5680000:    ch = 136; /* HiperLAN2 */  break;     \
+                    case 5700000:    ch = 140; /* HiperLAN2 */  break;     \
+                    case 5170000:    ch = 34;  /* Japan MMAC */   break;   \
+                    case 5190000:    ch = 38;  /* Japan MMAC */   break;   \
+                    case 5210000:    ch = 42;  /* Japan MMAC */   break;   \
+                    case 5230000:    ch = 46;  /* Japan MMAC */   break;   \
+                    case 4920000:    ch = 184; /* Japan */  break;   \
+                    case 4940000:    ch = 188; /* Japan */  break;   \
+                    case 4960000:    ch = 192; /* Japan */  break;   \
+                    case 4980000:    ch = 196; /* Japan */  break;   \
+                    case 5040000:    ch = 208; /* Japan, means J08 */  break;   \
+                    case 5060000:    ch = 212; /* Japan, means J12 */  break;   \
+                    case 5080000:    ch = 216; /* Japan, means J16 */  break;   \
+                    default:         ch = 1;     break;     \
+                }                                           \
+            }
+
+//
+// Common fragment list structure -  Identical to the scatter gather frag list structure
+//
+//#define RTMP_SCATTER_GATHER_ELEMENT         SCATTER_GATHER_ELEMENT
+//#define PRTMP_SCATTER_GATHER_ELEMENT        PSCATTER_GATHER_ELEMENT
+#define NIC_MAX_PHYS_BUF_COUNT              8
+
+typedef struct _RTMP_SCATTER_GATHER_ELEMENT {
+    PVOID              Address;
+    ULONG              Length;
+    PULONG             Reserved;
+} RTMP_SCATTER_GATHER_ELEMENT, *PRTMP_SCATTER_GATHER_ELEMENT;
+
+
+typedef struct _RTMP_SCATTER_GATHER_LIST {
+    ULONG  NumberOfElements;
+    PULONG Reserved;
+    RTMP_SCATTER_GATHER_ELEMENT Elements[NIC_MAX_PHYS_BUF_COUNT];
+} RTMP_SCATTER_GATHER_LIST, *PRTMP_SCATTER_GATHER_LIST;
+
+//
+//  Some utility macros
+//
+#ifndef min
+#define min(_a, _b)     (((_a) < (_b)) ? (_a) : (_b))
+#endif
+
+#ifndef max
+#define max(_a, _b)     (((_a) > (_b)) ? (_a) : (_b))
+#endif
+
+#define GET_LNA_GAIN(_pAd)     ((_pAd->LatchRfRegs.Channel <= 14) ? (_pAd->BLNAGain) : ((_pAd->LatchRfRegs.Channel <= 64) ? (_pAd->ALNAGain0) : ((_pAd->LatchRfRegs.Channel <= 128) ? (_pAd->ALNAGain1) : (_pAd->ALNAGain2))))
+
+#define INC_COUNTER64(Val)          (Val.QuadPart++)
+
+#define INFRA_ON(_p)                (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_INFRA_ON))
+#define ADHOC_ON(_p)                (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_ADHOC_ON))
+#define MONITOR_ON(_p)              (((_p)->StaCfg.BssType) == BSS_MONITOR)
+#define IDLE_ON(_p)                 (!INFRA_ON(_p) && !ADHOC_ON(_p))
+
+// Check LEAP & CCKM flags
+#define LEAP_ON(_p)                 (((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP)
+#define LEAP_CCKM_ON(_p)            ((((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) && ((_p)->StaCfg.LeapAuthInfo.CCKM == TRUE))
+
+// if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required
+#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(_pBufVA, _pExtraLlcSnapEncap)               \
+{                                                                                                                              \
+       if (((*(_pBufVA + 12) << 8) + *(_pBufVA + 13)) > 1500)          \
+       {                                                                                                                       \
+               _pExtraLlcSnapEncap = SNAP_802_1H;                                              \
+               if (NdisEqualMemory(IPX, _pBufVA + 12, 2) ||                    \
+                       NdisEqualMemory(APPLE_TALK, _pBufVA + 12, 2))           \
+               {                                                                                                               \
+                       _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL;                       \
+               }                                                                                                               \
+       }                                                                                                                       \
+       else                                                                                                            \
+       {                                                                                                                       \
+               _pExtraLlcSnapEncap = NULL;                                                             \
+       }                                                                                                                       \
+}
+
+// New Define for new Tx Path.
+#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(_pBufVA, _pExtraLlcSnapEncap)      \
+{                                                                                                                              \
+       if (((*(_pBufVA) << 8) + *(_pBufVA + 1)) > 1500)                        \
+       {                                                                                                                       \
+               _pExtraLlcSnapEncap = SNAP_802_1H;                                              \
+               if (NdisEqualMemory(IPX, _pBufVA, 2) ||                                 \
+                       NdisEqualMemory(APPLE_TALK, _pBufVA, 2))                        \
+               {                                                                                                               \
+                       _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL;                       \
+               }                                                                                                               \
+       }                                                                                                                       \
+       else                                                                                                            \
+       {                                                                                                                       \
+               _pExtraLlcSnapEncap = NULL;                                                             \
+       }                                                                                                                       \
+}
+
+
+#define MAKE_802_3_HEADER(_p, _pMac1, _pMac2, _pType)                   \
+{                                                                       \
+    NdisMoveMemory(_p, _pMac1, MAC_ADDR_LEN);                           \
+    NdisMoveMemory((_p + MAC_ADDR_LEN), _pMac2, MAC_ADDR_LEN);          \
+    NdisMoveMemory((_p + MAC_ADDR_LEN * 2), _pType, LENGTH_802_3_TYPE); \
+}
+
+// if pData has no LLC/SNAP (neither RFC1042 nor Bridge tunnel), keep it that way.
+// else if the received frame is LLC/SNAP-encaped IPX or APPLETALK, preserve the LLC/SNAP field
+// else remove the LLC/SNAP field from the result Ethernet frame
+// Patch for WHQL only, which did not turn on Netbios but use IPX within its payload
+// Note:
+//     _pData & _DataSize may be altered (remove 8-byte LLC/SNAP) by this MACRO
+//     _pRemovedLLCSNAP: pointer to removed LLC/SNAP; NULL is not removed
+#define CONVERT_TO_802_3(_p8023hdr, _pDA, _pSA, _pData, _DataSize, _pRemovedLLCSNAP)      \
+{                                                                       \
+    char LLC_Len[2];                                                    \
+                                                                        \
+    _pRemovedLLCSNAP = NULL;                                            \
+    if (NdisEqualMemory(SNAP_802_1H, _pData, 6)  ||                     \
+        NdisEqualMemory(SNAP_BRIDGE_TUNNEL, _pData, 6))                 \
+    {                                                                   \
+        PUCHAR pProto = _pData + 6;                                     \
+                                                                        \
+        if ((NdisEqualMemory(IPX, pProto, 2) || NdisEqualMemory(APPLE_TALK, pProto, 2)) &&  \
+            NdisEqualMemory(SNAP_802_1H, _pData, 6))                    \
+        {                                                               \
+            LLC_Len[0] = (UCHAR)(_DataSize / 256);                      \
+            LLC_Len[1] = (UCHAR)(_DataSize % 256);                      \
+            MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len);          \
+        }                                                               \
+        else                                                            \
+        {                                                               \
+            MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, pProto);           \
+            _pRemovedLLCSNAP = _pData;                                  \
+            _DataSize -= LENGTH_802_1_H;                                \
+            _pData += LENGTH_802_1_H;                                   \
+        }                                                               \
+    }                                                                   \
+    else                                                                \
+    {                                                                   \
+        LLC_Len[0] = (UCHAR)(_DataSize / 256);                          \
+        LLC_Len[1] = (UCHAR)(_DataSize % 256);                          \
+        MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len);              \
+    }                                                                   \
+}
+
+#define SWITCH_AB( _pAA, _pBB)    \
+{                                                                           \
+    PVOID pCC;                                                          \
+    pCC = _pBB;                                                 \
+    _pBB = _pAA;                                                 \
+    _pAA = pCC;                                                 \
+}
+
+// Enqueue this frame to MLME engine
+// We need to enqueue the whole frame because MLME need to pass data type
+// information from 802.11 header
+#ifdef RT2870
+#define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, _PlcpSignal)        \
+{                                                                                       \
+    UINT32 High32TSF=0, Low32TSF=0;                                                          \
+    MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (UCHAR)_Rssi0, (UCHAR)_Rssi1,(UCHAR)_Rssi2,_FrameSize, _pFrame, (UCHAR)_PlcpSignal);   \
+}
+#endif // RT2870 //
+
+#define NDIS_QUERY_BUFFER(_NdisBuf, _ppVA, _pBufLen)                    \
+    NdisQueryBuffer(_NdisBuf, _ppVA, _pBufLen)
+
+#define MAC_ADDR_EQUAL(pAddr1,pAddr2)           RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), MAC_ADDR_LEN)
+#define SSID_EQUAL(ssid1, len1, ssid2, len2)    ((len1==len2) && (RTMPEqualMemory(ssid1, ssid2, len1)))
+
+//
+// Check if it is Japan W53(ch52,56,60,64) channel.
+//
+#define JapanChannelCheck(channel)  ((channel == 52) || (channel == 56) || (channel == 60) || (channel == 64))
+
+#ifdef CONFIG_STA_SUPPORT
+#define STA_PORT_SECURED(_pAd) \
+{ \
+       _pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; \
+       NdisAcquireSpinLock(&_pAd->MacTabLock); \
+       _pAd->MacTab.Content[BSSID_WCID].PortSecured = _pAd->StaCfg.PortSecured; \
+       NdisReleaseSpinLock(&_pAd->MacTabLock); \
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+//
+// Register set pair for initialzation register set definition
+//
+typedef struct  _RTMP_REG_PAIR
+{
+       ULONG   Register;
+       ULONG   Value;
+} RTMP_REG_PAIR, *PRTMP_REG_PAIR;
+
+typedef struct  _REG_PAIR
+{
+       UCHAR   Register;
+       UCHAR   Value;
+} REG_PAIR, *PREG_PAIR;
+
+//
+// Register set pair for initialzation register set definition
+//
+typedef struct  _RTMP_RF_REGS
+{
+       UCHAR   Channel;
+       ULONG   R1;
+       ULONG   R2;
+       ULONG   R3;
+       ULONG   R4;
+} RTMP_RF_REGS, *PRTMP_RF_REGS;
+
+typedef struct _FREQUENCY_ITEM {
+       UCHAR   Channel;
+       UCHAR   N;
+       UCHAR   R;
+       UCHAR   K;
+} FREQUENCY_ITEM, *PFREQUENCY_ITEM;
+
+//
+//  Data buffer for DMA operation, the buffer must be contiguous physical memory
+//  Both DMA to / from CPU use the same structure.
+//
+typedef struct  _RTMP_DMABUF
+{
+       ULONG                   AllocSize;
+       PVOID                   AllocVa;            // TxBuf virtual address
+       NDIS_PHYSICAL_ADDRESS   AllocPa;            // TxBuf physical address
+} RTMP_DMABUF, *PRTMP_DMABUF;
+
+
+typedef        union   _HEADER_802_11_SEQ{
+#ifdef RT_BIG_ENDIAN
+    struct {
+       USHORT                  Sequence:12;
+       USHORT                  Frag:4;
+    }   field;
+#else
+    struct {
+       USHORT                  Frag:4;
+       USHORT                  Sequence:12;
+    }   field;
+#endif
+    USHORT           value;
+}      HEADER_802_11_SEQ, *PHEADER_802_11_SEQ;
+
+//
+//  Data buffer for DMA operation, the buffer must be contiguous physical memory
+//  Both DMA to / from CPU use the same structure.
+//
+typedef struct  _RTMP_REORDERBUF
+{
+       BOOLEAN                 IsFull;
+       PVOID                   AllocVa;            // TxBuf virtual address
+       UCHAR                   Header802_3[14];
+       HEADER_802_11_SEQ                       Sequence;       //support compressed bitmap BA, so no consider fragment in BA
+       UCHAR           DataOffset;
+       USHORT          Datasize;
+       ULONG                   AllocSize;
+#ifdef RT2870
+       PUCHAR                                  AllocPa;
+#endif // RT2870 //
+}   RTMP_REORDERBUF, *PRTMP_REORDERBUF;
+
+//
+// Control block (Descriptor) for all ring descriptor DMA operation, buffer must be
+// contiguous physical memory. NDIS_PACKET stored the binding Rx packet descriptor
+// which won't be released, driver has to wait until upper layer return the packet
+// before giveing up this rx ring descriptor to ASIC. NDIS_BUFFER is assocaited pair
+// to describe the packet buffer. For Tx, NDIS_PACKET stored the tx packet descriptor
+// which driver should ACK upper layer when the tx is physically done or failed.
+//
+typedef struct _RTMP_DMACB
+{
+       ULONG                   AllocSize;          // Control block size
+       PVOID                   AllocVa;            // Control block virtual address
+       NDIS_PHYSICAL_ADDRESS   AllocPa;            // Control block physical address
+       PNDIS_PACKET pNdisPacket;
+       PNDIS_PACKET pNextNdisPacket;
+
+       RTMP_DMABUF             DmaBuf;             // Associated DMA buffer structure
+} RTMP_DMACB, *PRTMP_DMACB;
+
+typedef struct _RTMP_TX_BUF
+{
+       PQUEUE_ENTRY    Next;
+       UCHAR           Index;
+       ULONG                   AllocSize;          // Control block size
+       PVOID                   AllocVa;            // Control block virtual address
+       NDIS_PHYSICAL_ADDRESS   AllocPa;            // Control block physical address
+} RTMP_TXBUF, *PRTMP_TXBUF;
+
+typedef struct _RTMP_RX_BUF
+{
+       BOOLEAN           InUse;
+       ULONG                   ByBaRecIndex;
+       RTMP_REORDERBUF MAP_RXBuf[MAX_RX_REORDERBUF];
+} RTMP_RXBUF, *PRTMP_RXBUF;
+typedef struct _RTMP_TX_RING
+{
+       RTMP_DMACB  Cell[TX_RING_SIZE];
+       UINT32          TxCpuIdx;
+       UINT32          TxDmaIdx;
+       UINT32          TxSwFreeIdx;    // software next free tx index
+} RTMP_TX_RING, *PRTMP_TX_RING;
+
+typedef struct _RTMP_RX_RING
+{
+       RTMP_DMACB  Cell[RX_RING_SIZE];
+       UINT32          RxCpuIdx;
+       UINT32          RxDmaIdx;
+       INT32           RxSwReadIdx;    // software next read index
+} RTMP_RX_RING, *PRTMP_RX_RING;
+
+typedef struct _RTMP_MGMT_RING
+{
+       RTMP_DMACB  Cell[MGMT_RING_SIZE];
+       UINT32          TxCpuIdx;
+       UINT32          TxDmaIdx;
+       UINT32          TxSwFreeIdx; // software next free tx index
+} RTMP_MGMT_RING, *PRTMP_MGMT_RING;
+
+//
+//  Statistic counter structure
+//
+typedef struct _COUNTER_802_3
+{
+       // General Stats
+       ULONG       GoodTransmits;
+       ULONG       GoodReceives;
+       ULONG       TxErrors;
+       ULONG       RxErrors;
+       ULONG       RxNoBuffer;
+
+       // Ethernet Stats
+       ULONG       RcvAlignmentErrors;
+       ULONG       OneCollision;
+       ULONG       MoreCollisions;
+
+} COUNTER_802_3, *PCOUNTER_802_3;
+
+typedef struct _COUNTER_802_11 {
+       ULONG           Length;
+       LARGE_INTEGER   LastTransmittedFragmentCount;
+       LARGE_INTEGER   TransmittedFragmentCount;
+       LARGE_INTEGER   MulticastTransmittedFrameCount;
+       LARGE_INTEGER   FailedCount;
+       LARGE_INTEGER   RetryCount;
+       LARGE_INTEGER   MultipleRetryCount;
+       LARGE_INTEGER   RTSSuccessCount;
+       LARGE_INTEGER   RTSFailureCount;
+       LARGE_INTEGER   ACKFailureCount;
+       LARGE_INTEGER   FrameDuplicateCount;
+       LARGE_INTEGER   ReceivedFragmentCount;
+       LARGE_INTEGER   MulticastReceivedFrameCount;
+       LARGE_INTEGER   FCSErrorCount;
+} COUNTER_802_11, *PCOUNTER_802_11;
+
+typedef struct _COUNTER_RALINK {
+       ULONG           TransmittedByteCount;   // both successful and failure, used to calculate TX throughput
+       ULONG           ReceivedByteCount;      // both CRC okay and CRC error, used to calculate RX throughput
+       ULONG           BeenDisassociatedCount;
+       ULONG           BadCQIAutoRecoveryCount;
+       ULONG           PoorCQIRoamingCount;
+       ULONG           MgmtRingFullCount;
+       ULONG           RxCountSinceLastNULL;
+       ULONG           RxCount;
+       ULONG           RxRingErrCount;
+       ULONG           KickTxCount;
+       ULONG           TxRingErrCount;
+       LARGE_INTEGER   RealFcsErrCount;
+       ULONG           PendingNdisPacketCount;
+
+       ULONG           OneSecOsTxCount[NUM_OF_TX_RING];
+       ULONG           OneSecDmaDoneCount[NUM_OF_TX_RING];
+       UINT32          OneSecTxDoneCount;
+       ULONG           OneSecRxCount;
+       UINT32          OneSecTxAggregationCount;
+       UINT32          OneSecRxAggregationCount;
+
+       UINT32                  OneSecFrameDuplicateCount;
+
+#ifdef RT2870
+       ULONG           OneSecTransmittedByteCount;   // both successful and failure, used to calculate TX throughput
+#endif // RT2870 //
+
+       UINT32          OneSecTxNoRetryOkCount;
+       UINT32          OneSecTxRetryOkCount;
+       UINT32          OneSecTxFailCount;
+       UINT32          OneSecFalseCCACnt;      // CCA error count, for debug purpose, might move to global counter
+       UINT32          OneSecRxOkCnt;          // RX without error
+       UINT32          OneSecRxOkDataCnt;      // unicast-to-me DATA frame count
+       UINT32          OneSecRxFcsErrCnt;      // CRC error
+       UINT32          OneSecBeaconSentCnt;
+       UINT32          LastOneSecTotalTxCount; // OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount
+       UINT32          LastOneSecRxOkDataCnt;  // OneSecRxOkDataCnt
+       ULONG           DuplicateRcv;
+       ULONG           TxAggCount;
+       ULONG           TxNonAggCount;
+       ULONG           TxAgg1MPDUCount;
+       ULONG           TxAgg2MPDUCount;
+       ULONG           TxAgg3MPDUCount;
+       ULONG           TxAgg4MPDUCount;
+       ULONG           TxAgg5MPDUCount;
+       ULONG           TxAgg6MPDUCount;
+       ULONG           TxAgg7MPDUCount;
+       ULONG           TxAgg8MPDUCount;
+       ULONG           TxAgg9MPDUCount;
+       ULONG           TxAgg10MPDUCount;
+       ULONG           TxAgg11MPDUCount;
+       ULONG           TxAgg12MPDUCount;
+       ULONG           TxAgg13MPDUCount;
+       ULONG           TxAgg14MPDUCount;
+       ULONG           TxAgg15MPDUCount;
+       ULONG           TxAgg16MPDUCount;
+
+       LARGE_INTEGER       TransmittedOctetsInAMSDU;
+       LARGE_INTEGER       TransmittedAMSDUCount;
+       LARGE_INTEGER       ReceivedOctesInAMSDUCount;
+       LARGE_INTEGER       ReceivedAMSDUCount;
+       LARGE_INTEGER       TransmittedAMPDUCount;
+       LARGE_INTEGER       TransmittedMPDUsInAMPDUCount;
+       LARGE_INTEGER       TransmittedOctetsInAMPDUCount;
+       LARGE_INTEGER       MPDUInReceivedAMPDUCount;
+} COUNTER_RALINK, *PCOUNTER_RALINK;
+
+typedef struct _PID_COUNTER {
+       ULONG           TxAckRequiredCount;      // CRC error
+       ULONG           TxAggreCount;
+       ULONG           TxSuccessCount; // OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount
+       ULONG           LastSuccessRate;
+} PID_COUNTER, *PPID_COUNTER;
+
+typedef struct _COUNTER_DRS {
+       // to record the each TX rate's quality. 0 is best, the bigger the worse.
+       USHORT          TxQuality[MAX_STEP_OF_TX_RATE_SWITCH];
+       UCHAR           PER[MAX_STEP_OF_TX_RATE_SWITCH];
+       UCHAR           TxRateUpPenalty;      // extra # of second penalty due to last unstable condition
+       ULONG           CurrTxRateStableTime; // # of second in current TX rate
+       BOOLEAN         fNoisyEnvironment;
+       BOOLEAN         fLastSecAccordingRSSI;
+       UCHAR           LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down
+       UCHAR                   LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction
+       ULONG                   LastTxOkCount;
+} COUNTER_DRS, *PCOUNTER_DRS;
+
+//
+//  Arcfour Structure Added by PaulWu
+//
+typedef struct  _ARCFOUR
+{
+       UINT            X;
+       UINT            Y;
+       UCHAR           STATE[256];
+} ARCFOURCONTEXT, *PARCFOURCONTEXT;
+
+// MIMO Tx parameter, ShortGI, MCS, STBC, etc.  these are fields in TXWI too. just copy to TXWI.
+typedef struct  _RECEIVE_SETTING {
+#ifdef RT_BIG_ENDIAN
+       USHORT          MIMO:1;
+       USHORT          OFDM:1;
+       USHORT          rsv:3;
+       USHORT          STBC:2; //SPACE
+       USHORT          ShortGI:1;
+       USHORT          Mode:2; //channel bandwidth 20MHz or 40 MHz
+       USHORT          NumOfRX:2;                 // MIMO. WE HAVE 3R
+#else
+       USHORT          NumOfRX:2;                 // MIMO. WE HAVE 3R
+       USHORT          Mode:2; //channel bandwidth 20MHz or 40 MHz
+       USHORT          ShortGI:1;
+       USHORT          STBC:2; //SPACE
+       USHORT          rsv:3;
+       USHORT          OFDM:1;
+       USHORT          MIMO:1;
+#endif
+ } RECEIVE_SETTING, *PRECEIVE_SETTING;
+
+// Shared key data structure
+typedef struct  _WEP_KEY {
+       UCHAR   KeyLen;                     // Key length for each key, 0: entry is invalid
+       UCHAR   Key[MAX_LEN_OF_KEY];        // right now we implement 4 keys, 128 bits max
+} WEP_KEY, *PWEP_KEY;
+
+typedef struct _CIPHER_KEY {
+       UCHAR   Key[16];            // right now we implement 4 keys, 128 bits max
+       UCHAR   RxMic[8];                       // make alignment
+       UCHAR   TxMic[8];
+       UCHAR   TxTsc[6];           // 48bit TSC value
+       UCHAR   RxTsc[6];           // 48bit TSC value
+       UCHAR   CipherAlg;          // 0-none, 1:WEP64, 2:WEP128, 3:TKIP, 4:AES, 5:CKIP64, 6:CKIP128
+       UCHAR   KeyLen;
+#ifdef CONFIG_STA_SUPPORT
+       UCHAR   BssId[6];
+#endif // CONFIG_STA_SUPPORT //
+            // Key length for each key, 0: entry is invalid
+       UCHAR   Type;               // Indicate Pairwise/Group when reporting MIC error
+} CIPHER_KEY, *PCIPHER_KEY;
+
+typedef struct _BBP_TUNING_STRUCT {
+       BOOLEAN     Enable;
+       UCHAR       FalseCcaCountUpperBound;  // 100 per sec
+       UCHAR       FalseCcaCountLowerBound;  // 10 per sec
+       UCHAR       R17LowerBound;            // specified in E2PROM
+       UCHAR       R17UpperBound;            // 0x68 according to David Tung
+       UCHAR       CurrentR17Value;
+} BBP_TUNING, *PBBP_TUNING;
+
+typedef struct _SOFT_RX_ANT_DIVERSITY_STRUCT {
+       UCHAR     EvaluatePeriod;                // 0:not evalute status, 1: evaluate status, 2: switching status
+       UCHAR     Pair1PrimaryRxAnt;     // 0:Ant-E1, 1:Ant-E2
+       UCHAR     Pair1SecondaryRxAnt;   // 0:Ant-E1, 1:Ant-E2
+       UCHAR     Pair2PrimaryRxAnt;     // 0:Ant-E3, 1:Ant-E4
+       UCHAR     Pair2SecondaryRxAnt;   // 0:Ant-E3, 1:Ant-E4
+       SHORT     Pair1AvgRssi[2];       // AvgRssi[0]:E1, AvgRssi[1]:E2
+       SHORT     Pair2AvgRssi[2];       // AvgRssi[0]:E3, AvgRssi[1]:E4
+       SHORT     Pair1LastAvgRssi;      //
+       SHORT     Pair2LastAvgRssi;      //
+       ULONG     RcvPktNumWhenEvaluate;
+       BOOLEAN   FirstPktArrivedWhenEvaluate;
+       RALINK_TIMER_STRUCT    RxAntDiversityTimer;
+} SOFT_RX_ANT_DIVERSITY, *PSOFT_RX_ANT_DIVERSITY;
+
+typedef struct _LEAP_AUTH_INFO {
+       BOOLEAN         Enabled;        //Ture: Enable LEAP Authentication
+       BOOLEAN         CCKM;           //Ture: Use Fast Reauthentication with CCKM
+       UCHAR           Reserve[2];
+       UCHAR           UserName[256];  //LEAP, User name
+       ULONG           UserNameLen;
+       UCHAR           Password[256];  //LEAP, User Password
+       ULONG           PasswordLen;
+} LEAP_AUTH_INFO, *PLEAP_AUTH_INFO;
+
+typedef struct {
+       UCHAR        Addr[MAC_ADDR_LEN];
+       UCHAR        ErrorCode[2];  //00 01-Invalid authentication type
+                                                               //00 02-Authentication timeout
+                                                               //00 03-Challenge from AP failed
+                                                               //00 04-Challenge to AP failed
+       BOOLEAN      Reported;
+} ROGUEAP_ENTRY, *PROGUEAP_ENTRY;
+
+typedef struct {
+       UCHAR               RogueApNr;
+       ROGUEAP_ENTRY       RogueApEntry[MAX_LEN_OF_BSS_TABLE];
+} ROGUEAP_TABLE, *PROGUEAP_TABLE;
+
+typedef struct {
+       BOOLEAN     Enable;
+       UCHAR       Delta;
+       BOOLEAN     PlusSign;
+} CCK_TX_POWER_CALIBRATE, *PCCK_TX_POWER_CALIBRATE;
+
+//
+// Receive Tuple Cache Format
+//
+typedef struct  _TUPLE_CACHE    {
+       BOOLEAN         Valid;
+       UCHAR           MacAddress[MAC_ADDR_LEN];
+       USHORT          Sequence;
+       USHORT          Frag;
+} TUPLE_CACHE, *PTUPLE_CACHE;
+
+//
+// Fragment Frame structure
+//
+typedef struct  _FRAGMENT_FRAME {
+       PNDIS_PACKET    pFragPacket;
+       ULONG       RxSize;
+       USHORT      Sequence;
+       USHORT      LastFrag;
+       ULONG       Flags;          // Some extra frame information. bit 0: LLC presented
+} FRAGMENT_FRAME, *PFRAGMENT_FRAME;
+
+
+//
+// Packet information for NdisQueryPacket
+//
+typedef struct  _PACKET_INFO    {
+       UINT            PhysicalBufferCount;    // Physical breaks of buffer descripor chained
+       UINT            BufferCount ;           // Number of Buffer descriptor chained
+       UINT            TotalPacketLength ;     // Self explained
+       PNDIS_BUFFER    pFirstBuffer;           // Pointer to first buffer descriptor
+} PACKET_INFO, *PPACKET_INFO;
+
+//
+// Tkip Key structure which RC4 key & MIC calculation
+//
+typedef struct  _TKIP_KEY_INFO  {
+       UINT        nBytesInM;  // # bytes in M for MICKEY
+       ULONG       IV16;
+       ULONG       IV32;
+       ULONG       K0;         // for MICKEY Low
+       ULONG       K1;         // for MICKEY Hig
+       ULONG       L;          // Current state for MICKEY
+       ULONG       R;          // Current state for MICKEY
+       ULONG       M;          // Message accumulator for MICKEY
+       UCHAR       RC4KEY[16];
+       UCHAR       MIC[8];
+} TKIP_KEY_INFO, *PTKIP_KEY_INFO;
+
+//
+// Private / Misc data, counters for driver internal use
+//
+typedef struct  __PRIVATE_STRUC {
+       UINT       SystemResetCnt;         // System reset counter
+       UINT       TxRingFullCnt;          // Tx ring full occurrance number
+       UINT       PhyRxErrCnt;            // PHY Rx error count, for debug purpose, might move to global counter
+       // Variables for WEP encryption / decryption in rtmp_wep.c
+       UINT       FCSCRC32;
+       ARCFOURCONTEXT  WEPCONTEXT;
+       // Tkip stuff
+       TKIP_KEY_INFO   Tx;
+       TKIP_KEY_INFO   Rx;
+} PRIVATE_STRUC, *PPRIVATE_STRUC;
+
+// structure to tune BBP R66 (BBP TUNING)
+typedef struct _BBP_R66_TUNING {
+       BOOLEAN     bEnable;
+       USHORT      FalseCcaLowerThreshold;  // default 100
+       USHORT      FalseCcaUpperThreshold;  // default 512
+       UCHAR       R66Delta;
+       UCHAR       R66CurrentValue;
+       BOOLEAN         R66LowerUpperSelect; //Before LinkUp, Used LowerBound or UpperBound as R66 value.
+} BBP_R66_TUNING, *PBBP_R66_TUNING;
+
+// structure to store channel TX power
+typedef struct _CHANNEL_TX_POWER {
+       USHORT     RemainingTimeForUse;         //unit: sec
+       UCHAR      Channel;
+#ifdef DOT11N_DRAFT3
+       BOOLEAN       bEffectedChannel; // For BW 40 operating in 2.4GHz , the "effected channel" is the channel that is covered in 40Mhz.
+#endif // DOT11N_DRAFT3 //
+       CHAR       Power;
+       CHAR       Power2;
+       UCHAR      MaxTxPwr;
+       UCHAR      DfsReq;
+} CHANNEL_TX_POWER, *PCHANNEL_TX_POWER;
+
+// structure to store 802.11j channel TX power
+typedef struct _CHANNEL_11J_TX_POWER {
+       UCHAR      Channel;
+       UCHAR      BW;  // BW_10 or BW_20
+       CHAR       Power;
+       CHAR       Power2;
+       USHORT     RemainingTimeForUse;         //unit: sec
+} CHANNEL_11J_TX_POWER, *PCHANNEL_11J_TX_POWER;
+
+typedef enum _ABGBAND_STATE_ {
+       UNKNOWN_BAND,
+       BG_BAND,
+       A_BAND,
+} ABGBAND_STATE;
+
+typedef struct _MLME_STRUCT {
+#ifdef CONFIG_STA_SUPPORT
+       // STA state machines
+       STATE_MACHINE           CntlMachine;
+       STATE_MACHINE           AssocMachine;
+       STATE_MACHINE           AuthMachine;
+       STATE_MACHINE           AuthRspMachine;
+       STATE_MACHINE           SyncMachine;
+       STATE_MACHINE           WpaPskMachine;
+       STATE_MACHINE           LeapMachine;
+       STATE_MACHINE           AironetMachine;
+       STATE_MACHINE_FUNC      AssocFunc[ASSOC_FUNC_SIZE];
+       STATE_MACHINE_FUNC      AuthFunc[AUTH_FUNC_SIZE];
+       STATE_MACHINE_FUNC      AuthRspFunc[AUTH_RSP_FUNC_SIZE];
+       STATE_MACHINE_FUNC      SyncFunc[SYNC_FUNC_SIZE];
+       STATE_MACHINE_FUNC      WpaPskFunc[WPA_PSK_FUNC_SIZE];
+       STATE_MACHINE_FUNC      AironetFunc[AIRONET_FUNC_SIZE];
+#endif // CONFIG_STA_SUPPORT //
+       STATE_MACHINE_FUNC      ActFunc[ACT_FUNC_SIZE];
+       // Action
+       STATE_MACHINE           ActMachine;
+
+
+#ifdef QOS_DLS_SUPPORT
+       STATE_MACHINE                   DlsMachine;
+       STATE_MACHINE_FUNC      DlsFunc[DLS_FUNC_SIZE];
+#endif // QOS_DLS_SUPPORT //
+
+
+
+
+       ULONG                   ChannelQuality;  // 0..100, Channel Quality Indication for Roaming
+       ULONG                   Now32;           // latch the value of NdisGetSystemUpTime()
+       ULONG                   LastSendNULLpsmTime;
+
+       BOOLEAN                 bRunning;
+       NDIS_SPIN_LOCK          TaskLock;
+       MLME_QUEUE              Queue;
+
+       UINT                    ShiftReg;
+
+       RALINK_TIMER_STRUCT     PeriodicTimer;
+       RALINK_TIMER_STRUCT     APSDPeriodicTimer;
+       RALINK_TIMER_STRUCT     LinkDownTimer;
+       RALINK_TIMER_STRUCT     LinkUpTimer;
+       ULONG                   PeriodicRound;
+       ULONG                   OneSecPeriodicRound;
+
+       UCHAR                                   RealRxPath;
+       BOOLEAN                                 bLowThroughput;
+       BOOLEAN                                 bEnableAutoAntennaCheck;
+       RALINK_TIMER_STRUCT             RxAntEvalTimer;
+
+#ifdef RT2870
+       UCHAR CaliBW40RfR24;
+       UCHAR CaliBW20RfR24;
+#endif // RT2870 //
+
+} MLME_STRUCT, *PMLME_STRUCT;
+
+// structure for radar detection and channel switch
+typedef struct _RADAR_DETECT_STRUCT {
+    //BOOLEAN          IEEE80211H;                     // 0: disable, 1: enable IEEE802.11h
+       UCHAR           CSCount;                        //Channel switch counter
+       UCHAR           CSPeriod;                       //Channel switch period (beacon count)
+       UCHAR           RDCount;                        //Radar detection counter
+       UCHAR           RDMode;                         //Radar Detection mode
+       UCHAR           RDDurRegion;            //Radar detection duration region
+       UCHAR           BBPR16;
+       UCHAR           BBPR17;
+       UCHAR           BBPR18;
+       UCHAR           BBPR21;
+       UCHAR           BBPR22;
+       UCHAR           BBPR64;
+       ULONG           InServiceMonitorCount; // unit: sec
+       UINT8           DfsSessionTime;
+       BOOLEAN         bFastDfs;
+       UINT8           ChMovingTime;
+       UINT8           LongPulseRadarTh;
+} RADAR_DETECT_STRUCT, *PRADAR_DETECT_STRUCT;
+
+#ifdef CARRIER_DETECTION_SUPPORT
+typedef enum CD_STATE_n
+{
+       CD_NORMAL,
+       CD_SILENCE,
+       CD_MAX_STATE
+} CD_STATE;
+
+typedef struct CARRIER_DETECTION_s
+{
+       BOOLEAN                                 Enable;
+       UINT8                                   CDSessionTime;
+       UINT8                                   CDPeriod;
+       CD_STATE                                CD_State;
+} CARRIER_DETECTION, *PCARRIER_DETECTION;
+#endif // CARRIER_DETECTION_SUPPORT //
+
+typedef enum _REC_BLOCKACK_STATUS
+{
+    Recipient_NONE=0,
+       Recipient_USED,
+       Recipient_HandleRes,
+    Recipient_Accept
+} REC_BLOCKACK_STATUS, *PREC_BLOCKACK_STATUS;
+
+typedef enum _ORI_BLOCKACK_STATUS
+{
+    Originator_NONE=0,
+       Originator_USED,
+    Originator_WaitRes,
+    Originator_Done
+} ORI_BLOCKACK_STATUS, *PORI_BLOCKACK_STATUS;
+
+#ifdef DOT11_N_SUPPORT
+typedef struct _BA_ORI_ENTRY{
+       UCHAR   Wcid;
+       UCHAR   TID;
+       UCHAR   BAWinSize;
+       UCHAR   Token;
+// Sequence is to fill every outgoing QoS DATA frame's sequence field in 802.11 header.
+       USHORT  Sequence;
+       USHORT  TimeOutValue;
+       ORI_BLOCKACK_STATUS  ORI_BA_Status;
+       RALINK_TIMER_STRUCT ORIBATimer;
+       PVOID   pAdapter;
+} BA_ORI_ENTRY, *PBA_ORI_ENTRY;
+
+typedef struct _BA_REC_ENTRY {
+       UCHAR   Wcid;
+       UCHAR   TID;
+       UCHAR   BAWinSize;      // 7.3.1.14. each buffer is capable of holding a max AMSDU or MSDU.
+       //UCHAR NumOfRxPkt;
+       //UCHAR    Curindidx; // the head in the RX reordering buffer
+       USHORT          LastIndSeq;
+//     USHORT          LastIndSeqAtTimer;
+       USHORT          TimeOutValue;
+       RALINK_TIMER_STRUCT RECBATimer;
+       ULONG           LastIndSeqAtTimer;
+       ULONG           nDropPacket;
+       ULONG           rcvSeq;
+       REC_BLOCKACK_STATUS  REC_BA_Status;
+//     UCHAR   RxBufIdxUsed;
+       // corresponding virtual address for RX reordering packet storage.
+       //RTMP_REORDERDMABUF MAP_RXBuf[MAX_RX_REORDERBUF];
+       NDIS_SPIN_LOCK          RxReRingLock;                 // Rx Ring spinlock
+//     struct _BA_REC_ENTRY *pNext;
+       PVOID   pAdapter;
+       struct reordering_list  list;
+} BA_REC_ENTRY, *PBA_REC_ENTRY;
+
+
+typedef struct {
+       ULONG           numAsRecipient;         // I am recipient of numAsRecipient clients. These client are in the BARecEntry[]
+       ULONG           numAsOriginator;        // I am originator of   numAsOriginator clients. These clients are in the BAOriEntry[]
+       BA_ORI_ENTRY       BAOriEntry[MAX_LEN_OF_BA_ORI_TABLE];
+       BA_REC_ENTRY       BARecEntry[MAX_LEN_OF_BA_REC_TABLE];
+} BA_TABLE, *PBA_TABLE;
+
+//For QureyBATableOID use;
+typedef struct  PACKED _OID_BA_REC_ENTRY{
+       UCHAR   MACAddr[MAC_ADDR_LEN];
+       UCHAR   BaBitmap;   // if (BaBitmap&(1<<TID)), this session with{MACAddr, TID}exists, so read BufSize[TID] for BufferSize
+       UCHAR   rsv;
+       UCHAR   BufSize[8];
+       REC_BLOCKACK_STATUS     REC_BA_Status[8];
+} OID_BA_REC_ENTRY, *POID_BA_REC_ENTRY;
+
+//For QureyBATableOID use;
+typedef struct  PACKED _OID_BA_ORI_ENTRY{
+       UCHAR   MACAddr[MAC_ADDR_LEN];
+       UCHAR   BaBitmap;  // if (BaBitmap&(1<<TID)), this session with{MACAddr, TID}exists, so read BufSize[TID] for BufferSize, read ORI_BA_Status[TID] for status
+       UCHAR   rsv;
+       UCHAR   BufSize[8];
+       ORI_BLOCKACK_STATUS  ORI_BA_Status[8];
+} OID_BA_ORI_ENTRY, *POID_BA_ORI_ENTRY;
+
+typedef struct _QUERYBA_TABLE{
+       OID_BA_ORI_ENTRY       BAOriEntry[32];
+       OID_BA_REC_ENTRY       BARecEntry[32];
+       UCHAR   OriNum;// Number of below BAOriEntry
+       UCHAR   RecNum;// Number of below BARecEntry
+} QUERYBA_TABLE, *PQUERYBA_TABLE;
+
+typedef        union   _BACAP_STRUC    {
+#ifdef RT_BIG_ENDIAN
+       struct  {
+               UINT32     :4;
+               UINT32     b2040CoexistScanSup:1;               //As Sta, support do 2040 coexistence scan for AP. As Ap, support monitor trigger event to check if can use BW 40MHz.
+               UINT32     bHtAdhoc:1;                  // adhoc can use ht rate.
+               UINT32     MMPSmode:2;  // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable
+               UINT32     AmsduSize:1; // 0:3839, 1:7935 bytes. UINT  MSDUSizeToBytes[]        = { 3839, 7935};
+               UINT32     AmsduEnable:1;       //Enable AMSDU transmisstion
+               UINT32          MpduDensity:3;
+               UINT32          Policy:2;       // 0: DELAY_BA 1:IMMED_BA  (//BA Policy subfiled value in ADDBA frame)   2:BA-not use
+               UINT32          AutoBA:1;       // automatically BA
+               UINT32          TxBAWinLimit:8;
+               UINT32          RxBAWinLimit:8;
+       }       field;
+#else
+       struct  {
+               UINT32          RxBAWinLimit:8;
+               UINT32          TxBAWinLimit:8;
+               UINT32          AutoBA:1;       // automatically BA
+               UINT32          Policy:2;       // 0: DELAY_BA 1:IMMED_BA  (//BA Policy subfiled value in ADDBA frame)   2:BA-not use
+               UINT32          MpduDensity:3;
+               UINT32          AmsduEnable:1;  //Enable AMSDU transmisstion
+               UINT32          AmsduSize:1;    // 0:3839, 1:7935 bytes. UINT  MSDUSizeToBytes[]        = { 3839, 7935};
+               UINT32          MMPSmode:2;     // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable
+               UINT32          bHtAdhoc:1;                     // adhoc can use ht rate.
+               UINT32          b2040CoexistScanSup:1;          //As Sta, support do 2040 coexistence scan for AP. As Ap, support monitor trigger event to check if can use BW 40MHz.
+               UINT32          :4;
+       }       field;
+#endif
+       UINT32                  word;
+} BACAP_STRUC, *PBACAP_STRUC;
+#endif // DOT11_N_SUPPORT //
+
+//This structure is for all 802.11n card InterOptibilityTest action. Reset all Num every n second.  (Details see MLMEPeriodic)
+typedef        struct  _IOT_STRUC      {
+       UCHAR                   Threshold[2];
+       UCHAR                   ReorderTimeOutNum[MAX_LEN_OF_BA_REC_TABLE];     // compare with threshold[0]
+       UCHAR                   RefreshNum[MAX_LEN_OF_BA_REC_TABLE];    // compare with threshold[1]
+       ULONG                   OneSecInWindowCount;
+       ULONG                   OneSecFrameDuplicateCount;
+       ULONG                   OneSecOutWindowCount;
+       UCHAR                   DelOriAct;
+       UCHAR                   DelRecAct;
+       UCHAR                   RTSShortProt;
+       UCHAR                   RTSLongProt;
+       BOOLEAN                 bRTSLongProtOn;
+#ifdef CONFIG_STA_SUPPORT
+       BOOLEAN                 bLastAtheros;
+    BOOLEAN                    bCurrentAtheros;
+    BOOLEAN         bNowAtherosBurstOn;
+       BOOLEAN                 bNextDisableRxBA;
+    BOOLEAN                    bToggle;
+#endif // CONFIG_STA_SUPPORT //
+} IOT_STRUC, *PIOT_STRUC;
+
+// This is the registry setting for 802.11n transmit setting.  Used in advanced page.
+typedef union _REG_TRANSMIT_SETTING {
+#ifdef RT_BIG_ENDIAN
+ struct {
+         UINT32  rsv:13;
+                UINT32  EXTCHA:2;
+                UINT32  HTMODE:1;
+                UINT32  TRANSNO:2;
+                UINT32  STBC:1; //SPACE
+                UINT32  ShortGI:1;
+                UINT32  BW:1; //channel bandwidth 20MHz or 40 MHz
+                UINT32  TxBF:1; // 3*3
+                UINT32  rsv0:10;
+                //UINT32  MCS:7;                 // MCS
+         //UINT32  PhyMode:4;
+    } field;
+#else
+ struct {
+         //UINT32  PhyMode:4;
+         //UINT32  MCS:7;                 // MCS
+                UINT32  rsv0:10;
+                UINT32  TxBF:1;
+         UINT32  BW:1; //channel bandwidth 20MHz or 40 MHz
+         UINT32  ShortGI:1;
+         UINT32  STBC:1; //SPACE
+         UINT32  TRANSNO:2;
+         UINT32  HTMODE:1;
+         UINT32  EXTCHA:2;
+         UINT32  rsv:13;
+    } field;
+#endif
+ UINT32   word;
+} REG_TRANSMIT_SETTING, *PREG_TRANSMIT_SETTING;
+
+typedef union  _DESIRED_TRANSMIT_SETTING {
+#ifdef RT_BIG_ENDIAN
+       struct  {
+                       USHORT          rsv:3;
+                       USHORT          FixedTxMode:2;                  // If MCS isn't AUTO, fix rate in CCK, OFDM or HT mode.
+                       USHORT          PhyMode:4;
+                       USHORT          MCS:7;                 // MCS
+       }       field;
+#else
+       struct  {
+                       USHORT          MCS:7;                  // MCS
+                       USHORT          PhyMode:4;
+                       USHORT          FixedTxMode:2;                  // If MCS isn't AUTO, fix rate in CCK, OFDM or HT mode.
+                       USHORT          rsv:3;
+       }       field;
+#endif
+       USHORT          word;
+ } DESIRED_TRANSMIT_SETTING, *PDESIRED_TRANSMIT_SETTING;
+
+typedef struct {
+       BOOLEAN         IsRecipient;
+       UCHAR   MACAddr[MAC_ADDR_LEN];
+       UCHAR   TID;
+       UCHAR   nMSDU;
+       USHORT   TimeOut;
+       BOOLEAN bAllTid;  // If True, delete all TID for BA sessions with this MACaddr.
+} OID_ADD_BA_ENTRY, *POID_ADD_BA_ENTRY;
+
+//
+// Multiple SSID structure
+//
+#define WLAN_MAX_NUM_OF_TIM                    ((MAX_LEN_OF_MAC_TABLE >> 3) + 1) /* /8 + 1 */
+#define WLAN_CT_TIM_BCMC_OFFSET                0 /* unit: 32B */
+
+/* clear bcmc TIM bit */
+#define WLAN_MR_TIM_BCMC_CLEAR(apidx) \
+       pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] &= ~BIT8[0];
+
+/* set bcmc TIM bit */
+#define WLAN_MR_TIM_BCMC_SET(apidx) \
+       pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] |= BIT8[0];
+
+/* clear a station PS TIM bit */
+#define WLAN_MR_TIM_BIT_CLEAR(ad_p, apidx, wcid) \
+       {       UCHAR tim_offset = wcid >> 3; \
+               UCHAR bit_offset = wcid & 0x7; \
+               ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] &= (~BIT8[bit_offset]); }
+
+/* set a station PS TIM bit */
+#define WLAN_MR_TIM_BIT_SET(ad_p, apidx, wcid) \
+       {       UCHAR tim_offset = wcid >> 3; \
+               UCHAR bit_offset = wcid & 0x7; \
+               ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] |= BIT8[bit_offset]; }
+
+#ifdef RT2870
+#define BEACON_BITMAP_MASK             0xff
+typedef struct _BEACON_SYNC_STRUCT_
+{
+       UCHAR                           BeaconBuf[HW_BEACON_MAX_COUNT][HW_BEACON_OFFSET];
+       UCHAR                                   BeaconTxWI[HW_BEACON_MAX_COUNT][TXWI_SIZE];
+       ULONG                                   TimIELocationInBeacon[HW_BEACON_MAX_COUNT];
+       ULONG                                   CapabilityInfoLocationInBeacon[HW_BEACON_MAX_COUNT];
+       BOOLEAN                                 EnableBeacon;           // trigger to enable beacon transmission.
+       UCHAR                                   BeaconBitMap;           // NOTE: If the MAX_MBSSID_NUM is larger than 8, this parameter need to change.
+       UCHAR                                   DtimBitOn;                      // NOTE: If the MAX_MBSSID_NUM is larger than 8, this parameter need to change.
+}BEACON_SYNC_STRUCT;
+#endif // RT2870 //
+
+typedef struct _MULTISSID_STRUCT {
+       UCHAR                                                           Bssid[MAC_ADDR_LEN];
+    UCHAR                               SsidLen;
+    CHAR                                Ssid[MAX_LEN_OF_SSID];
+    USHORT                              CapabilityInfo;
+
+    PNET_DEV                                           MSSIDDev;
+
+       NDIS_802_11_AUTHENTICATION_MODE     AuthMode;
+       NDIS_802_11_WEP_STATUS              WepStatus;
+       NDIS_802_11_WEP_STATUS                          GroupKeyWepStatus;
+       WPA_MIX_PAIR_CIPHER                                     WpaMixPairCipher;
+
+       ULONG                                                           TxCount;
+       ULONG                                                           RxCount;
+       ULONG                                                           ReceivedByteCount;
+       ULONG                                                           TransmittedByteCount;
+       ULONG                                                           RxErrorCount;
+       ULONG                                                           RxDropCount;
+
+       HTTRANSMIT_SETTING                                      HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI.
+       RT_HT_PHY_INFO                                          DesiredHtPhyInfo;
+       DESIRED_TRANSMIT_SETTING                DesiredTransmitSetting; // Desired transmit setting. this is for reading registry setting only. not useful.
+       BOOLEAN                                                         bAutoTxRateSwitch;
+
+       //CIPHER_KEY                          SharedKey[SHARE_KEY_NUM]; // ref pAd->SharedKey[BSS][4]
+       UCHAR                               DefaultKeyId;
+
+       UCHAR                                                           TxRate;       // RATE_1, RATE_2, RATE_5_5, RATE_11, ...
+       UCHAR                                                           DesiredRates[MAX_LEN_OF_SUPPORTED_RATES];// OID_802_11_DESIRED_RATES
+       UCHAR                                                           DesiredRatesIndex;
+       UCHAR                                                           MaxTxRate;            // RATE_1, RATE_2, RATE_5_5, RATE_11
+
+//     ULONG                                                   TimBitmap;      // bit0 for broadcast, 1 for AID1, 2 for AID2, ...so on
+//    ULONG                                            TimBitmap2;     // b0 for AID32, b1 for AID33, ... and so on
+       UCHAR                                                           TimBitmaps[WLAN_MAX_NUM_OF_TIM];
+
+    // WPA
+    UCHAR                               GMK[32];
+    UCHAR                               PMK[32];
+       UCHAR                                                           GTK[32];
+    BOOLEAN                             IEEE8021X;
+    BOOLEAN                             PreAuth;
+    UCHAR                               GNonce[32];
+    UCHAR                               PortSecured;
+    NDIS_802_11_PRIVACY_FILTER          PrivacyFilter;
+    UCHAR                               BANClass3Data;
+    ULONG                               IsolateInterStaTraffic;
+
+    UCHAR                               RSNIE_Len[2];
+    UCHAR                               RSN_IE[2][MAX_LEN_OF_RSNIE];
+
+
+    UCHAR                                      TimIELocationInBeacon;
+    UCHAR                                      CapabilityInfoLocationInBeacon;
+    // outgoing BEACON frame buffer and corresponding TXWI
+       // PTXWI_STRUC                           BeaconTxWI; //
+    CHAR                                BeaconBuf[MAX_BEACON_SIZE]; // NOTE: BeaconBuf should be 4-byte aligned
+
+    BOOLEAN                             bHideSsid;
+       UINT16                                                          StationKeepAliveTime; // unit: second
+
+    USHORT                              VLAN_VID;
+    USHORT                              VLAN_Priority;
+
+    RT_802_11_ACL                                              AccessControlList;
+
+       // EDCA Qos
+    BOOLEAN                                                            bWmmCapable;    // 0:disable WMM, 1:enable WMM
+    BOOLEAN                                                            bDLSCapable;    // 0:disable DLS, 1:enable DLS
+
+       UCHAR                                                   DlsPTK[64];             // Due to windows dirver count on meetinghouse to handle 4-way shake
+
+       // For 802.1x daemon setting per BSS
+       UCHAR                                                           radius_srv_num;
+       RADIUS_SRV_INFO                                         radius_srv_info[MAX_RADIUS_SRV_NUM];
+
+#ifdef RTL865X_SOC
+       unsigned int                                            mylinkid;
+#endif
+
+
+       UINT32                                  RcvdConflictSsidCount;
+       UINT32                                  RcvdSpoofedAssocRespCount;
+       UINT32                                  RcvdSpoofedReassocRespCount;
+       UINT32                                  RcvdSpoofedProbeRespCount;
+       UINT32                                  RcvdSpoofedBeaconCount;
+       UINT32                                  RcvdSpoofedDisassocCount;
+       UINT32                                  RcvdSpoofedAuthCount;
+       UINT32                                  RcvdSpoofedDeauthCount;
+       UINT32                                  RcvdSpoofedUnknownMgmtCount;
+       UINT32                                  RcvdReplayAttackCount;
+
+       CHAR                                    RssiOfRcvdConflictSsid;
+       CHAR                                    RssiOfRcvdSpoofedAssocResp;
+       CHAR                                    RssiOfRcvdSpoofedReassocResp;
+       CHAR                                    RssiOfRcvdSpoofedProbeResp;
+       CHAR                                    RssiOfRcvdSpoofedBeacon;
+       CHAR                                    RssiOfRcvdSpoofedDisassoc;
+       CHAR                                    RssiOfRcvdSpoofedAuth;
+       CHAR                                    RssiOfRcvdSpoofedDeauth;
+       CHAR                                    RssiOfRcvdSpoofedUnknownMgmt;
+       CHAR                                    RssiOfRcvdReplayAttack;
+
+       BOOLEAN                                 bBcnSntReq;
+       UCHAR                                   BcnBufIdx;
+} MULTISSID_STRUCT, *PMULTISSID_STRUCT;
+
+
+
+#ifdef DOT11N_DRAFT3
+typedef enum _BSS2040COEXIST_FLAG{
+       BSS_2040_COEXIST_DISABLE = 0,
+       BSS_2040_COEXIST_TIMER_FIRED  = 1,
+       BSS_2040_COEXIST_INFO_SYNC = 2,
+       BSS_2040_COEXIST_INFO_NOTIFY = 4,
+}BSS2040COEXIST_FLAG;
+#endif // DOT11N_DRAFT3 //
+
+// configuration common to OPMODE_AP as well as OPMODE_STA
+typedef struct _COMMON_CONFIG {
+
+       BOOLEAN         bCountryFlag;
+       UCHAR           CountryCode[3];
+       UCHAR           Geography;
+       UCHAR       CountryRegion;      // Enum of country region, 0:FCC, 1:IC, 2:ETSI, 3:SPAIN, 4:France, 5:MKK, 6:MKK1, 7:Israel
+       UCHAR       CountryRegionForABand;      // Enum of country region for A band
+       UCHAR       PhyMode;            // PHY_11A, PHY_11B, PHY_11BG_MIXED, PHY_ABG_MIXED
+       USHORT      Dsifs;              // in units of usec
+       ULONG       PacketFilter;       // Packet filter for receiving
+
+       CHAR        Ssid[MAX_LEN_OF_SSID]; // NOT NULL-terminated
+       UCHAR       SsidLen;               // the actual ssid length in used
+       UCHAR       LastSsidLen;               // the actual ssid length in used
+       CHAR        LastSsid[MAX_LEN_OF_SSID]; // NOT NULL-terminated
+       UCHAR           LastBssid[MAC_ADDR_LEN];
+
+       UCHAR       Bssid[MAC_ADDR_LEN];
+       USHORT      BeaconPeriod;
+       UCHAR       Channel;
+       UCHAR       CentralChannel;     // Central Channel when using 40MHz is indicating. not real channel.
+
+#if 0  // move to STA_ADMIN_CONFIG
+       UCHAR       DefaultKeyId;
+
+       NDIS_802_11_PRIVACY_FILTER          PrivacyFilter;  // PrivacyFilter enum for 802.1X
+       NDIS_802_11_AUTHENTICATION_MODE     AuthMode;       // This should match to whatever microsoft defined
+       NDIS_802_11_WEP_STATUS              WepStatus;
+       NDIS_802_11_WEP_STATUS                          OrigWepStatus;  // Original wep status set from OID
+
+       // Add to support different cipher suite for WPA2/WPA mode
+       NDIS_802_11_ENCRYPTION_STATUS           GroupCipher;            // Multicast cipher suite
+       NDIS_802_11_ENCRYPTION_STATUS           PairCipher;                     // Unicast cipher suite
+       BOOLEAN                                                         bMixCipher;                     // Indicate current Pair & Group use different cipher suites
+       USHORT                                                          RsnCapability;
+
+       NDIS_802_11_WEP_STATUS              GroupKeyWepStatus;
+#endif
+
+       UCHAR       SupRate[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR       SupRateLen;
+       UCHAR       ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR       ExtRateLen;
+       UCHAR       DesireRate[MAX_LEN_OF_SUPPORTED_RATES];      // OID_802_11_DESIRED_RATES
+       UCHAR       MaxDesiredRate;
+       UCHAR       ExpectedACKRate[MAX_LEN_OF_SUPPORTED_RATES];
+
+       ULONG       BasicRateBitmap;        // backup basic ratebitmap
+
+       BOOLEAN         bAPSDCapable;
+       BOOLEAN         bInServicePeriod;
+       BOOLEAN         bAPSDAC_BE;
+       BOOLEAN         bAPSDAC_BK;
+       BOOLEAN         bAPSDAC_VI;
+       BOOLEAN         bAPSDAC_VO;
+       BOOLEAN         bNeedSendTriggerFrame;
+       BOOLEAN         bAPSDForcePowerSave;    // Force power save mode, should only use in APSD-STAUT
+       ULONG           TriggerTimerCount;
+       UCHAR           MaxSPLength;
+       UCHAR           BBPCurrentBW;   // BW_10,       BW_20, BW_40
+       // move to MULTISSID_STRUCT for MBSS
+       //HTTRANSMIT_SETTING    HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI.
+       REG_TRANSMIT_SETTING        RegTransmitSetting; //registry transmit setting. this is for reading registry setting only. not useful.
+       //UCHAR       FixedTxMode;              // Fixed Tx Mode (CCK, OFDM), for HT fixed tx mode (GF, MIX) , refer to RegTransmitSetting.field.HTMode
+       UCHAR       TxRate;                 // Same value to fill in TXD. TxRate is 6-bit
+       UCHAR       MaxTxRate;              // RATE_1, RATE_2, RATE_5_5, RATE_11
+       UCHAR       TxRateIndex;            // Tx rate index in RateSwitchTable
+       UCHAR       TxRateTableSize;        // Valid Tx rate table size in RateSwitchTable
+       //BOOLEAN               bAutoTxRateSwitch;
+       UCHAR       MinTxRate;              // RATE_1, RATE_2, RATE_5_5, RATE_11
+       UCHAR       RtsRate;                // RATE_xxx
+       HTTRANSMIT_SETTING      MlmeTransmit;   // MGMT frame PHY rate setting when operatin at Ht rate.
+       UCHAR       MlmeRate;               // RATE_xxx, used to send MLME frames
+       UCHAR       BasicMlmeRate;          // Default Rate for sending MLME frames
+
+       USHORT      RtsThreshold;           // in unit of BYTE
+       USHORT      FragmentThreshold;      // in unit of BYTE
+
+       UCHAR       TxPower;                // in unit of mW
+       ULONG       TxPowerPercentage;      // 0~100 %
+       ULONG       TxPowerDefault;         // keep for TxPowerPercentage
+
+#ifdef DOT11_N_SUPPORT
+       BACAP_STRUC        BACapability; //   NO USE = 0XFF  ;  IMMED_BA =1  ;  DELAY_BA=0
+       BACAP_STRUC        REGBACapability; //   NO USE = 0XFF  ;  IMMED_BA =1  ;  DELAY_BA=0
+#endif // DOT11_N_SUPPORT //
+       IOT_STRUC               IOTestParm;     // 802.11n InterOpbility Test Parameter;
+       ULONG       TxPreamble;             // Rt802_11PreambleLong, Rt802_11PreambleShort, Rt802_11PreambleAuto
+       BOOLEAN     bUseZeroToDisableFragment;     // Microsoft use 0 as disable
+       ULONG       UseBGProtection;        // 0: auto, 1: always use, 2: always not use
+       BOOLEAN     bUseShortSlotTime;      // 0: disable, 1 - use short slot (9us)
+       BOOLEAN     bEnableTxBurst;         // 1: enble TX PACKET BURST, 0: disable TX PACKET BURST
+       BOOLEAN     bAggregationCapable;      // 1: enable TX aggregation when the peer supports it
+       BOOLEAN     bPiggyBackCapable;          // 1: enable TX piggy-back according MAC's version
+       BOOLEAN     bIEEE80211H;                        // 1: enable IEEE802.11h spec.
+       ULONG           DisableOLBCDetect;              // 0: enable OLBC detect; 1 disable OLBC detect
+
+#ifdef DOT11_N_SUPPORT
+       BOOLEAN                         bRdg;
+#endif // DOT11_N_SUPPORT //
+       BOOLEAN             bWmmCapable;        // 0:disable WMM, 1:enable WMM
+       QOS_CAPABILITY_PARM APQosCapability;    // QOS capability of the current associated AP
+       EDCA_PARM           APEdcaParm;         // EDCA parameters of the current associated AP
+       QBSS_LOAD_PARM      APQbssLoad;         // QBSS load of the current associated AP
+       UCHAR               AckPolicy[4];       // ACK policy of the specified AC. see ACK_xxx
+#ifdef CONFIG_STA_SUPPORT
+       BOOLEAN                         bDLSCapable;            // 0:disable DLS, 1:enable DLS
+#endif // CONFIG_STA_SUPPORT //
+       // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular
+       // BOOLEAN control, either ON or OFF. These flags should always be accessed via
+       // OPSTATUS_TEST_FLAG(), OPSTATUS_SET_FLAG(), OP_STATUS_CLEAR_FLAG() macros.
+       // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition
+       ULONG               OpStatusFlags;
+
+       BOOLEAN                         NdisRadioStateOff; //For HCT 12.0, set this flag to TRUE instead of called MlmeRadioOff.
+       ABGBAND_STATE           BandState;              // For setting BBP used on B/G or A mode.
+
+       // IEEE802.11H--DFS.
+       RADAR_DETECT_STRUCT     RadarDetect;
+
+#ifdef CARRIER_DETECTION_SUPPORT
+       CARRIER_DETECTION               CarrierDetect;
+#endif // CARRIER_DETECTION_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+       // HT
+       UCHAR                   BASize;         // USer desired BAWindowSize. Should not exceed our max capability
+       //RT_HT_CAPABILITY      SupportedHtPhy;
+       RT_HT_CAPABILITY        DesiredHtPhy;
+       HT_CAPABILITY_IE                HtCapability;
+       ADD_HT_INFO_IE          AddHTInfo;      // Useful as AP.
+       //This IE is used with channel switch announcement element when changing to a new 40MHz.
+       //This IE is included in channel switch ammouncement frames 7.4.1.5, beacons, probe Rsp.
+       NEW_EXT_CHAN_IE NewExtChanOffset;       //7.3.2.20A, 1 if extension channel is above the control channel, 3 if below, 0 if not present
+
+#ifdef DOT11N_DRAFT3
+       UCHAR                                   Bss2040CoexistFlag;             // bit 0: bBssCoexistTimerRunning, bit 1: NeedSyncAddHtInfo.
+       RALINK_TIMER_STRUCT     Bss2040CoexistTimer;
+
+       //This IE is used for 20/40 BSS Coexistence.
+       BSS_2040_COEXIST_IE             BSS2040CoexistInfo;
+       // ====== 11n D3.0 =======================>
+       USHORT                                  Dot11OBssScanPassiveDwell;                              // Unit : TU. 5~1000
+       USHORT                                  Dot11OBssScanActiveDwell;                               // Unit : TU. 10~1000
+       USHORT                                  Dot11BssWidthTriggerScanInt;                    // Unit : Second
+       USHORT                                  Dot11OBssScanPassiveTotalPerChannel;    // Unit : TU. 200~10000
+       USHORT                                  Dot11OBssScanActiveTotalPerChannel;     // Unit : TU. 20~10000
+       USHORT                                  Dot11BssWidthChanTranDelayFactor;
+       USHORT                                  Dot11OBssScanActivityThre;                              // Unit : percentage
+
+       ULONG                                   Dot11BssWidthChanTranDelay;                     // multiple of (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor)
+       ULONG                                   CountDownCtr;   // CountDown Counter from (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor)
+
+       NDIS_SPIN_LOCK          TriggerEventTabLock;
+       BSS_2040_COEXIST_IE             LastBSSCoexist2040;
+       BSS_2040_COEXIST_IE             BSSCoexist2040;
+       TRIGGER_EVENT_TAB               TriggerEventTab;
+       UCHAR                                   ChannelListIdx;
+       // <====== 11n D3.0 =======================
+       BOOLEAN                                 bOverlapScanning;
+#endif // DOT11N_DRAFT3 //
+
+    BOOLEAN                 bHTProtect;
+    BOOLEAN                 bMIMOPSEnable;
+    BOOLEAN                                    bBADecline;
+       BOOLEAN                                 bDisableReordering;
+       BOOLEAN                                 bForty_Mhz_Intolerant;
+       BOOLEAN                                 bExtChannelSwitchAnnouncement;
+       BOOLEAN                                 bRcvBSSWidthTriggerEvents;
+       ULONG                                   LastRcvBSSWidthTriggerEventsTime;
+
+       UCHAR                                   TxBASize;
+#endif // DOT11_N_SUPPORT //
+
+       // Enable wireless event
+       BOOLEAN                         bWirelessEvent;
+       BOOLEAN                         bWiFiTest;                              // Enable this parameter for WiFi test
+
+       // Tx & Rx Stream number selection
+       UCHAR                           TxStream;
+       UCHAR                           RxStream;
+
+       // transmit phy mode, trasmit rate for Multicast.
+#ifdef MCAST_RATE_SPECIFIC
+       UCHAR                           McastTransmitMcs;
+       UCHAR                           McastTransmitPhyMode;
+#endif // MCAST_RATE_SPECIFIC //
+
+       BOOLEAN                 bHardwareRadio;     // Hardware controlled Radio enabled
+
+#ifdef RT2870
+       BOOLEAN                 bMultipleIRP;       // Multiple Bulk IN flag
+       UCHAR                   NumOfBulkInIRP;     // if bMultipleIRP == TRUE, NumOfBulkInIRP will be 4 otherwise be 1
+       RT_HT_CAPABILITY        SupportedHtPhy;
+       ULONG                           MaxPktOneTxBulk;
+       UCHAR                           TxBulkFactor;
+       UCHAR                           RxBulkFactor;
+
+       BEACON_SYNC_STRUCT      *pBeaconSync;
+       RALINK_TIMER_STRUCT     BeaconUpdateTimer;
+       UINT32                          BeaconAdjust;
+       UINT32                          BeaconFactor;
+       UINT32                          BeaconRemain;
+#endif // RT2870 //
+
+
+       NDIS_SPIN_LOCK                  MeasureReqTabLock;
+       PMEASURE_REQ_TAB                pMeasureReqTab;
+
+       NDIS_SPIN_LOCK                  TpcReqTabLock;
+       PTPC_REQ_TAB                    pTpcReqTab;
+
+       // transmit phy mode, trasmit rate for Multicast.
+#ifdef MCAST_RATE_SPECIFIC
+       HTTRANSMIT_SETTING              MCastPhyMode;
+#endif // MCAST_RATE_SPECIFIC //
+
+#ifdef SINGLE_SKU
+       UINT16                                  DefineMaxTxPwr;
+#endif // SINGLE_SKU //
+
+
+} COMMON_CONFIG, *PCOMMON_CONFIG;
+
+
+#ifdef CONFIG_STA_SUPPORT
+/* Modified by Wu Xi-Kun 4/21/2006 */
+// STA configuration and status
+typedef struct _STA_ADMIN_CONFIG {
+       // GROUP 1 -
+       //   User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe
+       //   the user intended configuration, but not necessary fully equal to the final
+       //   settings in ACTIVE BSS after negotiation/compromize with the BSS holder (either
+       //   AP or IBSS holder).
+       //   Once initialized, user configuration can only be changed via OID_xxx
+       UCHAR       BssType;              // BSS_INFRA or BSS_ADHOC
+       USHORT      AtimWin;          // used when starting a new IBSS
+
+       // GROUP 2 -
+       //   User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe
+       //   the user intended configuration, and should be always applied to the final
+       //   settings in ACTIVE BSS without compromising with the BSS holder.
+       //   Once initialized, user configuration can only be changed via OID_xxx
+       UCHAR       RssiTrigger;
+       UCHAR       RssiTriggerMode;      // RSSI_TRIGGERED_UPON_BELOW_THRESHOLD or RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD
+       USHORT      DefaultListenCount;   // default listen count;
+       ULONG       WindowsPowerMode;           // Power mode for AC power
+       ULONG       WindowsBatteryPowerMode;    // Power mode for battery if exists
+       BOOLEAN     bWindowsACCAMEnable;        // Enable CAM power mode when AC on
+       BOOLEAN     bAutoReconnect;         // Set to TRUE when setting OID_802_11_SSID with no matching BSSID
+       ULONG       WindowsPowerProfile;    // Windows power profile, for NDIS5.1 PnP
+
+       // MIB:ieee802dot11.dot11smt(1).dot11StationConfigTable(1)
+       USHORT      Psm;                  // power management mode   (PWR_ACTIVE|PWR_SAVE)
+       USHORT      DisassocReason;
+       UCHAR       DisassocSta[MAC_ADDR_LEN];
+       USHORT      DeauthReason;
+       UCHAR       DeauthSta[MAC_ADDR_LEN];
+       USHORT      AuthFailReason;
+       UCHAR       AuthFailSta[MAC_ADDR_LEN];
+
+       NDIS_802_11_PRIVACY_FILTER          PrivacyFilter;  // PrivacyFilter enum for 802.1X
+       NDIS_802_11_AUTHENTICATION_MODE     AuthMode;       // This should match to whatever microsoft defined
+       NDIS_802_11_WEP_STATUS              WepStatus;
+       NDIS_802_11_WEP_STATUS                          OrigWepStatus;  // Original wep status set from OID
+
+       // Add to support different cipher suite for WPA2/WPA mode
+       NDIS_802_11_ENCRYPTION_STATUS           GroupCipher;            // Multicast cipher suite
+       NDIS_802_11_ENCRYPTION_STATUS           PairCipher;                     // Unicast cipher suite
+       BOOLEAN                                                         bMixCipher;                     // Indicate current Pair & Group use different cipher suites
+       USHORT                                                          RsnCapability;
+
+       NDIS_802_11_WEP_STATUS              GroupKeyWepStatus;
+
+       UCHAR           PMK[32];                // WPA PSK mode PMK
+       UCHAR       PTK[64];                // WPA PSK mode PTK
+       UCHAR           GTK[32];                                // GTK from authenticator
+       BSSID_INFO      SavedPMK[PMKID_NO];
+       UINT            SavedPMKNum;                    // Saved PMKID number
+
+       UCHAR           DefaultKeyId;
+
+
+       // WPA 802.1x port control, WPA_802_1X_PORT_SECURED, WPA_802_1X_PORT_NOT_SECURED
+       UCHAR       PortSecured;
+
+       // For WPA countermeasures
+       ULONG       LastMicErrorTime;   // record last MIC error time
+       ULONG       MicErrCnt;          // Should be 0, 1, 2, then reset to zero (after disassoiciation).
+       BOOLEAN     bBlockAssoc;        // Block associate attempt for 60 seconds after counter measure occurred.
+       // For WPA-PSK supplicant state
+       WPA_STATE   WpaState;           // Default is SS_NOTUSE and handled by microsoft 802.1x
+       UCHAR       ReplayCounter[8];
+       UCHAR       ANonce[32];         // ANonce for WPA-PSK from aurhenticator
+       UCHAR       SNonce[32];         // SNonce for WPA-PSK
+
+       UCHAR       LastSNR0;             // last received BEACON's SNR
+       UCHAR       LastSNR1;            // last received BEACON's SNR for 2nd  antenna
+       RSSI_SAMPLE RssiSample;
+       ULONG       NumOfAvgRssiSample;
+
+       ULONG       LastBeaconRxTime;     // OS's timestamp of the last BEACON RX time
+       ULONG       Last11bBeaconRxTime;  // OS's timestamp of the last 11B BEACON RX time
+       ULONG           Last11gBeaconRxTime;    // OS's timestamp of the last 11G BEACON RX time
+       ULONG           Last20NBeaconRxTime;    // OS's timestamp of the last 20MHz N BEACON RX time
+
+       ULONG       LastScanTime;       // Record last scan time for issue BSSID_SCAN_LIST
+       ULONG       ScanCnt;            // Scan counts since most recent SSID, BSSID, SCAN OID request
+       BOOLEAN     bSwRadio;           // Software controlled Radio On/Off, TRUE: On
+       BOOLEAN     bHwRadio;           // Hardware controlled Radio On/Off, TRUE: On
+       BOOLEAN     bRadio;             // Radio state, And of Sw & Hw radio state
+       BOOLEAN     bHardwareRadio;     // Hardware controlled Radio enabled
+       BOOLEAN     bShowHiddenSSID;    // Show all known SSID in SSID list get operation
+
+
+       // New for WPA, windows want us to to keep association information and
+       // Fixed IEs from last association response
+       NDIS_802_11_ASSOCIATION_INFORMATION     AssocInfo;
+       USHORT       ReqVarIELen;                // Length of next VIE include EID & Length
+       UCHAR       ReqVarIEs[MAX_VIE_LEN];             // The content saved here should be little-endian format.
+       USHORT       ResVarIELen;                // Length of next VIE include EID & Length
+       UCHAR       ResVarIEs[MAX_VIE_LEN];
+
+       UCHAR       RSNIE_Len;
+       UCHAR       RSN_IE[MAX_LEN_OF_RSNIE];   // The content saved here should be little-endian format.
+
+       // New variables used for CCX 1.0
+       BOOLEAN             bCkipOn;
+       BOOLEAN             bCkipCmicOn;
+       UCHAR               CkipFlag;
+       UCHAR               GIV[3];  //for CCX iv
+       UCHAR               RxSEQ[4];
+       UCHAR               TxSEQ[4];
+       UCHAR               CKIPMIC[4];
+       UCHAR               LeapAuthMode;
+       LEAP_AUTH_INFO      LeapAuthInfo;
+       UCHAR               HashPwd[16];
+       UCHAR               NetworkChallenge[8];
+       UCHAR               NetworkChallengeResponse[24];
+       UCHAR               PeerChallenge[8];
+
+       UCHAR               PeerChallengeResponse[24];
+       UCHAR               SessionKey[16]; //Network session keys (NSK)
+       RALINK_TIMER_STRUCT LeapAuthTimer;
+       ROGUEAP_TABLE       RogueApTab;   //Cisco CCX1 Rogue AP Detection
+
+       // New control flags for CCX
+       CCX_CONTROL         CCXControl;                 // Master administration state
+       BOOLEAN             CCXEnable;                  // Actual CCX state
+       UCHAR               CCXScanChannel;             // Selected channel for CCX beacon request
+       USHORT              CCXScanTime;                // Time out to wait for beacon and probe response
+       UCHAR               CCXReqType;                 // Current processing CCX request type
+       BSS_TABLE           CCXBssTab;                  // BSS Table
+       UCHAR               FrameReportBuf[2048];       // Buffer for creating frame report
+       USHORT              FrameReportLen;             // Current Frame report length
+       ULONG               CLBusyBytes;                // Save the total bytes received durning channel load scan time
+       USHORT              RPIDensity[8];              // Array for RPI density collection
+       // Start address of each BSS table within FrameReportBuf
+       // It's important to update the RxPower of the corresponding Bss
+       USHORT              BssReportOffset[MAX_LEN_OF_BSS_TABLE];
+       USHORT              BeaconToken;                // Token for beacon report
+       ULONG               LastBssIndex;               // Most current reported Bss index
+       RM_REQUEST_ACTION   MeasurementRequest[16];     // Saved measurement request
+       UCHAR               RMReqCnt;                   // Number of measurement request saved.
+       UCHAR               CurrentRMReqIdx;            // Number of measurement request saved.
+       BOOLEAN             ParallelReq;                // Parallel measurement, only one request performed,
+                                                                                                       // It must be the same channel with maximum duration
+       USHORT              ParallelDuration;           // Maximum duration for parallel measurement
+       UCHAR               ParallelChannel;            // Only one channel with parallel measurement
+       USHORT              IAPPToken;                  // IAPP dialog token
+       UCHAR               CCXQosECWMin;               // Cisco QOS ECWMin for AC 0
+       UCHAR               CCXQosECWMax;               // Cisco QOS ECWMax for AC 0
+       // Hack for channel load and noise histogram parameters
+       UCHAR               NHFactor;                   // Parameter for Noise histogram
+       UCHAR               CLFactor;                   // Parameter for channel load
+
+       UCHAR               KRK[16];        //Key Refresh Key.
+       UCHAR               BTK[32];        //Base Transient Key
+       BOOLEAN             CCKMLinkUpFlag;
+       ULONG               CCKMRN;    //(Re)Association request number.
+       LARGE_INTEGER       CCKMBeaconAtJoinTimeStamp;  //TSF timer for Re-assocaite to the new AP
+       UCHAR               AironetCellPowerLimit;      //in dBm
+       UCHAR               AironetIPAddress[4];        //eg. 192.168.1.1
+       BOOLEAN             CCXAdjacentAPReportFlag;    //flag for determining report Assoc Lost time
+       CHAR                CCXAdjacentAPSsid[MAX_LEN_OF_SSID]; //Adjacent AP's SSID report
+       UCHAR               CCXAdjacentAPSsidLen;               // the actual ssid length in used
+       UCHAR               CCXAdjacentAPBssid[MAC_ADDR_LEN];         //Adjacent AP's BSSID report
+       USHORT              CCXAdjacentAPChannel;
+       ULONG               CCXAdjacentAPLinkDownTime;  //for Spec S32.
+
+       RALINK_TIMER_STRUCT     StaQuickResponeForRateUpTimer;
+       BOOLEAN                         StaQuickResponeForRateUpTimerRunning;
+
+       UCHAR                   DtimCount;      // 0.. DtimPeriod-1
+       UCHAR                   DtimPeriod;     // default = 3
+
+#ifdef QOS_DLS_SUPPORT
+       RT_802_11_DLS           DLSEntry[MAX_NUM_OF_DLS_ENTRY];
+       UCHAR                           DlsReplayCounter[8];
+#endif // QOS_DLS_SUPPORT //
+       ////////////////////////////////////////////////////////////////////////////////////////
+       // This is only for WHQL test.
+       BOOLEAN                         WhqlTest;
+       ////////////////////////////////////////////////////////////////////////////////////////
+
+    RALINK_TIMER_STRUCT WpaDisassocAndBlockAssocTimer;
+    // Fast Roaming
+       BOOLEAN                 bFastRoaming;       // 0:disable fast roaming, 1:enable fast roaming
+       CHAR                    dBmToRoam;          // the condition to roam when receiving Rssi less than this value. It's negative value.
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+    BOOLEAN             IEEE8021X;
+    BOOLEAN             IEEE8021x_required_keys;
+    CIPHER_KEY         DesireSharedKey[4];     // Record user desired WEP keys
+    UCHAR               DesireSharedKeyId;
+
+    // 0: driver ignores wpa_supplicant
+    // 1: wpa_supplicant initiates scanning and AP selection
+    // 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters
+    UCHAR               WpaSupplicantUP;
+       UCHAR                           WpaSupplicantScanCount;
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+    CHAR                dev_name[16];
+    USHORT              OriDevType;
+
+    BOOLEAN             bTGnWifiTest;
+       BOOLEAN                     bScanReqIsFromWebUI;
+
+       HTTRANSMIT_SETTING                              HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI.
+       DESIRED_TRANSMIT_SETTING        DesiredTransmitSetting;
+       RT_HT_PHY_INFO                                  DesiredHtPhyInfo;
+       BOOLEAN                                                 bAutoTxRateSwitch;
+
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+       UCHAR                           IEEE80211dClientMode;
+       UCHAR                           StaOriCountryCode[3];
+       UCHAR                           StaOriGeography;
+#endif // EXT_BUILD_CHANNEL_LIST //
+} STA_ADMIN_CONFIG, *PSTA_ADMIN_CONFIG;
+
+// This data structure keep the current active BSS/IBSS's configuration that this STA
+// had agreed upon joining the network. Which means these parameters are usually decided
+// by the BSS/IBSS creator instead of user configuration. Data in this data structurre
+// is valid only when either ADHOC_ON(pAd) or INFRA_ON(pAd) is TRUE.
+// Normally, after SCAN or failed roaming attempts, we need to recover back to
+// the current active settings.
+typedef struct _STA_ACTIVE_CONFIG {
+       USHORT      Aid;
+       USHORT      AtimWin;                // in kusec; IBSS parameter set element
+       USHORT      CapabilityInfo;
+       USHORT      CfpMaxDuration;
+       USHORT      CfpPeriod;
+
+       // Copy supported rate from desired AP's beacon. We are trying to match
+       // AP's supported and extended rate settings.
+       UCHAR       SupRate[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR       ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR       SupRateLen;
+       UCHAR       ExtRateLen;
+       // Copy supported ht from desired AP's beacon. We are trying to match
+       RT_HT_PHY_INFO          SupportedPhyInfo;
+       RT_HT_CAPABILITY        SupportedHtPhy;
+} STA_ACTIVE_CONFIG, *PSTA_ACTIVE_CONFIG;
+
+#ifdef RT2870
+// for USB interface, avoid in interrupt when write key
+typedef struct   RT_ADD_PAIRWISE_KEY_ENTRY {
+        NDIS_802_11_MAC_ADDRESS         MacAddr;
+        USHORT                          MacTabMatchWCID;        // ASIC
+        CIPHER_KEY                      CipherKey;
+} RT_ADD_PAIRWISE_KEY_ENTRY,*PRT_ADD_PAIRWISE_KEY_ENTRY;
+#endif // RT2870 //
+#endif // CONFIG_STA_SUPPORT //
+
+// ----------- start of AP --------------------------
+// AUTH-RSP State Machine Aux data structure
+typedef struct _AP_MLME_AUX {
+       UCHAR               Addr[MAC_ADDR_LEN];
+       USHORT              Alg;
+       CHAR                Challenge[CIPHER_TEXT_LEN];
+} AP_MLME_AUX, *PAP_MLME_AUX;
+
+// structure to define WPA Group Key Rekey Interval
+typedef struct PACKED _RT_802_11_WPA_REKEY {
+       ULONG ReKeyMethod;          // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based
+       ULONG ReKeyInterval;        // time-based: seconds, packet-based: kilo-packets
+} RT_WPA_REKEY,*PRT_WPA_REKEY, RT_802_11_WPA_REKEY, *PRT_802_11_WPA_REKEY;
+
+typedef struct _MAC_TABLE_ENTRY {
+       //Choose 1 from ValidAsWDS and ValidAsCLI  to validize.
+       BOOLEAN         ValidAsCLI;             // Sta mode, set this TRUE after Linkup,too.
+       BOOLEAN         ValidAsWDS;     // This is WDS Entry. only for AP mode.
+       BOOLEAN         ValidAsApCli;   //This is a AP-Client entry, only for AP mode which enable AP-Client functions.
+       BOOLEAN         ValidAsMesh;
+       BOOLEAN         ValidAsDls;     // This is DLS Entry. only for STA mode.
+       BOOLEAN         isCached;
+       BOOLEAN         bIAmBadAtheros; // Flag if this is Atheros chip that has IOT problem.  We need to turn on RTS/CTS protection.
+
+       UCHAR           EnqueueEapolStartTimerRunning;  // Enqueue EAPoL-Start for triggering EAP SM
+       //jan for wpa
+       // record which entry revoke MIC Failure , if it leaves the BSS itself, AP won't update aMICFailTime MIB
+       UCHAR           CMTimerRunning;
+       UCHAR           apidx;                  // MBSS number
+       UCHAR           RSNIE_Len;
+       UCHAR           RSN_IE[MAX_LEN_OF_RSNIE];
+       UCHAR           ANonce[LEN_KEY_DESC_NONCE];
+       UCHAR           R_Counter[LEN_KEY_DESC_REPLAY];
+       UCHAR           PTK[64];
+       UCHAR           ReTryCounter;
+       RALINK_TIMER_STRUCT                 RetryTimer;
+       RALINK_TIMER_STRUCT                                     EnqueueStartForPSKTimer;        // A timer which enqueue EAPoL-Start for triggering PSK SM
+       NDIS_802_11_AUTHENTICATION_MODE     AuthMode;   // This should match to whatever microsoft defined
+       NDIS_802_11_WEP_STATUS              WepStatus;
+       AP_WPA_STATE    WpaState;
+       GTK_STATE       GTKState;
+       USHORT          PortSecured;
+       NDIS_802_11_PRIVACY_FILTER  PrivacyFilter;      // PrivacyFilter enum for 802.1X
+       CIPHER_KEY      PairwiseKey;
+       PVOID           pAd;
+    INT                                PMKID_CacheIdx;
+    UCHAR                      PMKID[LEN_PMKID];
+
+
+       UCHAR           Addr[MAC_ADDR_LEN];
+       UCHAR           PsMode;
+       SST             Sst;
+       AUTH_STATE      AuthState; // for SHARED KEY authentication state machine used only
+       BOOLEAN                 IsReassocSta;   // Indicate whether this is a reassociation procedure
+       USHORT          Aid;
+       USHORT          CapabilityInfo;
+       UCHAR           LastRssi;
+       ULONG           NoDataIdleCount;
+       UINT16                  StationKeepAliveCount; // unit: second
+       ULONG           PsQIdleCount;
+       QUEUE_HEADER    PsQueue;
+
+       UINT32                  StaConnectTime;         // the live time of this station since associated with AP
+
+
+#ifdef DOT11_N_SUPPORT
+       BOOLEAN                 bSendBAR;
+       USHORT                  NoBADataCountDown;
+
+       UINT32                  CachedBuf[16];          // UINT (4 bytes) for alignment
+       UINT                    TxBFCount; // 3*3
+#endif // DOT11_N_SUPPORT //
+       UINT                    FIFOCount;
+       UINT                    DebugFIFOCount;
+       UINT                    DebugTxCount;
+    BOOLEAN                    bDlsInit;
+
+
+//====================================================
+//WDS entry needs these
+// rt2860 add this. if ValidAsWDS==TRUE, MatchWDSTabIdx is the index in WdsTab.MacTab
+       UINT                    MatchWDSTabIdx;
+       UCHAR           MaxSupportedRate;
+       UCHAR           CurrTxRate;
+       UCHAR           CurrTxRateIndex;
+       // to record the each TX rate's quality. 0 is best, the bigger the worse.
+       USHORT          TxQuality[MAX_STEP_OF_TX_RATE_SWITCH];
+//     USHORT          OneSecTxOkCount;
+       UINT32                  OneSecTxNoRetryOkCount;
+       UINT32          OneSecTxRetryOkCount;
+       UINT32          OneSecTxFailCount;
+       UINT32                  ContinueTxFailCnt;
+       UINT32          CurrTxRateStableTime; // # of second in current TX rate
+       UCHAR           TxRateUpPenalty;      // extra # of second penalty due to last unstable condition
+//====================================================
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+       UINT                    MatchDlsEntryIdx; // indicate the index in pAd->StaCfg.DLSEntry
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+       BOOLEAN         fNoisyEnvironment;
+       BOOLEAN                 fLastSecAccordingRSSI;
+       UCHAR           LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down
+       CHAR                    LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction
+       ULONG                   LastTxOkCount;
+       UCHAR           PER[MAX_STEP_OF_TX_RATE_SWITCH];
+
+       // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular
+       // BOOLEAN control, either ON or OFF. These flags should always be accessed via
+       // CLIENT_STATUS_TEST_FLAG(), CLIENT_STATUS_SET_FLAG(), CLIENT_STATUS_CLEAR_FLAG() macros.
+       // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition. fCLIENT_STATUS_AMSDU_INUSED
+       ULONG           ClientStatusFlags;
+
+       // TODO: Shall we move that to DOT11_N_SUPPORT???
+       HTTRANSMIT_SETTING      HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI.
+
+#ifdef DOT11_N_SUPPORT
+       // HT EWC MIMO-N used parameters
+       USHORT          RXBAbitmap;     // fill to on-chip  RXWI_BA_BITMASK in 8.1.3RX attribute entry format
+       USHORT          TXBAbitmap;     // This bitmap as originator, only keep in software used to mark AMPDU bit in TXWI
+       USHORT          TXAutoBAbitmap;
+       USHORT          BADeclineBitmap;
+       USHORT          BARecWcidArray[NUM_OF_TID];     // The mapping wcid of recipient session. if RXBAbitmap bit is masked
+       USHORT          BAOriWcidArray[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked
+       USHORT          BAOriSequence[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked
+
+       // 802.11n features.
+       UCHAR           MpduDensity;
+       UCHAR           MaxRAmpduFactor;
+       UCHAR           AMsduSize;
+       UCHAR           MmpsMode;       // MIMO power save more.
+
+       HT_CAPABILITY_IE                HTCapability;
+
+#ifdef DOT11N_DRAFT3
+       UCHAR           BSS2040CoexistenceMgmtSupport;
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+       BOOLEAN         bAutoTxRateSwitch;
+
+       UCHAR       RateLen;
+       struct _MAC_TABLE_ENTRY *pNext;
+    USHORT      TxSeq[NUM_OF_TID];
+       USHORT          NonQosDataSeq;
+
+       RSSI_SAMPLE     RssiSample;
+
+       UINT32                  TXMCSExpected[16];
+       UINT32                  TXMCSSuccessful[16];
+       UINT32                  TXMCSFailed[16];
+       UINT32                  TXMCSAutoFallBack[16][16];
+
+#ifdef CONFIG_STA_SUPPORT
+       ULONG                   LastBeaconRxTime;
+#endif // CONFIG_STA_SUPPORT //
+} MAC_TABLE_ENTRY, *PMAC_TABLE_ENTRY;
+
+typedef struct _MAC_TABLE {
+       USHORT                  Size;
+       MAC_TABLE_ENTRY *Hash[HASH_TABLE_SIZE];
+       MAC_TABLE_ENTRY Content[MAX_LEN_OF_MAC_TABLE];
+       QUEUE_HEADER    McastPsQueue;
+       ULONG           PsQIdleCount;
+       BOOLEAN         fAnyStationInPsm;
+       BOOLEAN         fAnyStationBadAtheros;  // Check if any Station is atheros 802.11n Chip.  We need to use RTS/CTS with Atheros 802,.11n chip.
+       BOOLEAN                 fAnyTxOPForceDisable;   // Check if it is necessary to disable BE TxOP
+       BOOLEAN                 fAllStationAsRalink;    // Check if all stations are ralink-chipset
+#ifdef DOT11_N_SUPPORT
+       BOOLEAN         fAnyStationIsLegacy;    // Check if I use legacy rate to transmit to my BSS Station/
+       BOOLEAN         fAnyStationNonGF;               // Check if any Station can't support GF.
+       BOOLEAN         fAnyStation20Only;              // Check if any Station can't support GF.
+       BOOLEAN                 fAnyStationMIMOPSDynamic; // Check if any Station is MIMO Dynamic
+       BOOLEAN         fAnyBASession;   // Check if there is BA session.  Force turn on RTS/CTS
+#endif // DOT11_N_SUPPORT //
+} MAC_TABLE, *PMAC_TABLE;
+
+#ifdef DOT11_N_SUPPORT
+#define IS_HT_STA(_pMacEntry)  \
+       (_pMacEntry->MaxHTPhyMode.field.MODE >= MODE_HTMIX)
+
+#define IS_HT_RATE(_pMacEntry) \
+       (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
+
+#define PEER_IS_HT_RATE(_pMacEntry)    \
+       (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
+#endif // DOT11_N_SUPPORT //
+
+typedef struct _WDS_ENTRY {
+       BOOLEAN         Valid;
+       UCHAR           Addr[MAC_ADDR_LEN];
+       ULONG           NoDataIdleCount;
+       struct _WDS_ENTRY *pNext;
+} WDS_ENTRY, *PWDS_ENTRY;
+
+typedef struct  _WDS_TABLE_ENTRY {
+       USHORT                  Size;
+       UCHAR           WdsAddr[MAC_ADDR_LEN];
+       WDS_ENTRY       *Hash[HASH_TABLE_SIZE];
+       WDS_ENTRY       Content[MAX_LEN_OF_MAC_TABLE];
+       UCHAR           MaxSupportedRate;
+       UCHAR           CurrTxRate;
+       USHORT          TxQuality[MAX_LEN_OF_SUPPORTED_RATES];
+       USHORT          OneSecTxOkCount;
+       USHORT          OneSecTxRetryOkCount;
+       USHORT          OneSecTxFailCount;
+       ULONG           CurrTxRateStableTime; // # of second in current TX rate
+       UCHAR           TxRateUpPenalty;      // extra # of second penalty due to last unstable condition
+} WDS_TABLE_ENTRY, *PWDS_TABLE_ENTRY;
+
+typedef struct _RT_802_11_WDS_ENTRY {
+       PNET_DEV                        dev;
+       UCHAR                           Valid;
+       UCHAR                           PhyMode;
+       UCHAR                           PeerWdsAddr[MAC_ADDR_LEN];
+       UCHAR                           MacTabMatchWCID;        // ASIC
+       NDIS_802_11_WEP_STATUS  WepStatus;
+       UCHAR                                   KeyIdx;
+       CIPHER_KEY              WdsKey;
+       HTTRANSMIT_SETTING                              HTPhyMode, MaxHTPhyMode, MinHTPhyMode;
+       RT_HT_PHY_INFO                                  DesiredHtPhyInfo;
+       BOOLEAN                                                 bAutoTxRateSwitch;
+       DESIRED_TRANSMIT_SETTING        DesiredTransmitSetting; // Desired transmit setting.
+} RT_802_11_WDS_ENTRY, *PRT_802_11_WDS_ENTRY;
+
+typedef struct _WDS_TABLE {
+       UCHAR               Mode;
+       ULONG               Size;
+       RT_802_11_WDS_ENTRY     WdsEntry[MAX_WDS_ENTRY];
+} WDS_TABLE, *PWDS_TABLE;
+
+typedef struct _APCLI_STRUCT {
+       PNET_DEV                                dev;
+#ifdef RTL865X_SOC
+       unsigned int            mylinkid;
+#endif
+       BOOLEAN                 Enable; // Set it as 1 if the apcli interface was configured to "1"  or by iwpriv cmd "ApCliEnable"
+       BOOLEAN                 Valid;  // Set it as 1 if the apcli interface associated success to remote AP.
+       UCHAR                                   MacTabWCID;     //WCID value, which point to the entry of ASIC Mac table.
+       UCHAR                   SsidLen;
+       CHAR                    Ssid[MAX_LEN_OF_SSID];
+
+       UCHAR                   CfgSsidLen;
+       CHAR                    CfgSsid[MAX_LEN_OF_SSID];
+       UCHAR                   CfgApCliBssid[ETH_LENGTH_OF_ADDRESS];
+       UCHAR                   CurrentAddress[ETH_LENGTH_OF_ADDRESS];
+
+       ULONG                   ApCliRcvBeaconTime;
+
+       ULONG                   CtrlCurrState;
+       ULONG                   SyncCurrState;
+       ULONG                   AuthCurrState;
+       ULONG                   AssocCurrState;
+       ULONG                                   WpaPskCurrState;
+
+       USHORT                  AuthReqCnt;
+       USHORT                  AssocReqCnt;
+
+       ULONG                   ClientStatusFlags;
+       UCHAR                   MpduDensity;
+
+       NDIS_802_11_AUTHENTICATION_MODE     AuthMode;   // This should match to whatever microsoft defined
+       NDIS_802_11_WEP_STATUS              WepStatus;
+
+       // Add to support different cipher suite for WPA2/WPA mode
+       NDIS_802_11_ENCRYPTION_STATUS           GroupCipher;            // Multicast cipher suite
+       NDIS_802_11_ENCRYPTION_STATUS           PairCipher;                     // Unicast cipher suite
+       BOOLEAN                                                         bMixCipher;                     // Indicate current Pair & Group use different cipher suites
+       USHORT                                                          RsnCapability;
+
+       UCHAR           PSK[100];                               // reserve PSK key material
+       UCHAR       PSKLen;
+       UCHAR       PMK[32];                // WPA PSK mode PMK
+       //UCHAR       PTK[64];                // WPA PSK mode PTK
+       UCHAR           GTK[32];                                // GTK from authenticator
+
+       //CIPHER_KEY            PairwiseKey;
+       CIPHER_KEY      SharedKey[SHARE_KEY_NUM];
+       UCHAR           DefaultKeyId;
+
+       // WPA 802.1x port control, WPA_802_1X_PORT_SECURED, WPA_802_1X_PORT_NOT_SECURED
+       //UCHAR       PortSecured;
+
+       // store RSN_IE built by driver
+       UCHAR           RSN_IE[MAX_LEN_OF_RSNIE];  // The content saved here should be convert to little-endian format.
+       UCHAR           RSNIE_Len;
+
+       // For WPA countermeasures
+       ULONG       LastMicErrorTime;   // record last MIC error time
+       //ULONG       MicErrCnt;          // Should be 0, 1, 2, then reset to zero (after disassoiciation).
+       BOOLEAN                 bBlockAssoc; // Block associate attempt for 60 seconds after counter measure occurred.
+
+       // For WPA-PSK supplicant state
+       //WPA_STATE     WpaState;           // Default is SS_NOTUSE
+       //UCHAR         ReplayCounter[8];
+       //UCHAR         ANonce[32];         // ANonce for WPA-PSK from authenticator
+       UCHAR           SNonce[32];         // SNonce for WPA-PSK
+       UCHAR                   GNonce[32];                     // GNonce for WPA-PSK from authenticator
+
+       HTTRANSMIT_SETTING                              HTPhyMode, MaxHTPhyMode, MinHTPhyMode;
+       RT_HT_PHY_INFO                                  DesiredHtPhyInfo;
+       BOOLEAN                                                 bAutoTxRateSwitch;
+       DESIRED_TRANSMIT_SETTING        DesiredTransmitSetting; // Desired transmit setting.
+} APCLI_STRUCT, *PAPCLI_STRUCT;
+
+// ----------- end of AP ----------------------------
+
+#ifdef BLOCK_NET_IF
+typedef struct _BLOCK_QUEUE_ENTRY
+{
+       BOOLEAN SwTxQueueBlockFlag;
+       LIST_HEADER NetIfList;
+} BLOCK_QUEUE_ENTRY, *PBLOCK_QUEUE_ENTRY;
+#endif // BLOCK_NET_IF //
+
+struct wificonf
+{
+       BOOLEAN bShortGI;
+       BOOLEAN bGreenField;
+};
+
+
+
+typedef struct _INF_PCI_CONFIG
+{
+       PUCHAR                  CSRBaseAddress;     // PCI MMIO Base Address, all access will use
+}INF_PCI_CONFIG;
+
+typedef struct _INF_USB_CONFIG
+{
+       UINT                BulkInEpAddr;               // bulk-in endpoint address
+       UINT                BulkOutEpAddr[6];   // bulk-out endpoint address
+
+}INF_USB_CONFIG;
+
+#ifdef IKANOS_VX_1X0
+       typedef void (*IkanosWlanTxCbFuncP)(void *, void *);
+
+       struct IKANOS_TX_INFO
+       {
+               struct net_device *netdev;
+               IkanosWlanTxCbFuncP *fp;
+       };
+#endif // IKANOS_VX_1X0 //
+
+#ifdef NINTENDO_AP
+typedef struct _NINDO_CTRL_BLOCK {
+
+       RT_NINTENDO_TABLE       DS_TABLE;
+
+#ifdef CHIP25XX
+       spinlock_t                      NINTENDO_TABLE_Lock;
+#else
+       NDIS_SPIN_LOCK          NINTENDO_TABLE_Lock;
+#endif // CHIP25XX //
+
+       UCHAR                           NINTENDO_UP_BUFFER[512];
+       UCHAR                           Local_KeyIdx;
+       CIPHER_KEY                      Local_SharedKey;
+       UCHAR                           Local_bHideSsid;
+       UCHAR                           Local_AuthMode;
+       UCHAR                           Local_WepStatus;
+       USHORT                          Local_CapabilityInfo;
+} NINDO_CTRL_BLOCK;
+#endif // NINTENDO_AP //
+
+
+#ifdef DBG_DIAGNOSE
+#define DIAGNOSE_TIME  10   // 10 sec
+typedef struct _RtmpDiagStrcut_
+{      // Diagnosis Related element
+       unsigned char           inited;
+       unsigned char   qIdx;
+       unsigned char   ArrayStartIdx;
+       unsigned char           ArrayCurIdx;
+       // Tx Related Count
+       USHORT                  TxDataCnt[DIAGNOSE_TIME];
+       USHORT                  TxFailCnt[DIAGNOSE_TIME];
+//     USHORT                  TxDescCnt[DIAGNOSE_TIME][16];           // TxDesc queue length in scale of 0~14, >=15
+       USHORT                  TxDescCnt[DIAGNOSE_TIME][24]; // 3*3    // TxDesc queue length in scale of 0~14, >=15
+//     USHORT                  TxMcsCnt[DIAGNOSE_TIME][16];                    // TxDate MCS Count in range from 0 to 15, step in 1.
+       USHORT                  TxMcsCnt[DIAGNOSE_TIME][24]; // 3*3
+       USHORT                  TxSWQueCnt[DIAGNOSE_TIME][9];           // TxSwQueue length in scale of 0, 1, 2, 3, 4, 5, 6, 7, >=8
+
+       USHORT                  TxAggCnt[DIAGNOSE_TIME];
+       USHORT                  TxNonAggCnt[DIAGNOSE_TIME];
+//     USHORT                  TxAMPDUCnt[DIAGNOSE_TIME][16];          // 10 sec, TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1.
+       USHORT                  TxAMPDUCnt[DIAGNOSE_TIME][24]; // 3*3 // 10 sec, TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1.
+       USHORT                  TxRalinkCnt[DIAGNOSE_TIME];                     // TxRalink Aggregation Count in 1 sec scale.
+       USHORT                  TxAMSDUCnt[DIAGNOSE_TIME];                      // TxAMSUD Aggregation Count in 1 sec scale.
+
+       // Rx Related Count
+       USHORT                  RxDataCnt[DIAGNOSE_TIME];                       // Rx Total Data count.
+       USHORT                  RxCrcErrCnt[DIAGNOSE_TIME];
+//     USHORT                  RxMcsCnt[DIAGNOSE_TIME][16];            // Rx MCS Count in range from 0 to 15, step in 1.
+       USHORT                  RxMcsCnt[DIAGNOSE_TIME][24]; // 3*3
+}RtmpDiagStruct;
+#endif // DBG_DIAGNOSE //
+
+
+//
+//  The miniport adapter structure
+//
+typedef struct _RTMP_ADAPTER
+{
+       PVOID                                   OS_Cookie;      // save specific structure relative to OS
+       PNET_DEV                                net_dev;
+       ULONG                                   VirtualIfCnt;
+
+
+
+       NDIS_SPIN_LOCK          irq_lock;
+       UCHAR                   irq_disabled;
+
+#ifdef RT2870
+/*****************************************************************************************/
+/*      USB related parameters                                                           */
+/*****************************************************************************************/
+       struct usb_config_descriptor            *config;
+       UINT                                                            BulkInEpAddr;           // bulk-in endpoint address
+       UINT                                                            BulkOutEpAddr[6];       // bulk-out endpoint address
+
+       UINT                                                            NumberOfPipes;
+       USHORT                                                          BulkOutMaxPacketSize;
+       USHORT                                                          BulkInMaxPacketSize;
+
+       //======Control Flags
+       LONG                            PendingIoCount;
+       ULONG                                           BulkFlags;
+       BOOLEAN                     bUsbTxBulkAggre;    // Flags for bulk out data priority
+
+
+       //======Timer Thread
+       RT2870_TIMER_QUEUE              TimerQ;
+       NDIS_SPIN_LOCK                  TimerQLock;
+
+
+       //======Cmd Thread
+       CmdQ                                    CmdQ;
+       NDIS_SPIN_LOCK                  CmdQLock;                               // CmdQLock spinlock
+
+       BOOLEAN                                 TimerFunc_kill;
+       BOOLEAN                                 mlme_kill;
+
+
+       //======Semaphores (event)
+       struct semaphore                        mlme_semaphore;                 /* to sleep thread on   */
+       struct semaphore                        RTUSBCmd_semaphore;             /* to sleep thread on   */
+       struct semaphore                        RTUSBTimer_semaphore;
+#ifdef INF_AMAZON_SE
+       struct semaphore                        UsbVendorReq_semaphore;
+       PVOID                                           UsbVendorReqBuf;
+#endif // INF_AMAZON_SE //
+       struct completion                       TimerQComplete;
+       struct completion                       mlmeComplete;
+       struct completion                       CmdQComplete;
+       wait_queue_head_t                       *wait;
+
+       //======Lock for 2870 ATE
+#ifdef RALINK_ATE
+       NDIS_SPIN_LOCK                  GenericLock;            // ATE Tx/Rx generic spinlock
+#endif // RALINK_ATE //
+
+#endif // RT2870 //
+
+
+/*****************************************************************************************/
+       /*      Both PCI/USB related parameters                                                  */
+/*****************************************************************************************/
+
+
+/*****************************************************************************************/
+/*      Tx related parameters                                                           */
+/*****************************************************************************************/
+       BOOLEAN                 DeQueueRunning[NUM_OF_TX_RING];  // for ensuring RTUSBDeQueuePacket get call once
+       NDIS_SPIN_LOCK          DeQueueLock[NUM_OF_TX_RING];
+
+#ifdef RT2870
+       // Data related context and AC specified, 4 AC supported
+       NDIS_SPIN_LOCK                  BulkOutLock[6];                 // BulkOut spinlock for 4 ACs
+       NDIS_SPIN_LOCK                  MLMEBulkOutLock;        // MLME BulkOut lock
+
+       HT_TX_CONTEXT                   TxContext[NUM_OF_TX_RING];
+       NDIS_SPIN_LOCK                  TxContextQueueLock[NUM_OF_TX_RING];             // TxContextQueue spinlock
+
+       // 4 sets of Bulk Out index and pending flag
+       UCHAR                                   NextBulkOutIndex[4];    // only used for 4 EDCA bulkout pipe
+
+       BOOLEAN                                 BulkOutPending[6];      // used for total 6 bulkout pipe
+       UCHAR                                   bulkResetPipeid;
+       BOOLEAN                                 MgmtBulkPending;
+       ULONG                                   bulkResetReq[6];
+#endif // RT2870 //
+
+       // resource for software backlog queues
+       QUEUE_HEADER            TxSwQueue[NUM_OF_TX_RING];  // 4 AC + 1 HCCA
+       NDIS_SPIN_LOCK          TxSwQueueLock[NUM_OF_TX_RING];  // TxSwQueue spinlock
+
+       RTMP_DMABUF             MgmtDescRing;                   // Shared memory for MGMT descriptors
+       RTMP_MGMT_RING          MgmtRing;
+       NDIS_SPIN_LOCK          MgmtRingLock;                   // Prio Ring spinlock
+
+
+/*****************************************************************************************/
+/*      Rx related parameters                                                           */
+/*****************************************************************************************/
+
+
+#ifdef RT2870
+       RX_CONTEXT                              RxContext[RX_RING_SIZE];  // 1 for redundant multiple IRP bulk in.
+       NDIS_SPIN_LOCK                  BulkInLock;                             // BulkIn spinlock for 4 ACs
+       UCHAR                                   PendingRx;                              // The Maxima pending Rx value should be        RX_RING_SIZE.
+       UCHAR                                   NextRxBulkInIndex;              // Indicate the current RxContext Index which hold by Host controller.
+       UCHAR                                   NextRxBulkInReadIndex;  // Indicate the current RxContext Index which driver can read & process it.
+       ULONG                                   NextRxBulkInPosition;   // Want to contatenate 2 URB buffer while 1st is bulkin failed URB. This Position is 1st URB TransferLength.
+       ULONG                                   TransferBufferLength;   // current length of the packet buffer
+       ULONG                                   ReadPosition;                   // current read position in a packet buffer
+#endif // RT2870 //
+
+
+/*****************************************************************************************/
+/*      ASIC related parameters                                                          */
+/*****************************************************************************************/
+       UINT32                  MACVersion;             // MAC version. Record rt2860C(0x28600100) or rt2860D (0x28600101)..
+
+       // ---------------------------
+       // E2PROM
+       // ---------------------------
+       ULONG                   EepromVersion;          // byte 0: version, byte 1: revision, byte 2~3: unused
+       UCHAR                   EEPROMAddressNum;       // 93c46=6  93c66=8
+       USHORT                  EEPROMDefaultValue[NUM_EEPROM_BBP_PARMS];
+       ULONG                   FirmwareVersion;        // byte 0: Minor version, byte 1: Major version, otherwise unused.
+
+       // ---------------------------
+       // BBP Control
+       // ---------------------------
+       UCHAR                   BbpWriteLatch[140];     // record last BBP register value written via BBP_IO_WRITE/BBP_IO_WRITE_VY_REG_ID
+       UCHAR                   BbpRssiToDbmDelta;
+       BBP_R66_TUNING          BbpTuning;
+
+       // ----------------------------
+       // RFIC control
+       // ----------------------------
+       UCHAR                   RfIcType;       // RFIC_xxx
+       ULONG                   RfFreqOffset;   // Frequency offset for channel switching
+       RTMP_RF_REGS            LatchRfRegs;    // latch th latest RF programming value since RF IC doesn't support READ
+
+       EEPROM_ANTENNA_STRUC    Antenna;                            // Since ANtenna definition is different for a & g. We need to save it for future reference.
+       EEPROM_NIC_CONFIG2_STRUC    NicConfig2;
+
+       // This soft Rx Antenna Diversity mechanism is used only when user set
+       // RX Antenna = DIVERSITY ON
+       SOFT_RX_ANT_DIVERSITY   RxAnt;
+
+       UCHAR                   RFProgSeq;
+       CHANNEL_TX_POWER        TxPower[MAX_NUM_OF_CHANNELS];       // Store Tx power value for all channels.
+       CHANNEL_TX_POWER        ChannelList[MAX_NUM_OF_CHANNELS];   // list all supported channels for site survey
+       CHANNEL_11J_TX_POWER    TxPower11J[MAX_NUM_OF_11JCHANNELS];       // 802.11j channel and bw
+       CHANNEL_11J_TX_POWER    ChannelList11J[MAX_NUM_OF_11JCHANNELS];   // list all supported channels for site survey
+
+       UCHAR                   ChannelListNum;                     // number of channel in ChannelList[]
+       UCHAR                                   Bbp94;
+       BOOLEAN                                 BbpForCCK;
+       ULONG           Tx20MPwrCfgABand[5];
+       ULONG           Tx20MPwrCfgGBand[5];
+       ULONG           Tx40MPwrCfgABand[5];
+       ULONG           Tx40MPwrCfgGBand[5];
+
+       BOOLEAN     bAutoTxAgcA;                // Enable driver auto Tx Agc control
+       UCHAR       TssiRefA;                                   // Store Tssi reference value as 25 temperature.
+       UCHAR       TssiPlusBoundaryA[5];               // Tssi boundary for increase Tx power to compensate.
+       UCHAR       TssiMinusBoundaryA[5];              // Tssi boundary for decrease Tx power to compensate.
+       UCHAR       TxAgcStepA;                                 // Store Tx TSSI delta increment / decrement value
+       CHAR            TxAgcCompensateA;                       // Store the compensation (TxAgcStep * (idx-1))
+
+       BOOLEAN     bAutoTxAgcG;                // Enable driver auto Tx Agc control
+       UCHAR       TssiRefG;                                   // Store Tssi reference value as 25 temperature.
+       UCHAR       TssiPlusBoundaryG[5];               // Tssi boundary for increase Tx power to compensate.
+       UCHAR       TssiMinusBoundaryG[5];              // Tssi boundary for decrease Tx power to compensate.
+       UCHAR       TxAgcStepG;                                 // Store Tx TSSI delta increment / decrement value
+       CHAR            TxAgcCompensateG;                       // Store the compensation (TxAgcStep * (idx-1))
+
+       //+++For RT2870, the parameteres is start from BGRssiOffset1 ~ BGRssiOffset3
+       CHAR            BGRssiOffset0;                          // Store B/G RSSI#0 Offset value on EEPROM 0x46h
+       CHAR            BGRssiOffset1;                          // Store B/G RSSI#1 Offset value
+       CHAR            BGRssiOffset2;                          // Store B/G RSSI#2 Offset value
+       //---
+
+       //+++For RT2870, the parameteres is start from ARssiOffset1 ~ ARssiOffset3
+       CHAR            ARssiOffset0;                           // Store A RSSI#0 Offset value on EEPROM 0x4Ah
+       CHAR            ARssiOffset1;                           // Store A RSSI#1 Offset value
+       CHAR            ARssiOffset2;                           // Store A RSSI#2 Offset value
+       //---
+
+       CHAR            BLNAGain;                                       // Store B/G external LNA#0 value on EEPROM 0x44h
+       CHAR            ALNAGain0;                                      // Store A external LNA#0 value for ch36~64
+       CHAR            ALNAGain1;                                      // Store A external LNA#1 value for ch100~128
+       CHAR            ALNAGain2;                                      // Store A external LNA#2 value for ch132~165
+
+       // ----------------------------
+       // LED control
+       // ----------------------------
+       MCU_LEDCS_STRUC         LedCntl;
+       USHORT                          Led1;   // read from EEPROM 0x3c
+       USHORT                          Led2;   // EEPROM 0x3e
+       USHORT                          Led3;   // EEPROM 0x40
+       UCHAR                           LedIndicatorStregth;
+       UCHAR                           RssiSingalstrengthOffet;
+    BOOLEAN                            bLedOnScanning;
+       UCHAR                           LedStatus;
+
+/*****************************************************************************************/
+/*      802.11 related parameters                                                        */
+/*****************************************************************************************/
+       // outgoing BEACON frame buffer and corresponding TXD
+       TXWI_STRUC                      BeaconTxWI;
+       PUCHAR                                          BeaconBuf;
+       USHORT                                          BeaconOffset[HW_BEACON_MAX_COUNT];
+
+       // pre-build PS-POLL and NULL frame upon link up. for efficiency purpose.
+       PSPOLL_FRAME                    PsPollFrame;
+       HEADER_802_11                   NullFrame;
+
+#ifdef RT2870
+       TX_CONTEXT                              BeaconContext[BEACON_RING_SIZE];
+       TX_CONTEXT                              NullContext;
+       TX_CONTEXT                              PsPollContext;
+       TX_CONTEXT                              RTSContext;
+#endif // RT2870 //
+
+
+
+//=========AP===========
+
+
+//=======STA===========
+#ifdef CONFIG_STA_SUPPORT
+/* Modified by Wu Xi-Kun 4/21/2006 */
+       // -----------------------------------------------
+       // STA specific configuration & operation status
+       // used only when pAd->OpMode == OPMODE_STA
+       // -----------------------------------------------
+       STA_ADMIN_CONFIG        StaCfg;           // user desired settings
+       STA_ACTIVE_CONFIG       StaActive;         // valid only when ADHOC_ON(pAd) || INFRA_ON(pAd)
+       CHAR                    nickname[IW_ESSID_MAX_SIZE+1]; // nickname, only used in the iwconfig i/f
+       NDIS_MEDIA_STATE        PreMediaState;
+#endif // CONFIG_STA_SUPPORT //
+
+//=======Common===========
+       // OP mode: either AP or STA
+       UCHAR                   OpMode;                     // OPMODE_STA, OPMODE_AP
+
+       NDIS_MEDIA_STATE        IndicateMediaState;                     // Base on Indication state, default is NdisMediaStateDisConnected
+
+
+       // configuration: read from Registry & E2PROM
+       BOOLEAN                 bLocalAdminMAC;             // Use user changed MAC
+       UCHAR                   PermanentAddress[MAC_ADDR_LEN];    // Factory default MAC address
+       UCHAR                   CurrentAddress[MAC_ADDR_LEN];      // User changed MAC address
+
+       // ------------------------------------------------------
+       // common configuration to both OPMODE_STA and OPMODE_AP
+       // ------------------------------------------------------
+       COMMON_CONFIG           CommonCfg;
+       MLME_STRUCT             Mlme;
+
+       // AP needs those vaiables for site survey feature.
+       MLME_AUX                MlmeAux;           // temporary settings used during MLME state machine
+       BSS_TABLE               ScanTab;           // store the latest SCAN result
+
+       //About MacTab, the sta driver will use #0 and #1 for multicast and AP.
+       MAC_TABLE                 MacTab;     // ASIC on-chip WCID entry table.  At TX, ASIC always use key according to this on-chip table.
+       NDIS_SPIN_LOCK          MacTabLock;
+
+#ifdef DOT11_N_SUPPORT
+       BA_TABLE                        BATable;
+#endif // DOT11_N_SUPPORT //
+       NDIS_SPIN_LOCK          BATabLock;
+       RALINK_TIMER_STRUCT RECBATimer;
+
+       // encryption/decryption KEY tables
+       CIPHER_KEY              SharedKey[MAX_MBSSID_NUM][4]; // STA always use SharedKey[BSS0][0..3]
+
+               // RX re-assembly buffer for fragmentation
+       FRAGMENT_FRAME          FragFrame;                  // Frame storage for fragment frame
+
+       // various Counters
+       COUNTER_802_3           Counters8023;               // 802.3 counters
+       COUNTER_802_11          WlanCounters;               // 802.11 MIB counters
+       COUNTER_RALINK          RalinkCounters;             // Ralink propriety counters
+       COUNTER_DRS             DrsCounters;                // counters for Dynamic TX Rate Switching
+       PRIVATE_STRUC           PrivateInfo;                // Private information & counters
+
+       // flags, see fRTMP_ADAPTER_xxx flags
+       ULONG                   Flags;                      // Represent current device status
+
+       // current TX sequence #
+       USHORT                  Sequence;
+
+       // Control disconnect / connect event generation
+       //+++Didn't used anymore
+       ULONG                   LinkDownTime;
+       //---
+       ULONG                   LastRxRate;
+       ULONG                   LastTxRate;
+       //+++Used only for Station
+       BOOLEAN                 bConfigChanged;         // Config Change flag for the same SSID setting
+       //---
+
+       ULONG                   ExtraInfo;              // Extra information for displaying status
+       ULONG                   SystemErrorBitmap;      // b0: E2PROM version error
+
+       //+++Didn't used anymore
+       ULONG                   MacIcVersion;           // MAC/BBP serial interface issue solved after ver.D
+       //---
+
+       // ---------------------------
+       // System event log
+       // ---------------------------
+       RT_802_11_EVENT_TABLE   EventTab;
+
+
+       BOOLEAN         HTCEnable;
+
+       /*****************************************************************************************/
+       /*      Statistic related parameters                                                     */
+       /*****************************************************************************************/
+#ifdef RT2870
+       ULONG                                           BulkOutDataOneSecCount;
+       ULONG                                           BulkInDataOneSecCount;
+       ULONG                                           BulkLastOneSecCount; // BulkOutDataOneSecCount + BulkInDataOneSecCount
+       ULONG                                           watchDogRxCnt;
+       ULONG                                           watchDogRxOverFlowCnt;
+       ULONG                                           watchDogTxPendingCnt[NUM_OF_TX_RING];
+#endif // RT2870 //
+
+       BOOLEAN                                         bUpdateBcnCntDone;
+       ULONG                                           watchDogMacDeadlock;    // prevent MAC/BBP into deadlock condition
+       // ----------------------------
+       // DEBUG paramerts
+       // ----------------------------
+       //ULONG         DebugSetting[4];
+       BOOLEAN         bBanAllBaSetup;
+       BOOLEAN         bPromiscuous;
+
+       // ----------------------------
+       // rt2860c emulation-use Parameters
+       // ----------------------------
+       ULONG           rtsaccu[30];
+       ULONG           ctsaccu[30];
+       ULONG           cfendaccu[30];
+       ULONG           bacontent[16];
+       ULONG           rxint[RX_RING_SIZE+1];
+       UCHAR           rcvba[60];
+       BOOLEAN         bLinkAdapt;
+       BOOLEAN         bForcePrintTX;
+       BOOLEAN         bForcePrintRX;
+       BOOLEAN         bDisablescanning;               //defined in RT2870 USB
+       BOOLEAN         bStaFifoTest;
+       BOOLEAN         bProtectionTest;
+       BOOLEAN         bHCCATest;
+       BOOLEAN         bGenOneHCCA;
+       BOOLEAN         bBroadComHT;
+       //+++Following add from RT2870 USB.
+       ULONG           BulkOutReq;
+       ULONG           BulkOutComplete;
+       ULONG           BulkOutCompleteOther;
+       ULONG           BulkOutCompleteCancel;  // seems not use now?
+       ULONG           BulkInReq;
+       ULONG           BulkInComplete;
+       ULONG           BulkInCompleteFail;
+       //---
+
+    struct wificonf                    WIFItestbed;
+
+#ifdef RALINK_ATE
+       ATE_INFO                                ate;
+#ifdef RT2870
+       BOOLEAN                                 ContinBulkOut;          //ATE bulk out control
+       BOOLEAN                                 ContinBulkIn;           //ATE bulk in control
+       atomic_t                                BulkOutRemained;
+       atomic_t                                BulkInRemained;
+#endif // RT2870 //
+#endif // RALINK_ATE //
+
+#ifdef DOT11_N_SUPPORT
+       struct reordering_mpdu_pool mpdu_blk_pool;
+#endif // DOT11_N_SUPPORT //
+
+       ULONG                                   OneSecondnonBEpackets;          // record non BE packets per second
+
+#if WIRELESS_EXT >= 12
+    struct iw_statistics    iw_stats;
+#endif
+
+       struct net_device_stats stats;
+
+#ifdef BLOCK_NET_IF
+       BLOCK_QUEUE_ENTRY               blockQueueTab[NUM_OF_TX_RING];
+#endif // BLOCK_NET_IF //
+
+
+
+#ifdef MULTIPLE_CARD_SUPPORT
+       INT32                                   MC_RowID;
+       UCHAR                                   MC_FileName[256];
+#endif // MULTIPLE_CARD_SUPPORT //
+
+       ULONG                                   TbttTickCount;
+#ifdef PCI_MSI_SUPPORT
+       BOOLEAN                                 HaveMsi;
+#endif // PCI_MSI_SUPPORT //
+
+
+       UCHAR                                   is_on;
+
+#define TIME_BASE                      (1000000/OS_HZ)
+#define TIME_ONE_SECOND                (1000000/TIME_BASE)
+       UCHAR                                   flg_be_adjust;
+       ULONG                                   be_adjust_last_time;
+
+
+#ifdef IKANOS_VX_1X0
+       struct IKANOS_TX_INFO   IkanosTxInfo;
+       struct IKANOS_TX_INFO   IkanosRxInfo[MAX_MBSSID_NUM + MAX_WDS_ENTRY + MAX_APCLI_NUM + MAX_MESH_NUM];
+#endif // IKANOS_VX_1X0 //
+
+
+#ifdef DBG_DIAGNOSE
+       RtmpDiagStruct  DiagStruct;
+#endif // DBG_DIAGNOSE //
+
+
+       UINT8                                   PM_FlgSuspend;
+} RTMP_ADAPTER, *PRTMP_ADAPTER;
+
+//
+// Cisco IAPP format
+//
+typedef struct  _CISCO_IAPP_CONTENT_
+{
+       USHORT     Length;        //IAPP Length
+       UCHAR      MessageType;      //IAPP type
+       UCHAR      FunctionCode;     //IAPP function type
+       UCHAR      DestinaionMAC[MAC_ADDR_LEN];
+       UCHAR      SourceMAC[MAC_ADDR_LEN];
+       USHORT     Tag;           //Tag(element IE) - Adjacent AP report
+       USHORT     TagLength;     //Length of element not including 4 byte header
+       UCHAR      OUI[4];           //0x00, 0x40, 0x96, 0x00
+       UCHAR      PreviousAP[MAC_ADDR_LEN];       //MAC Address of access point
+       USHORT     Channel;
+       USHORT     SsidLen;
+       UCHAR      Ssid[MAX_LEN_OF_SSID];
+       USHORT     Seconds;          //Seconds that the client has been disassociated.
+} CISCO_IAPP_CONTENT, *PCISCO_IAPP_CONTENT;
+
+#define DELAYINTMASK           0x0003fffb
+#define INTMASK                                0x0003fffb
+#define IndMask                                0x0003fffc
+#define RxINT                          0x00000005      // Delayed Rx or indivi rx
+#define TxDataInt                      0x000000fa      // Delayed Tx or indivi tx
+#define TxMgmtInt                      0x00000102      // Delayed Tx or indivi tx
+#define TxCoherent                     0x00020000      // tx coherent
+#define RxCoherent                     0x00010000      // rx coherent
+#define McuCommand                     0x00000200      // mcu
+#define PreTBTTInt                     0x00001000      // Pre-TBTT interrupt
+#define TBTTInt                                0x00000800              // TBTT interrupt
+#define GPTimeOutInt                   0x00008000              // GPtimeout interrupt
+#define AutoWakeupInt          0x00004000              // AutoWakeupInt interrupt
+#define FifoStaFullInt                 0x00002000      //  fifo statistics full interrupt
+
+
+typedef struct _RX_BLK_
+{
+//     RXD_STRUC               RxD; // sample
+       RT28XX_RXD_STRUC        RxD;
+       PRXWI_STRUC                     pRxWI;
+       PHEADER_802_11          pHeader;
+       PNDIS_PACKET            pRxPacket;
+       UCHAR                           *pData;
+       USHORT                          DataSize;
+       USHORT                          Flags;
+       UCHAR                           UserPriority;   // for calculate TKIP MIC using
+} RX_BLK;
+
+
+#define RX_BLK_SET_FLAG(_pRxBlk, _flag)                (_pRxBlk->Flags |= _flag)
+#define RX_BLK_TEST_FLAG(_pRxBlk, _flag)       (_pRxBlk->Flags & _flag)
+#define RX_BLK_CLEAR_FLAG(_pRxBlk, _flag)      (_pRxBlk->Flags &= ~(_flag))
+
+
+#define fRX_WDS                        0x0001
+#define fRX_AMSDU       0x0002
+#define fRX_ARALINK     0x0004
+#define fRX_HTC         0x0008
+#define fRX_PAD         0x0010
+#define fRX_AMPDU       0x0020
+#define fRX_QOS                        0x0040
+#define fRX_INFRA              0x0080
+#define fRX_EAP                        0x0100
+#define fRX_MESH               0x0200
+#define fRX_APCLI              0x0400
+#define fRX_DLS                        0x0800
+#define fRX_WPI                        0x1000
+
+#define LENGTH_AMSDU_SUBFRAMEHEAD      14
+#define LENGTH_ARALINK_SUBFRAMEHEAD    14
+#define LENGTH_ARALINK_HEADER_FIELD     2
+
+#define TX_UNKOWN_FRAME                        0x00
+#define TX_MCAST_FRAME                 0x01
+#define TX_LEGACY_FRAME                        0x02
+#define TX_AMPDU_FRAME                 0x04
+#define TX_AMSDU_FRAME                 0x08
+#define TX_RALINK_FRAME                        0x10
+#define TX_FRAG_FRAME                  0x20
+
+
+//     Currently the sizeof(TX_BLK) is 148 bytes.
+typedef struct _TX_BLK_
+{
+       UCHAR                           QueIdx;
+       UCHAR                           TxFrameType;                            // Indicate the Transmission type of the all frames in one batch
+       UCHAR                           TotalFrameNum;                          // Total frame number want to send-out in one batch
+       USHORT                          TotalFragNum;                           // Total frame fragments required in one batch
+       USHORT                          TotalFrameLen;                          // Total length of all frames want to send-out in one batch
+
+       QUEUE_HEADER            TxPacketList;
+       MAC_TABLE_ENTRY         *pMacEntry;                                     // NULL: packet with 802.11 RA field is multicast/broadcast address
+       HTTRANSMIT_SETTING      *pTransmit;
+
+       // Following structure used for the characteristics of a specific packet.
+       PNDIS_PACKET            pPacket;
+       PUCHAR                          pSrcBufHeader;                          // Reference to the head of sk_buff->data
+       PUCHAR                          pSrcBufData;                            // Reference to the sk_buff->data, will changed depends on hanlding progresss
+       UINT                            SrcBufLen;                                      // Length of packet payload which not including Layer 2 header
+       PUCHAR                          pExtraLlcSnapEncap;                     // NULL means no extra LLC/SNAP is required
+       UCHAR                           HeaderBuf[80];                          // TempBuffer for TX_INFO + TX_WI + 802.11 Header + padding + AMSDU SubHeader + LLC/SNAP
+       UCHAR                           MpduHeaderLen;                          // 802.11 header length NOT including the padding
+       UCHAR                           HdrPadLen;                                      // recording Header Padding Length;
+       UCHAR                           apidx;                                          // The interface associated to this packet
+       UCHAR                           Wcid;                                           // The MAC entry associated to this packet
+       UCHAR                           UserPriority;                           // priority class of packet
+       UCHAR                           FrameGap;                                       // what kind of IFS this packet use
+       UCHAR                           MpduReqNum;                                     // number of fragments of this frame
+       UCHAR                           TxRate;                                         // TODO: Obsoleted? Should change to MCS?
+       UCHAR                           CipherAlg;                                      // cipher alogrithm
+       PCIPHER_KEY                     pKey;
+
+
+
+       USHORT                          Flags;                                          //See following definitions for detail.
+
+       //YOU SHOULD NOT TOUCH IT! Following parameters are used for hardware-depended layer.
+       ULONG                           Priv;                                           // Hardware specific value saved in here.
+} TX_BLK, *PTX_BLK;
+
+
+#define fTX_bRtsRequired               0x0001  // Indicate if need send RTS frame for protection. Not used in RT2860/RT2870.
+#define fTX_bAckRequired               0x0002  // the packet need ack response
+#define fTX_bPiggyBack                 0x0004  // Legacy device use Piggback or not
+#define fTX_bHTRate            0x0008  // allow to use HT rate
+//#define fTX_bForceLowRate       0x0010       // force to use Low Rate
+#define fTX_bForceNonQoS               0x0010  // force to transmit frame without WMM-QoS in HT mode
+#define fTX_bAllowFrag         0x0020  // allow to fragment the packet, A-MPDU, A-MSDU, A-Ralink is not allowed to fragment
+#define fTX_bMoreData                  0x0040  // there are more data packets in PowerSave Queue
+#define fTX_bWMM                               0x0080  // QOS Data
+
+#define fTX_bClearEAPFrame             0x0100
+
+
+#ifdef CONFIG_STA_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+
+
+
+#define TX_BLK_ASSIGN_FLAG(_pTxBlk, _flag, value)      \
+               do {                                                                            \
+                       if (value)                                                              \
+                               (_pTxBlk->Flags |= _flag)                       \
+                       else                                                                    \
+                               (_pTxBlk->Flags &= ~(_flag))            \
+               }while(0)
+
+#define TX_BLK_SET_FLAG(_pTxBlk, _flag)                (_pTxBlk->Flags |= _flag)
+#define TX_BLK_TEST_FLAG(_pTxBlk, _flag)       (((_pTxBlk->Flags & _flag) == _flag) ? 1 : 0)
+#define TX_BLK_CLEAR_FLAG(_pTxBlk, _flag)      (_pTxBlk->Flags &= ~(_flag))
+
+
+
+
+
+//------------------------------------------------------------------------------------------
+
+
+
+#ifdef RT_BIG_ENDIAN
+static inline VOID     WriteBackToDescriptor(
+       IN  PUCHAR                      Dest,
+       IN      PUCHAR                  Src,
+    IN  BOOLEAN                        DoEncrypt,
+       IN  ULONG           DescriptorType)
+{
+       UINT32 *p1, *p2;
+
+       p1 = ((UINT32 *)Dest);
+       p2 = ((UINT32 *)Src);
+
+       *p1 = *p2;
+       *(p1+2) = *(p2+2);
+       *(p1+3) = *(p2+3);
+       *(p1+1) = *(p2+1); // Word 1; this must be written back last
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Endian conversion of Tx/Rx descriptor .
+
+       Arguments:
+               pAd     Pointer to our adapter
+               pData                   Pointer to Tx/Rx descriptor
+               DescriptorType  Direction of the frame
+
+       Return Value:
+               None
+
+       Note:
+               Call this function when read or update descriptor
+       ========================================================================
+*/
+static inline VOID     RTMPWIEndianChange(
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DescriptorType)
+{
+       int size;
+       int i;
+
+       size = ((DescriptorType == TYPE_TXWI) ? TXWI_SIZE : RXWI_SIZE);
+
+       if(DescriptorType == TYPE_TXWI)
+       {
+               *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData)));            // Byte 0~3
+               *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData+4)));      // Byte 4~7
+       }
+       else
+       {
+               for(i=0; i < size/4 ; i++)
+                       *(((UINT32 *)pData) +i) = SWAP32(*(((UINT32 *)pData)+i));
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Endian conversion of Tx/Rx descriptor .
+
+       Arguments:
+               pAd     Pointer to our adapter
+               pData                   Pointer to Tx/Rx descriptor
+               DescriptorType  Direction of the frame
+
+       Return Value:
+               None
+
+       Note:
+               Call this function when read or update descriptor
+       ========================================================================
+*/
+
+#ifdef RT2870
+static inline VOID     RTMPDescriptorEndianChange(
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DescriptorType)
+{
+       *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData)));
+}
+#endif // RT2870 //
+/*
+       ========================================================================
+
+       Routine Description:
+               Endian conversion of all kinds of 802.11 frames .
+
+       Arguments:
+               pAd     Pointer to our adapter
+               pData                   Pointer to the 802.11 frame structure
+               Dir                     Direction of the frame
+               FromRxDoneInt   Caller is from RxDone interrupt
+
+       Return Value:
+               None
+
+       Note:
+               Call this function when read or update buffer data
+       ========================================================================
+*/
+static inline VOID     RTMPFrameEndianChange(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   Dir,
+       IN      BOOLEAN                 FromRxDoneInt)
+{
+       PHEADER_802_11 pFrame;
+       PUCHAR  pMacHdr;
+
+       // swab 16 bit fields - Frame Control field
+       if(Dir == DIR_READ)
+       {
+               *(USHORT *)pData = SWAP16(*(USHORT *)pData);
+       }
+
+       pFrame = (PHEADER_802_11) pData;
+       pMacHdr = (PUCHAR) pFrame;
+
+       // swab 16 bit fields - Duration/ID field
+       *(USHORT *)(pMacHdr + 2) = SWAP16(*(USHORT *)(pMacHdr + 2));
+
+       // swab 16 bit fields - Sequence Control field
+       *(USHORT *)(pMacHdr + 22) = SWAP16(*(USHORT *)(pMacHdr + 22));
+
+       if(pFrame->FC.Type == BTYPE_MGMT)
+       {
+               switch(pFrame->FC.SubType)
+               {
+                       case SUBTYPE_ASSOC_REQ:
+                       case SUBTYPE_REASSOC_REQ:
+                               // swab 16 bit fields - CapabilityInfo field
+                               pMacHdr += sizeof(HEADER_802_11);
+                               *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+                               // swab 16 bit fields - Listen Interval field
+                               pMacHdr += 2;
+                               *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+                               break;
+
+                       case SUBTYPE_ASSOC_RSP:
+                       case SUBTYPE_REASSOC_RSP:
+                               // swab 16 bit fields - CapabilityInfo field
+                               pMacHdr += sizeof(HEADER_802_11);
+                               *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+                               // swab 16 bit fields - Status Code field
+                               pMacHdr += 2;
+                               *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+                               // swab 16 bit fields - AID field
+                               pMacHdr += 2;
+                               *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+                               break;
+
+                       case SUBTYPE_AUTH:
+                               // If from APHandleRxDoneInterrupt routine, it is still a encrypt format.
+                               // The convertion is delayed to RTMPHandleDecryptionDoneInterrupt.
+                               if(!FromRxDoneInt && pFrame->FC.Wep == 1)
+                                       break;
+                               else
+                               {
+                                       // swab 16 bit fields - Auth Alg No. field
+                                       pMacHdr += sizeof(HEADER_802_11);
+                                       *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+                                       // swab 16 bit fields - Auth Seq No. field
+                                       pMacHdr += 2;
+                                       *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+                                       // swab 16 bit fields - Status Code field
+                                       pMacHdr += 2;
+                                       *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+                               }
+                               break;
+
+                       case SUBTYPE_BEACON:
+                       case SUBTYPE_PROBE_RSP:
+                               // swab 16 bit fields - BeaconInterval field
+                               pMacHdr += (sizeof(HEADER_802_11) + TIMESTAMP_LEN);
+                               *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+                               // swab 16 bit fields - CapabilityInfo field
+                               pMacHdr += sizeof(USHORT);
+                               *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+                               break;
+
+                       case SUBTYPE_DEAUTH:
+                       case SUBTYPE_DISASSOC:
+                               // swab 16 bit fields - Reason code field
+                               pMacHdr += sizeof(HEADER_802_11);
+                               *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+                               break;
+               }
+       }
+       else if( pFrame->FC.Type == BTYPE_DATA )
+       {
+       }
+       else if(pFrame->FC.Type == BTYPE_CNTL)
+       {
+               switch(pFrame->FC.SubType)
+               {
+                       case SUBTYPE_BLOCK_ACK_REQ:
+                               {
+                                       PFRAME_BA_REQ pBAReq = (PFRAME_BA_REQ)pFrame;
+                                       *(USHORT *)(&pBAReq->BARControl) = SWAP16(*(USHORT *)(&pBAReq->BARControl));
+                                       pBAReq->BAStartingSeq.word = SWAP16(pBAReq->BAStartingSeq.word);
+                               }
+                               break;
+                       case SUBTYPE_BLOCK_ACK:
+                               // For Block Ack packet, the HT_CONTROL field is in the same offset with Addr3
+                               *(UINT32 *)(&pFrame->Addr3[0]) = SWAP32(*(UINT32 *)(&pFrame->Addr3[0]));
+                               break;
+
+                       case SUBTYPE_ACK:
+                               //For ACK packet, the HT_CONTROL field is in the same offset with Addr2
+                               *(UINT32 *)(&pFrame->Addr2[0])= SWAP32(*(UINT32 *)(&pFrame->Addr2[0]));
+                               break;
+               }
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("Invalid Frame Type!!!\n"));
+       }
+
+       // swab 16 bit fields - Frame Control
+       if(Dir == DIR_WRITE)
+       {
+               *(USHORT *)pData = SWAP16(*(USHORT *)pData);
+       }
+}
+#endif // RT_BIG_ENDIAN //
+
+
+static inline VOID ConvertMulticastIP2MAC(
+       IN PUCHAR pIpAddr,
+       IN PUCHAR *ppMacAddr,
+       IN UINT16 ProtoType)
+{
+       if (pIpAddr == NULL)
+               return;
+
+       if (ppMacAddr == NULL || *ppMacAddr == NULL)
+               return;
+
+       switch (ProtoType)
+       {
+               case ETH_P_IPV6:
+//                     memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS);
+                       *(*ppMacAddr) = 0x33;
+                       *(*ppMacAddr + 1) = 0x33;
+                       *(*ppMacAddr + 2) = pIpAddr[12];
+                       *(*ppMacAddr + 3) = pIpAddr[13];
+                       *(*ppMacAddr + 4) = pIpAddr[14];
+                       *(*ppMacAddr + 5) = pIpAddr[15];
+                       break;
+
+               case ETH_P_IP:
+               default:
+//                     memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS);
+                       *(*ppMacAddr) = 0x01;
+                       *(*ppMacAddr + 1) = 0x00;
+                       *(*ppMacAddr + 2) = 0x5e;
+                       *(*ppMacAddr + 3) = pIpAddr[1] & 0x7f;
+                       *(*ppMacAddr + 4) = pIpAddr[2];
+                       *(*ppMacAddr + 5) = pIpAddr[3];
+                       break;
+       }
+
+       return;
+}
+
+BOOLEAN RTMPCheckForHang(
+       IN  NDIS_HANDLE MiniportAdapterContext
+       );
+
+VOID  RTMPHalt(
+       IN  NDIS_HANDLE MiniportAdapterContext
+       );
+
+//
+//  Private routines in rtmp_init.c
+//
+NDIS_STATUS RTMPAllocAdapterBlock(
+       IN PVOID                        handle,
+       OUT PRTMP_ADAPTER   *ppAdapter
+       );
+
+NDIS_STATUS RTMPAllocTxRxRingMemory(
+       IN  PRTMP_ADAPTER   pAd
+       );
+
+NDIS_STATUS RTMPFindAdapter(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  NDIS_HANDLE     WrapperConfigurationContext
+       );
+
+NDIS_STATUS    RTMPReadParametersHook(
+       IN      PRTMP_ADAPTER pAd
+       );
+
+VOID RTMPFreeAdapter(
+       IN  PRTMP_ADAPTER   pAd
+       );
+
+NDIS_STATUS NICReadRegParameters(
+       IN  PRTMP_ADAPTER       pAd,
+       IN  NDIS_HANDLE         WrapperConfigurationContext
+       );
+
+#ifdef RT2870
+VOID NICInitRT30xxRFRegisters(
+       IN PRTMP_ADAPTER pAd);
+#endif // RT2870 //
+
+VOID NICReadEEPROMParameters(
+       IN  PRTMP_ADAPTER       pAd,
+       IN      PUCHAR                          mac_addr);
+
+VOID NICInitAsicFromEEPROM(
+       IN  PRTMP_ADAPTER       pAd);
+
+VOID NICInitTxRxRingAndBacklogQueue(
+       IN  PRTMP_ADAPTER   pAd);
+
+NDIS_STATUS NICInitializeAdapter(
+       IN  PRTMP_ADAPTER   pAd,
+       IN   BOOLEAN    bHardReset);
+
+NDIS_STATUS NICInitializeAsic(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  BOOLEAN             bHardReset);
+
+VOID NICIssueReset(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID RTMPRingCleanUp(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR           RingType);
+
+VOID RxTest(
+       IN  PRTMP_ADAPTER   pAd);
+
+NDIS_STATUS DbgSendPacket(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PNDIS_PACKET    pPacket);
+
+VOID UserCfgInit(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID NICResetFromError(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID NICEraseFirmware(
+       IN PRTMP_ADAPTER pAd);
+
+NDIS_STATUS NICLoadFirmware(
+       IN  PRTMP_ADAPTER   pAd);
+
+NDIS_STATUS NICLoadRateSwitchingParams(
+       IN PRTMP_ADAPTER pAd);
+
+BOOLEAN NICCheckForHang(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID NICUpdateFifoStaCounters(
+       IN PRTMP_ADAPTER pAd);
+
+VOID NICUpdateRawCounters(
+       IN  PRTMP_ADAPTER   pAd);
+
+#if 0
+ULONG RTMPEqualMemory(
+       IN  PVOID   pSrc1,
+       IN  PVOID   pSrc2,
+       IN  ULONG   Length);
+#endif
+
+ULONG  RTMPNotAllZero(
+       IN      PVOID   pSrc1,
+       IN      ULONG   Length);
+
+VOID RTMPZeroMemory(
+       IN  PVOID   pSrc,
+       IN  ULONG   Length);
+
+ULONG RTMPCompareMemory(
+       IN  PVOID   pSrc1,
+       IN  PVOID   pSrc2,
+       IN  ULONG   Length);
+
+VOID RTMPMoveMemory(
+       OUT PVOID   pDest,
+       IN  PVOID   pSrc,
+       IN  ULONG   Length);
+
+VOID AtoH(
+       char    *src,
+       UCHAR   *dest,
+       int             destlen);
+
+UCHAR BtoH(
+       char ch);
+
+VOID RTMPPatchMacBbpBug(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID RTMPPatchCardBus(
+       IN      PRTMP_ADAPTER   pAdapter);
+
+VOID RTMPPatchRalinkCardBus(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      ULONG                   Bus);
+
+ULONG RTMPReadCBConfig(
+       IN      ULONG   Bus,
+       IN      ULONG   Slot,
+       IN      ULONG   Func,
+       IN      ULONG   Offset);
+
+VOID RTMPWriteCBConfig(
+       IN      ULONG   Bus,
+       IN      ULONG   Slot,
+       IN      ULONG   Func,
+       IN      ULONG   Offset,
+       IN      ULONG   Value);
+
+VOID RTMPInitTimer(
+       IN  PRTMP_ADAPTER           pAd,
+       IN  PRALINK_TIMER_STRUCT    pTimer,
+       IN  PVOID                   pTimerFunc,
+       IN      PVOID                                   pData,
+       IN  BOOLEAN                 Repeat);
+
+VOID RTMPSetTimer(
+       IN  PRALINK_TIMER_STRUCT    pTimer,
+       IN  ULONG                   Value);
+
+
+VOID RTMPModTimer(
+       IN      PRALINK_TIMER_STRUCT    pTimer,
+       IN      ULONG                                   Value);
+
+VOID RTMPCancelTimer(
+       IN  PRALINK_TIMER_STRUCT    pTimer,
+       OUT BOOLEAN                 *pCancelled);
+
+VOID RTMPSetLED(
+       IN PRTMP_ADAPTER        pAd,
+       IN UCHAR                        Status);
+
+VOID RTMPSetSignalLED(
+       IN PRTMP_ADAPTER        pAd,
+       IN NDIS_802_11_RSSI Dbm);
+
+VOID RTMPEnableRxTx(
+       IN PRTMP_ADAPTER        pAd);
+
+//
+// prototype in action.c
+//
+VOID ActionStateMachineInit(
+    IN PRTMP_ADAPTER   pAd,
+    IN  STATE_MACHINE *S,
+    OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID MlmeADDBAAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeDELBAAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeDLSAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeInvalidAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeQOSAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+#ifdef DOT11_N_SUPPORT
+VOID PeerAddBAReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerAddBARspAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerDelBAAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerBAAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+#endif // DOT11_N_SUPPORT //
+
+VOID SendPSMPAction(
+       IN PRTMP_ADAPTER        pAd,
+       IN UCHAR                        Wcid,
+       IN UCHAR                        Psmp);
+
+
+#ifdef DOT11N_DRAFT3
+VOID SendBSS2040CoexistMgmtAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR   Wcid,
+       IN      UCHAR   apidx,
+       IN      UCHAR   InfoReq);
+
+VOID SendNotifyBWActionFrame(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR  Wcid,
+       IN UCHAR apidx);
+
+BOOLEAN ChannelSwitchSanityCheck(
+       IN      PRTMP_ADAPTER   pAd,
+       IN    UCHAR  Wcid,
+       IN    UCHAR  NewChannel,
+       IN    UCHAR  Secondary);
+
+VOID ChannelSwitchAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN    UCHAR  Wcid,
+       IN    UCHAR  Channel,
+       IN    UCHAR  Secondary);
+
+ULONG BuildIntolerantChannelRep(
+       IN      PRTMP_ADAPTER   pAd,
+       IN    PUCHAR  pDest);
+
+VOID Update2040CoexistFrameAndNotify(
+       IN      PRTMP_ADAPTER   pAd,
+       IN    UCHAR  Wcid,
+       IN      BOOLEAN bAddIntolerantCha);
+
+VOID Send2040CoexistAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN    UCHAR  Wcid,
+       IN      BOOLEAN bAddIntolerantCha);
+#endif // DOT11N_DRAFT3 //
+
+VOID PeerRMAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerPublicAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+#ifdef CONFIG_STA_SUPPORT
+VOID StaPublicAction(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR Bss2040Coexist);
+#endif // CONFIG_STA_SUPPORT //
+
+
+VOID PeerBSSTranAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+#ifdef DOT11_N_SUPPORT
+VOID PeerHTAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+#endif // DOT11_N_SUPPORT //
+
+VOID PeerQOSAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+#ifdef QOS_DLS_SUPPORT
+VOID PeerDLSAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+#endif // QOS_DLS_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+VOID DlsParmFill(
+       IN PRTMP_ADAPTER pAd,
+       IN OUT MLME_DLS_REQ_STRUCT *pDlsReq,
+       IN PRT_802_11_DLS pDls,
+       IN USHORT reason);
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+VOID RECBATimerTimeout(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3);
+
+VOID ORIBATimerTimeout(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID SendRefreshBAR(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MAC_TABLE_ENTRY *pEntry);
+#endif // DOT11_N_SUPPORT //
+
+VOID ActHeaderInit(
+    IN PRTMP_ADAPTER   pAd,
+    IN OUT PHEADER_802_11 pHdr80211,
+    IN PUCHAR Addr1,
+    IN PUCHAR Addr2,
+    IN PUCHAR Addr3);
+
+VOID BarHeaderInit(
+       IN      PRTMP_ADAPTER   pAd,
+       IN OUT PFRAME_BAR pCntlBar,
+       IN PUCHAR pDA,
+       IN PUCHAR pSA);
+
+VOID InsertActField(
+       IN PRTMP_ADAPTER pAd,
+       OUT PUCHAR pFrameBuf,
+       OUT PULONG pFrameLen,
+       IN UINT8 Category,
+       IN UINT8 ActCode);
+
+BOOLEAN QosBADataParse(
+       IN PRTMP_ADAPTER        pAd,
+       IN BOOLEAN bAMSDU,
+       IN PUCHAR p8023Header,
+       IN UCHAR        WCID,
+       IN UCHAR        TID,
+       IN USHORT Sequence,
+       IN UCHAR DataOffset,
+       IN USHORT Datasize,
+       IN UINT   CurRxIndex);
+
+#ifdef DOT11_N_SUPPORT
+BOOLEAN CntlEnqueueForRecv(
+    IN PRTMP_ADAPTER   pAd,
+       IN ULONG Wcid,
+    IN ULONG MsgLen,
+       IN PFRAME_BA_REQ pMsg);
+
+VOID BaAutoManSwitch(
+       IN      PRTMP_ADAPTER   pAd);
+#endif // DOT11_N_SUPPORT //
+
+VOID HTIOTCheck(
+       IN      PRTMP_ADAPTER   pAd,
+       IN    UCHAR     BatRecIdx);
+
+//
+// Private routines in rtmp_data.c
+//
+BOOLEAN RTMPHandleRxDoneInterrupt(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID RTMPHandleTxDoneInterrupt(
+       IN  PRTMP_ADAPTER   pAd);
+
+BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  INT_SOURCE_CSR_STRUC TxRingBitmap);
+
+VOID RTMPHandleMgmtRingDmaDoneInterrupt(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID RTMPHandleTBTTInterrupt(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID RTMPHandlePreTBTTInterrupt(
+       IN  PRTMP_ADAPTER   pAd);
+
+void RTMPHandleTwakeupInterrupt(
+       IN PRTMP_ADAPTER pAd);
+
+VOID   RTMPHandleRxCoherentInterrupt(
+       IN      PRTMP_ADAPTER   pAd);
+
+BOOLEAN TxFrameIsAggregatible(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pPrevAddr1,
+       IN  PUCHAR          p8023hdr);
+
+BOOLEAN PeerIsAggreOn(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  ULONG          TxRate,
+    IN  PMAC_TABLE_ENTRY pMacEntry);
+
+#if 0  // It's not be used
+HTTRANSMIT_SETTING  *GetTxMode(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk);
+#endif
+
+NDIS_STATUS Sniff2BytesFromNdisBuffer(
+       IN  PNDIS_BUFFER    pFirstBuffer,
+       IN  UCHAR           DesiredOffset,
+       OUT PUCHAR          pByte0,
+       OUT PUCHAR          pByte1);
+
+NDIS_STATUS STASendPacket(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PNDIS_PACKET    pPacket);
+
+VOID STASendPackets(
+       IN  NDIS_HANDLE     MiniportAdapterContext,
+       IN  PPNDIS_PACKET   ppPacketArray,
+       IN  UINT            NumberOfPackets);
+
+VOID RTMPDeQueuePacket(
+       IN  PRTMP_ADAPTER   pAd,
+       IN      BOOLEAN                 bIntContext,
+       IN  UCHAR                       QueIdx,
+       IN      UCHAR                   Max_Tx_Packets);
+
+NDIS_STATUS    RTMPHardTransmit(
+       IN PRTMP_ADAPTER        pAd,
+       IN PNDIS_PACKET         pPacket,
+       IN  UCHAR                       QueIdx,
+       OUT     PULONG                  pFreeTXDLeft);
+
+NDIS_STATUS    STAHardTransmit(
+       IN PRTMP_ADAPTER        pAd,
+       IN TX_BLK                       *pTxBlk,
+       IN  UCHAR                       QueIdx);
+
+VOID STARxEAPOLFrameIndicate(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MAC_TABLE_ENTRY *pEntry,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID);
+
+NDIS_STATUS RTMPFreeTXDRequest(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR           RingType,
+       IN  UCHAR           NumberRequired,
+       IN      PUCHAR          FreeNumberIs);
+
+NDIS_STATUS MlmeHardTransmit(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR       QueIdx,
+       IN  PNDIS_PACKET    pPacket);
+
+NDIS_STATUS MlmeHardTransmitMgmtRing(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR       QueIdx,
+       IN  PNDIS_PACKET    pPacket);
+
+NDIS_STATUS MlmeHardTransmitTxRing(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR       QueIdx,
+       IN  PNDIS_PACKET    pPacket);
+
+USHORT  RTMPCalcDuration(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR           Rate,
+       IN  ULONG           Size);
+
+VOID RTMPWriteTxWI(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTXWI_STRUC             pTxWI,
+       IN  BOOLEAN             FRAG,
+       IN  BOOLEAN             CFACK,
+       IN  BOOLEAN             InsTimestamp,
+       IN      BOOLEAN                 AMPDU,
+       IN      BOOLEAN                 Ack,
+       IN      BOOLEAN                 NSeq,           // HW new a sequence.
+       IN      UCHAR                   BASize,
+       IN      UCHAR                   WCID,
+       IN      ULONG                   Length,
+       IN  UCHAR               PID,
+       IN      UCHAR                   TID,
+       IN      UCHAR                   TxRate,
+       IN      UCHAR                   Txopmode,
+       IN      BOOLEAN                 CfAck,
+       IN      HTTRANSMIT_SETTING      *pTransmit);
+
+
+VOID RTMPWriteTxWI_Data(
+       IN      PRTMP_ADAPTER           pAd,
+       IN      OUT PTXWI_STRUC         pTxWI,
+       IN      TX_BLK                          *pTxBlk);
+
+
+VOID RTMPWriteTxWI_Cache(
+       IN      PRTMP_ADAPTER           pAd,
+       IN      OUT PTXWI_STRUC         pTxWI,
+       IN      TX_BLK                          *pTxBlk);
+
+VOID RTMPWriteTxDescriptor(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTXD_STRUC              pTxD,
+       IN      BOOLEAN                 bWIV,
+       IN      UCHAR                   QSEL);
+
+VOID RTMPSuspendMsduTransmission(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID RTMPResumeMsduTransmission(
+       IN  PRTMP_ADAPTER   pAd);
+
+NDIS_STATUS MiniportMMRequest(
+       IN  PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   QueIdx,
+       IN      PUCHAR                  pData,
+       IN  UINT            Length);
+
+NDIS_STATUS MiniportDataMMRequest(
+        IN  PRTMP_ADAPTER   pAd,
+        IN  UCHAR           QueIdx,
+        IN  PUCHAR          pData,
+        IN  UINT            Length);
+
+VOID RTMPSendNullFrame(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR           TxRate,
+       IN      BOOLEAN                 bQosNull);
+
+VOID RTMPSendDisassociationFrame(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID RTMPSendRTSFrame(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pDA,
+       IN      unsigned int    NextMpduSize,
+       IN  UCHAR           TxRate,
+       IN  UCHAR           RTSRate,
+       IN  USHORT          AckDuration,
+       IN  UCHAR           QueIdx,
+       IN  UCHAR                       FrameGap);
+
+
+NDIS_STATUS RTMPApplyPacketFilter(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PRT28XX_RXD_STRUC      pRxD,
+       IN  PHEADER_802_11  pHeader);
+
+PQUEUE_HEADER   RTMPCheckTxSwQueue(
+       IN  PRTMP_ADAPTER   pAd,
+       OUT UCHAR           *QueIdx);
+
+#ifdef CONFIG_STA_SUPPORT
+VOID RTMPReportMicError(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PCIPHER_KEY     pWpaKey);
+
+VOID   WpaMicFailureReportFrame(
+       IN  PRTMP_ADAPTER    pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID    WpaDisassocApAndBlockAssoc(
+    IN  PVOID SystemSpecific1,
+    IN  PVOID FunctionContext,
+    IN  PVOID SystemSpecific2,
+    IN  PVOID SystemSpecific3);
+#endif // CONFIG_STA_SUPPORT //
+
+NDIS_STATUS RTMPCloneNdisPacket(
+       IN  PRTMP_ADAPTER   pAd,
+       IN      BOOLEAN    pInsAMSDUHdr,
+       IN  PNDIS_PACKET    pInPacket,
+       OUT PNDIS_PACKET   *ppOutPacket);
+
+NDIS_STATUS RTMPAllocateNdisPacket(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PNDIS_PACKET    *pPacket,
+       IN  PUCHAR          pHeader,
+       IN  UINT            HeaderLen,
+       IN  PUCHAR          pData,
+       IN  UINT            DataLen);
+
+VOID RTMPFreeNdisPacket(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PNDIS_PACKET    pPacket);
+
+BOOLEAN RTMPFreeTXDUponTxDmaDone(
+       IN PRTMP_ADAPTER    pAd,
+       IN UCHAR            QueIdx);
+
+BOOLEAN RTMPCheckDHCPFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket);
+
+
+BOOLEAN RTMPCheckEtherType(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket);
+
+
+VOID RTMPCckBbpTuning(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UINT                    TxRate);
+
+//
+// Private routines in rtmp_wep.c
+//
+VOID RTMPInitWepEngine(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pKey,
+       IN  UCHAR           KeyId,
+       IN  UCHAR           KeyLen,
+       IN  PUCHAR          pDest);
+
+VOID RTMPEncryptData(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pSrc,
+       IN  PUCHAR          pDest,
+       IN  UINT            Len);
+
+BOOLEAN        RTMPDecryptData(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  pSrc,
+       IN      UINT                    Len,
+       IN      UINT                    idx);
+
+BOOLEAN        RTMPSoftDecryptWEP(
+       IN PRTMP_ADAPTER        pAd,
+       IN PUCHAR                       pData,
+       IN ULONG                        DataByteCnt,
+       IN PCIPHER_KEY          pGroupKey);
+
+VOID RTMPSetICV(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pDest);
+
+VOID ARCFOUR_INIT(
+       IN  PARCFOURCONTEXT Ctx,
+       IN  PUCHAR          pKey,
+       IN  UINT            KeyLen);
+
+UCHAR   ARCFOUR_BYTE(
+       IN  PARCFOURCONTEXT     Ctx);
+
+VOID ARCFOUR_DECRYPT(
+       IN  PARCFOURCONTEXT Ctx,
+       IN  PUCHAR          pDest,
+       IN  PUCHAR          pSrc,
+       IN  UINT            Len);
+
+VOID ARCFOUR_ENCRYPT(
+       IN  PARCFOURCONTEXT Ctx,
+       IN  PUCHAR          pDest,
+       IN  PUCHAR          pSrc,
+       IN  UINT            Len);
+
+VOID WPAARCFOUR_ENCRYPT(
+       IN  PARCFOURCONTEXT Ctx,
+       IN  PUCHAR          pDest,
+       IN  PUCHAR          pSrc,
+       IN  UINT            Len);
+
+UINT RTMP_CALC_FCS32(
+       IN  UINT   Fcs,
+       IN  PUCHAR  Cp,
+       IN  INT     Len);
+
+//
+// MLME routines
+//
+
+// Asic/RF/BBP related functions
+
+VOID AsicAdjustTxPower(
+       IN PRTMP_ADAPTER pAd);
+
+VOID   AsicUpdateProtect(
+       IN              PRTMP_ADAPTER   pAd,
+       IN              USHORT                  OperaionMode,
+       IN              UCHAR                   SetMask,
+       IN              BOOLEAN                 bDisableBGProtect,
+       IN              BOOLEAN                 bNonGFExist);
+
+VOID AsicSwitchChannel(
+       IN  PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Channel,
+       IN      BOOLEAN                 bScan);
+
+VOID AsicLockChannel(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR Channel) ;
+
+VOID AsicAntennaSelect(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR           Channel);
+
+VOID AsicAntennaSetting(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      ABGBAND_STATE   BandState);
+
+VOID AsicRfTuningExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+#ifdef CONFIG_STA_SUPPORT
+VOID AsicSleepThenAutoWakeup(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  USHORT TbttNumToNextWakeUp);
+
+VOID AsicForceSleep(
+       IN PRTMP_ADAPTER pAd);
+
+VOID AsicForceWakeup(
+       IN PRTMP_ADAPTER pAd,
+       IN BOOLEAN    bFromTx);
+#endif // CONFIG_STA_SUPPORT //
+
+VOID AsicSetBssid(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR pBssid);
+
+VOID AsicSetMcastWC(
+       IN PRTMP_ADAPTER pAd);
+
+#if 0  // removed by AlbertY
+VOID AsicSetBssidWC(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pBssid);
+#endif
+
+VOID AsicDelWcidTab(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR        Wcid);
+
+VOID AsicEnableRDG(
+       IN PRTMP_ADAPTER pAd);
+
+VOID AsicDisableRDG(
+       IN PRTMP_ADAPTER pAd);
+
+VOID AsicDisableSync(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID AsicEnableBssSync(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID AsicEnableIbssSync(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID AsicSetEdcaParm(
+       IN PRTMP_ADAPTER pAd,
+       IN PEDCA_PARM    pEdcaParm);
+
+VOID AsicSetSlotTime(
+       IN PRTMP_ADAPTER pAd,
+       IN BOOLEAN bUseShortSlotTime);
+
+#if 0
+VOID AsicAddWcidCipherEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR                 WCID,
+       IN UCHAR                 BssIndex,
+       IN UCHAR                 KeyTable,
+       IN UCHAR                 CipherAlg,
+       IN PUCHAR                pAddr,
+       IN CIPHER_KEY            *pCipherKey);
+#endif
+
+VOID AsicAddSharedKeyEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR         BssIndex,
+       IN UCHAR         KeyIdx,
+       IN UCHAR         CipherAlg,
+       IN PUCHAR        pKey,
+       IN PUCHAR        pTxMic,
+       IN PUCHAR        pRxMic);
+
+VOID AsicRemoveSharedKeyEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR         BssIndex,
+       IN UCHAR         KeyIdx);
+
+VOID AsicUpdateWCIDAttribute(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT               WCID,
+       IN UCHAR                BssIndex,
+       IN UCHAR        CipherAlg,
+       IN BOOLEAN              bUsePairewiseKeyTable);
+
+VOID AsicUpdateWCIDIVEIV(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT               WCID,
+       IN ULONG        uIV,
+       IN ULONG        uEIV);
+
+VOID AsicUpdateRxWCIDTable(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT               WCID,
+       IN PUCHAR        pAddr);
+
+VOID AsicAddKeyEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT               WCID,
+       IN UCHAR                BssIndex,
+       IN UCHAR                KeyIdx,
+       IN PCIPHER_KEY  pCipherKey,
+       IN BOOLEAN              bUsePairewiseKeyTable,
+       IN BOOLEAN              bTxKey);
+
+VOID AsicAddPairwiseKeyEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR        pAddr,
+       IN UCHAR                WCID,
+       IN CIPHER_KEY            *pCipherKey);
+
+VOID AsicRemovePairwiseKeyEntry(
+       IN PRTMP_ADAPTER  pAd,
+       IN UCHAR                 BssIdx,
+       IN UCHAR                 Wcid);
+
+BOOLEAN AsicSendCommandToMcu(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR         Command,
+       IN UCHAR         Token,
+       IN UCHAR         Arg0,
+       IN UCHAR         Arg1);
+
+
+VOID MacAddrRandomBssid(
+       IN  PRTMP_ADAPTER   pAd,
+       OUT PUCHAR pAddr);
+
+VOID MgtMacHeaderInit(
+       IN  PRTMP_ADAPTER     pAd,
+       IN OUT PHEADER_802_11 pHdr80211,
+       IN UCHAR SubType,
+       IN UCHAR ToDs,
+       IN PUCHAR pDA,
+       IN PUCHAR pBssid);
+
+VOID MlmeRadioOff(
+       IN PRTMP_ADAPTER pAd);
+
+VOID MlmeRadioOn(
+       IN PRTMP_ADAPTER pAd);
+
+
+VOID BssTableInit(
+       IN BSS_TABLE *Tab);
+
+#ifdef DOT11_N_SUPPORT
+VOID BATableInit(
+       IN PRTMP_ADAPTER pAd,
+    IN BA_TABLE *Tab);
+#endif // DOT11_N_SUPPORT //
+
+ULONG BssTableSearch(
+       IN BSS_TABLE *Tab,
+       IN PUCHAR pBssid,
+       IN UCHAR Channel);
+
+ULONG BssSsidTableSearch(
+       IN BSS_TABLE *Tab,
+       IN PUCHAR    pBssid,
+       IN PUCHAR    pSsid,
+       IN UCHAR     SsidLen,
+       IN UCHAR     Channel);
+
+ULONG BssTableSearchWithSSID(
+       IN BSS_TABLE *Tab,
+       IN PUCHAR    Bssid,
+       IN PUCHAR    pSsid,
+       IN UCHAR     SsidLen,
+       IN UCHAR     Channel);
+
+VOID BssTableDeleteEntry(
+       IN OUT  PBSS_TABLE pTab,
+       IN      PUCHAR pBssid,
+       IN      UCHAR Channel);
+
+#ifdef DOT11_N_SUPPORT
+VOID BATableDeleteORIEntry(
+       IN OUT  PRTMP_ADAPTER pAd,
+       IN              BA_ORI_ENTRY    *pBAORIEntry);
+
+VOID BATableDeleteRECEntry(
+       IN OUT  PRTMP_ADAPTER pAd,
+       IN              BA_REC_ENTRY    *pBARECEntry);
+
+VOID BATableTearORIEntry(
+       IN OUT  PRTMP_ADAPTER pAd,
+       IN              UCHAR TID,
+       IN              UCHAR Wcid,
+       IN              BOOLEAN bForceDelete,
+       IN              BOOLEAN ALL);
+
+VOID BATableTearRECEntry(
+       IN OUT  PRTMP_ADAPTER pAd,
+       IN              UCHAR TID,
+       IN              UCHAR WCID,
+       IN              BOOLEAN ALL);
+#endif // DOT11_N_SUPPORT //
+
+VOID  BssEntrySet(
+       IN  PRTMP_ADAPTER   pAd,
+       OUT PBSS_ENTRY pBss,
+       IN PUCHAR pBssid,
+       IN CHAR Ssid[],
+       IN UCHAR SsidLen,
+       IN UCHAR BssType,
+       IN USHORT BeaconPeriod,
+       IN PCF_PARM CfParm,
+       IN USHORT AtimWin,
+       IN USHORT CapabilityInfo,
+       IN UCHAR SupRate[],
+       IN UCHAR SupRateLen,
+       IN UCHAR ExtRate[],
+       IN UCHAR ExtRateLen,
+       IN HT_CAPABILITY_IE *pHtCapability,
+       IN ADD_HT_INFO_IE *pAddHtInfo,  // AP might use this additional ht info IE
+       IN UCHAR                        HtCapabilityLen,
+       IN UCHAR                        AddHtInfoLen,
+       IN UCHAR                        NewExtChanOffset,
+       IN UCHAR Channel,
+       IN CHAR Rssi,
+       IN LARGE_INTEGER TimeStamp,
+       IN UCHAR CkipFlag,
+       IN PEDCA_PARM pEdcaParm,
+       IN PQOS_CAPABILITY_PARM pQosCapability,
+       IN PQBSS_LOAD_PARM pQbssLoad,
+       IN USHORT LengthVIE,
+       IN PNDIS_802_11_VARIABLE_IEs pVIE);
+
+ULONG  BssTableSetEntry(
+       IN  PRTMP_ADAPTER   pAd,
+       OUT PBSS_TABLE pTab,
+       IN PUCHAR pBssid,
+       IN CHAR Ssid[],
+       IN UCHAR SsidLen,
+       IN UCHAR BssType,
+       IN USHORT BeaconPeriod,
+       IN CF_PARM *CfParm,
+       IN USHORT AtimWin,
+       IN USHORT CapabilityInfo,
+       IN UCHAR SupRate[],
+       IN UCHAR SupRateLen,
+       IN UCHAR ExtRate[],
+       IN UCHAR ExtRateLen,
+       IN HT_CAPABILITY_IE *pHtCapability,
+       IN ADD_HT_INFO_IE *pAddHtInfo,  // AP might use this additional ht info IE
+       IN UCHAR                        HtCapabilityLen,
+       IN UCHAR                        AddHtInfoLen,
+       IN UCHAR                        NewExtChanOffset,
+       IN UCHAR Channel,
+       IN CHAR Rssi,
+       IN LARGE_INTEGER TimeStamp,
+       IN UCHAR CkipFlag,
+       IN PEDCA_PARM pEdcaParm,
+       IN PQOS_CAPABILITY_PARM pQosCapability,
+       IN PQBSS_LOAD_PARM pQbssLoad,
+       IN USHORT LengthVIE,
+       IN PNDIS_802_11_VARIABLE_IEs pVIE);
+
+#ifdef DOT11_N_SUPPORT
+VOID BATableInsertEntry(
+    IN PRTMP_ADAPTER   pAd,
+       IN USHORT Aid,
+    IN USHORT          TimeOutValue,
+       IN USHORT               StartingSeq,
+    IN UCHAR TID,
+       IN UCHAR BAWinSize,
+       IN UCHAR OriginatorStatus,
+    IN BOOLEAN IsRecipient);
+
+#ifdef DOT11N_DRAFT3
+VOID Bss2040CoexistTimeOut(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+
+VOID  TriEventInit(
+       IN      PRTMP_ADAPTER   pAd);
+
+ULONG TriEventTableSetEntry(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT TRIGGER_EVENT_TAB *Tab,
+       IN PUCHAR pBssid,
+       IN HT_CAPABILITY_IE *pHtCapability,
+       IN UCHAR                        HtCapabilityLen,
+       IN UCHAR                        RegClass,
+       IN UCHAR ChannelNo);
+
+VOID TriEventCounterMaintenance(
+       IN      PRTMP_ADAPTER   pAd);
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+VOID BssTableSsidSort(
+       IN  PRTMP_ADAPTER   pAd,
+       OUT BSS_TABLE *OutTab,
+       IN  CHAR Ssid[],
+       IN  UCHAR SsidLen);
+
+VOID  BssTableSortByRssi(
+       IN OUT BSS_TABLE *OutTab);
+
+VOID BssCipherParse(
+       IN OUT  PBSS_ENTRY  pBss);
+
+NDIS_STATUS  MlmeQueueInit(
+       IN MLME_QUEUE *Queue);
+
+VOID  MlmeQueueDestroy(
+       IN MLME_QUEUE *Queue);
+
+BOOLEAN MlmeEnqueue(
+       IN PRTMP_ADAPTER pAd,
+       IN ULONG Machine,
+       IN ULONG MsgType,
+       IN ULONG MsgLen,
+       IN VOID *Msg);
+
+BOOLEAN MlmeEnqueueForRecv(
+       IN  PRTMP_ADAPTER   pAd,
+       IN ULONG Wcid,
+       IN ULONG TimeStampHigh,
+       IN ULONG TimeStampLow,
+       IN UCHAR Rssi0,
+       IN UCHAR Rssi1,
+       IN UCHAR Rssi2,
+       IN ULONG MsgLen,
+       IN PVOID Msg,
+       IN UCHAR Signal);
+
+
+BOOLEAN MlmeDequeue(
+       IN MLME_QUEUE *Queue,
+       OUT MLME_QUEUE_ELEM **Elem);
+
+VOID    MlmeRestartStateMachine(
+       IN  PRTMP_ADAPTER   pAd);
+
+BOOLEAN  MlmeQueueEmpty(
+       IN MLME_QUEUE *Queue);
+
+BOOLEAN  MlmeQueueFull(
+       IN MLME_QUEUE *Queue);
+
+BOOLEAN  MsgTypeSubst(
+       IN PRTMP_ADAPTER pAd,
+       IN PFRAME_802_11 pFrame,
+       OUT INT *Machine,
+       OUT INT *MsgType);
+
+VOID StateMachineInit(
+       IN STATE_MACHINE *Sm,
+       IN STATE_MACHINE_FUNC Trans[],
+       IN ULONG StNr,
+       IN ULONG MsgNr,
+       IN STATE_MACHINE_FUNC DefFunc,
+       IN ULONG InitState,
+       IN ULONG Base);
+
+VOID StateMachineSetAction(
+       IN STATE_MACHINE *S,
+       IN ULONG St,
+       ULONG Msg,
+       IN STATE_MACHINE_FUNC F);
+
+VOID StateMachinePerformAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN STATE_MACHINE *S,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID Drop(
+       IN  PRTMP_ADAPTER   pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID AssocStateMachineInit(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  STATE_MACHINE *Sm,
+       OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID ReassocTimeout(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID AssocTimeout(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID DisassocTimeout(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+//----------------------------------------------
+VOID MlmeDisassocReqAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeAssocReqAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeReassocReqAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeDisassocReqAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID PeerAssocRspAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID PeerReassocRspAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID PeerDisassocAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID DisassocTimeoutAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID AssocTimeoutAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID  ReassocTimeoutAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID  Cls3errAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR pAddr);
+
+VOID SwitchBetweenWepAndCkip(
+       IN PRTMP_ADAPTER pAd);
+
+VOID  InvalidStateWhenAssoc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID  InvalidStateWhenReassoc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID InvalidStateWhenDisassociate(
+       IN  PRTMP_ADAPTER pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+#ifdef RT2870
+VOID MlmeCntlConfirm(
+       IN PRTMP_ADAPTER pAd,
+       IN ULONG MsgType,
+       IN USHORT Msg);
+#endif // RT2870 //
+
+VOID  ComposePsPoll(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID  ComposeNullFrame(
+       IN  PRTMP_ADAPTER pAd);
+
+VOID  AssocPostProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR pAddr2,
+       IN  USHORT CapabilityInfo,
+       IN  USHORT Aid,
+       IN  UCHAR SupRate[],
+       IN  UCHAR SupRateLen,
+       IN  UCHAR ExtRate[],
+       IN  UCHAR ExtRateLen,
+       IN PEDCA_PARM pEdcaParm,
+       IN HT_CAPABILITY_IE             *pHtCapability,
+       IN  UCHAR HtCapabilityLen,
+       IN ADD_HT_INFO_IE               *pAddHtInfo);
+
+VOID AuthStateMachineInit(
+       IN  PRTMP_ADAPTER   pAd,
+       IN PSTATE_MACHINE sm,
+       OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID AuthTimeout(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID MlmeAuthReqAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID PeerAuthRspAtSeq2Action(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID PeerAuthRspAtSeq4Action(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID AuthTimeoutAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID Cls2errAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR pAddr);
+
+VOID MlmeDeauthReqAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID InvalidStateWhenAuth(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+//=============================================
+
+VOID AuthRspStateMachineInit(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PSTATE_MACHINE Sm,
+       IN  STATE_MACHINE_FUNC Trans[]);
+
+VOID PeerDeauthAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerAuthSimpleRspGenAndSend(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PHEADER_802_11  pHdr80211,
+       IN  USHORT Alg,
+       IN  USHORT Seq,
+       IN  USHORT Reason,
+       IN  USHORT Status);
+
+//
+// Private routines in dls.c
+//
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+void DlsStateMachineInit(
+    IN PRTMP_ADAPTER pAd,
+    IN STATE_MACHINE *Sm,
+    OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID MlmeDlsReqAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerDlsReqAction(
+    IN PRTMP_ADAPTER   pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerDlsRspAction(
+    IN PRTMP_ADAPTER   pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeDlsTearDownAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerDlsTearDownAction(
+    IN PRTMP_ADAPTER   pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+VOID RTMPCheckDLSTimeOut(
+       IN PRTMP_ADAPTER        pAd);
+
+BOOLEAN RTMPRcvFrameDLSCheck(
+       IN PRTMP_ADAPTER        pAd,
+       IN PHEADER_802_11       pHeader,
+       IN ULONG                        Len,
+       IN PRT28XX_RXD_STRUC    pRxD);
+
+INT    RTMPCheckDLSFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pDA);
+
+VOID RTMPSendDLSTearDownFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pDA);
+
+NDIS_STATUS RTMPSendSTAKeyRequest(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pDA);
+
+NDIS_STATUS RTMPSendSTAKeyHandShake(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pDA);
+
+VOID DlsTimeoutAction(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+BOOLEAN MlmeDlsReqSanity(
+       IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PRT_802_11_DLS *pDLS,
+    OUT PUSHORT pReason);
+
+INT Set_DlsEntryInfo_Display_Proc(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR arg);
+
+MAC_TABLE_ENTRY *MacTableInsertDlsEntry(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR      pAddr,
+       IN  UINT        DlsEntryIdx);
+
+BOOLEAN MacTableDeleteDlsEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT wcid,
+       IN PUCHAR pAddr);
+
+MAC_TABLE_ENTRY *DlsEntryTableLookup(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR       pAddr,
+       IN BOOLEAN      bResetIdelCount);
+
+MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR        wcid,
+       IN PUCHAR       pAddr,
+       IN BOOLEAN      bResetIdelCount);
+
+INT    Set_DlsAddEntry_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_DlsTearDownEntry_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef QOS_DLS_SUPPORT
+BOOLEAN PeerDlsReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pDA,
+    OUT PUCHAR pSA,
+    OUT USHORT *pCapabilityInfo,
+    OUT USHORT *pDlsTimeout,
+    OUT UCHAR *pRatesLen,
+    OUT UCHAR Rates[],
+    OUT UCHAR *pHtCapabilityLen,
+    OUT HT_CAPABILITY_IE *pHtCapability);
+
+BOOLEAN PeerDlsRspSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pDA,
+    OUT PUCHAR pSA,
+    OUT USHORT *pCapabilityInfo,
+    OUT USHORT *pStatus,
+    OUT UCHAR *pRatesLen,
+    OUT UCHAR Rates[],
+    OUT UCHAR *pHtCapabilityLen,
+    OUT HT_CAPABILITY_IE *pHtCapability);
+
+BOOLEAN PeerDlsTearDownSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pDA,
+    OUT PUCHAR pSA,
+    OUT USHORT *pReason);
+#endif // QOS_DLS_SUPPORT //
+
+//========================================
+
+VOID SyncStateMachineInit(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  STATE_MACHINE *Sm,
+       OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID BeaconTimeout(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID ScanTimeout(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID MlmeScanReqAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID InvalidStateWhenScan(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID InvalidStateWhenJoin(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID InvalidStateWhenStart(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID PeerBeacon(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID EnqueueProbeRequest(
+       IN PRTMP_ADAPTER pAd);
+
+BOOLEAN ScanRunning(
+               IN PRTMP_ADAPTER pAd);
+//=========================================
+
+VOID MlmeCntlInit(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  STATE_MACHINE *S,
+       OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID MlmeCntlMachinePerformAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  STATE_MACHINE *S,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID CntlIdleProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID CntlOidScanProc(
+       IN  PRTMP_ADAPTER pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID CntlOidSsidProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM * Elem);
+
+VOID CntlOidRTBssidProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM * Elem);
+
+VOID CntlMlmeRoamingProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM * Elem);
+
+VOID CntlWaitDisassocProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitJoinProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitReassocProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitStartProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitAuthProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitAuthProc2(
+       IN  PRTMP_ADAPTER pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitAssocProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+#ifdef QOS_DLS_SUPPORT
+VOID CntlOidDLSSetupProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+#endif // QOS_DLS_SUPPORT //
+
+VOID LinkUp(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR BssType);
+
+VOID LinkDown(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  BOOLEAN         IsReqFromAP);
+
+VOID IterateOnBssTab(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID IterateOnBssTab2(
+       IN  PRTMP_ADAPTER   pAd);;
+
+VOID JoinParmFill(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  OUT MLME_JOIN_REQ_STRUCT *JoinReq,
+       IN  ULONG BssIdx);
+
+VOID AssocParmFill(
+       IN  PRTMP_ADAPTER   pAd,
+       IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
+       IN  PUCHAR pAddr,
+       IN  USHORT CapabilityInfo,
+       IN  ULONG Timeout,
+       IN  USHORT ListenIntv);
+
+VOID ScanParmFill(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  OUT MLME_SCAN_REQ_STRUCT *ScanReq,
+       IN  CHAR Ssid[],
+       IN  UCHAR SsidLen,
+       IN  UCHAR BssType,
+       IN  UCHAR ScanType);
+
+VOID DisassocParmFill(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
+       IN  PUCHAR pAddr,
+       IN  USHORT Reason);
+
+VOID StartParmFill(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  OUT MLME_START_REQ_STRUCT *StartReq,
+       IN  CHAR Ssid[],
+       IN  UCHAR SsidLen);
+
+VOID AuthParmFill(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  OUT MLME_AUTH_REQ_STRUCT *AuthReq,
+       IN  PUCHAR pAddr,
+       IN  USHORT Alg);
+
+VOID EnqueuePsPoll(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID EnqueueBeaconFrame(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID MlmeJoinReqAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeScanReqAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeStartReqAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID ScanTimeoutAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID BeaconTimeoutAtJoinAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID PeerBeaconAtScanAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID PeerBeaconAtJoinAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID PeerBeacon(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID PeerProbeReqAction(
+       IN  PRTMP_ADAPTER pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID ScanNextChannel(
+       IN  PRTMP_ADAPTER   pAd);
+
+ULONG MakeIbssBeacon(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID CCXAdjacentAPReport(
+       IN  PRTMP_ADAPTER   pAd);
+
+BOOLEAN MlmeScanReqSanity(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  VOID *Msg,
+       IN  ULONG MsgLen,
+       OUT UCHAR *BssType,
+       OUT CHAR ssid[],
+       OUT UCHAR *SsidLen,
+       OUT UCHAR *ScanType);
+
+BOOLEAN PeerBeaconAndProbeRspSanity(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  VOID *Msg,
+       IN  ULONG MsgLen,
+       IN  UCHAR MsgChannel,
+       OUT PUCHAR pAddr2,
+       OUT PUCHAR pBssid,
+       OUT CHAR Ssid[],
+       OUT UCHAR *pSsidLen,
+       OUT UCHAR *pBssType,
+       OUT USHORT *pBeaconPeriod,
+       OUT UCHAR *pChannel,
+       OUT UCHAR *pNewChannel,
+       OUT LARGE_INTEGER *pTimestamp,
+       OUT CF_PARM *pCfParm,
+       OUT USHORT *pAtimWin,
+       OUT USHORT *pCapabilityInfo,
+       OUT UCHAR *pErp,
+       OUT UCHAR *pDtimCount,
+       OUT UCHAR *pDtimPeriod,
+       OUT UCHAR *pBcastFlag,
+       OUT UCHAR *pMessageToMe,
+       OUT UCHAR SupRate[],
+       OUT UCHAR *pSupRateLen,
+       OUT UCHAR ExtRate[],
+       OUT UCHAR *pExtRateLen,
+       OUT     UCHAR *pCkipFlag,
+       OUT     UCHAR *pAironetCellPowerLimit,
+       OUT PEDCA_PARM       pEdcaParm,
+       OUT PQBSS_LOAD_PARM  pQbssLoad,
+       OUT PQOS_CAPABILITY_PARM pQosCapability,
+       OUT ULONG *pRalinkIe,
+       OUT UCHAR                *pHtCapabilityLen,
+#ifdef CONFIG_STA_SUPPORT
+       OUT UCHAR                *pPreNHtCapabilityLen,
+#endif // CONFIG_STA_SUPPORT //
+       OUT HT_CAPABILITY_IE *pHtCapability,
+       OUT UCHAR                *AddHtInfoLen,
+       OUT ADD_HT_INFO_IE *AddHtInfo,
+       OUT UCHAR *NewExtChannel,
+       OUT USHORT *LengthVIE,
+       OUT PNDIS_802_11_VARIABLE_IEs pVIE);
+
+BOOLEAN PeerAddBAReqActionSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *pMsg,
+    IN ULONG MsgLen,
+       OUT PUCHAR pAddr2);
+
+BOOLEAN PeerAddBARspActionSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *pMsg,
+    IN ULONG MsgLen);
+
+BOOLEAN PeerDelBAActionSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN UCHAR Wcid,
+    IN VOID *pMsg,
+    IN ULONG MsgLen);
+
+BOOLEAN MlmeAssocReqSanity(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  VOID *Msg,
+       IN  ULONG MsgLen,
+       OUT PUCHAR pApAddr,
+       OUT USHORT *CapabilityInfo,
+       OUT ULONG *Timeout,
+       OUT USHORT *ListenIntv);
+
+BOOLEAN MlmeAuthReqSanity(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  VOID *Msg,
+       IN  ULONG MsgLen,
+       OUT PUCHAR pAddr,
+       OUT ULONG *Timeout,
+       OUT USHORT *Alg);
+
+BOOLEAN MlmeStartReqSanity(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  VOID *Msg,
+       IN  ULONG MsgLen,
+       OUT CHAR Ssid[],
+       OUT UCHAR *Ssidlen);
+
+BOOLEAN PeerAuthSanity(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  VOID *Msg,
+       IN  ULONG MsgLen,
+       OUT PUCHAR pAddr,
+       OUT USHORT *Alg,
+       OUT USHORT *Seq,
+       OUT USHORT *Status,
+       OUT CHAR ChlgText[]);
+
+BOOLEAN PeerAssocRspSanity(
+       IN  PRTMP_ADAPTER   pAd,
+    IN VOID *pMsg,
+       IN  ULONG MsgLen,
+       OUT PUCHAR pAddr2,
+       OUT USHORT *pCapabilityInfo,
+       OUT USHORT *pStatus,
+       OUT USHORT *pAid,
+       OUT UCHAR SupRate[],
+       OUT UCHAR *pSupRateLen,
+       OUT UCHAR ExtRate[],
+       OUT UCHAR *pExtRateLen,
+    OUT HT_CAPABILITY_IE               *pHtCapability,
+    OUT ADD_HT_INFO_IE         *pAddHtInfo,    // AP might use this additional ht info IE
+    OUT UCHAR                  *pHtCapabilityLen,
+    OUT UCHAR                  *pAddHtInfoLen,
+    OUT UCHAR                  *pNewExtChannelOffset,
+       OUT PEDCA_PARM pEdcaParm,
+       OUT UCHAR *pCkipFlag);
+
+BOOLEAN PeerDisassocSanity(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  VOID *Msg,
+       IN  ULONG MsgLen,
+       OUT PUCHAR pAddr2,
+       OUT USHORT *Reason);
+
+BOOLEAN PeerWpaMessageSanity(
+    IN         PRTMP_ADAPTER           pAd,
+    IN         PEAPOL_PACKET           pMsg,
+    IN         ULONG                           MsgLen,
+    IN         UCHAR                           MsgType,
+    IN         MAC_TABLE_ENTRY         *pEntry);
+
+BOOLEAN PeerDeauthSanity(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  VOID *Msg,
+       IN  ULONG MsgLen,
+       OUT PUCHAR pAddr2,
+       OUT USHORT *Reason);
+
+BOOLEAN PeerProbeReqSanity(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  VOID *Msg,
+       IN  ULONG MsgLen,
+       OUT PUCHAR pAddr2,
+       OUT CHAR Ssid[],
+       OUT UCHAR *pSsidLen);
+
+BOOLEAN GetTimBit(
+       IN  CHAR *Ptr,
+       IN  USHORT Aid,
+       OUT UCHAR *TimLen,
+       OUT UCHAR *BcastFlag,
+       OUT UCHAR *DtimCount,
+       OUT UCHAR *DtimPeriod,
+       OUT UCHAR *MessageToMe);
+
+UCHAR ChannelSanity(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR channel);
+
+NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(
+       IN PBSS_ENTRY pBss);
+
+#if 0  // It's omitted
+NDIS_STATUS    RTMPWepKeySanity(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PVOID                   pBuf);
+#endif
+
+BOOLEAN MlmeDelBAReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen);
+
+BOOLEAN MlmeAddBAReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr2);
+
+ULONG MakeOutgoingFrame(
+       OUT CHAR *Buffer,
+       OUT ULONG *Length, ...);
+
+VOID  LfsrInit(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  ULONG Seed);
+
+UCHAR RandomByte(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID AsicUpdateAutoFallBackTable(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pTxRate);
+
+VOID  MlmePeriodicExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID LinkDownExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID LinkUpExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID STAMlmePeriodicExec(
+       PRTMP_ADAPTER pAd);
+
+VOID MlmeAutoScan(
+       IN PRTMP_ADAPTER pAd);
+
+VOID MlmeAutoReconnectLastSSID(
+       IN PRTMP_ADAPTER pAd);
+
+BOOLEAN MlmeValidateSSID(
+       IN PUCHAR pSsid,
+       IN UCHAR  SsidLen);
+
+VOID MlmeCheckForRoaming(
+       IN PRTMP_ADAPTER pAd,
+       IN ULONG    Now32);
+
+VOID MlmeCheckForFastRoaming(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  ULONG           Now);
+
+VOID MlmeDynamicTxRateSwitching(
+       IN PRTMP_ADAPTER pAd);
+
+VOID MlmeSetTxRate(
+       IN PRTMP_ADAPTER                pAd,
+       IN PMAC_TABLE_ENTRY             pEntry,
+       IN PRTMP_TX_RATE_SWITCH pTxRate);
+
+VOID MlmeSelectTxRateTable(
+       IN PRTMP_ADAPTER                pAd,
+       IN PMAC_TABLE_ENTRY             pEntry,
+       IN PUCHAR                               *ppTable,
+       IN PUCHAR                               pTableSize,
+       IN PUCHAR                               pInitTxRateIdx);
+
+VOID MlmeCalculateChannelQuality(
+       IN PRTMP_ADAPTER pAd,
+       IN ULONG Now);
+
+VOID MlmeCheckPsmChange(
+       IN PRTMP_ADAPTER pAd,
+       IN ULONG    Now32);
+
+VOID MlmeSetPsmBit(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT psm);
+
+VOID MlmeSetTxPreamble(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT TxPreamble);
+
+VOID UpdateBasicRateBitmap(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID MlmeUpdateTxRates(
+       IN PRTMP_ADAPTER        pAd,
+       IN      BOOLEAN                 bLinkUp,
+       IN      UCHAR                   apidx);
+
+#ifdef DOT11_N_SUPPORT
+VOID MlmeUpdateHtTxRates(
+       IN PRTMP_ADAPTER                pAd,
+       IN      UCHAR                           apidx);
+#endif // DOT11_N_SUPPORT //
+
+VOID    RTMPCheckRates(
+       IN      PRTMP_ADAPTER   pAd,
+       IN OUT  UCHAR           SupRate[],
+       IN OUT  UCHAR           *SupRateLen);
+
+#ifdef CONFIG_STA_SUPPORT
+BOOLEAN RTMPCheckChannel(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR                CentralChannel,
+       IN UCHAR                Channel);
+#endif // CONFIG_STA_SUPPORT //
+
+BOOLEAN        RTMPCheckHt(
+       IN              PRTMP_ADAPTER   pAd,
+       IN              UCHAR   Wcid,
+       IN OUT  HT_CAPABILITY_IE                        *pHtCapability,
+       IN OUT  ADD_HT_INFO_IE                  *pAddHtInfo);
+
+VOID StaQuickResponeForRateUpExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID AsicBbpTuning1(
+       IN PRTMP_ADAPTER pAd);
+
+VOID AsicBbpTuning2(
+       IN PRTMP_ADAPTER pAd);
+
+VOID RTMPUpdateMlmeRate(
+       IN PRTMP_ADAPTER        pAd);
+
+CHAR RTMPMaxRssi(
+       IN PRTMP_ADAPTER        pAd,
+       IN CHAR                         Rssi0,
+       IN CHAR                         Rssi1,
+       IN CHAR                         Rssi2);
+
+VOID AsicEvaluateRxAnt(
+       IN PRTMP_ADAPTER        pAd);
+
+VOID AsicRxAntEvalTimeout(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID APSDPeriodicExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
+       IN PRTMP_ADAPTER    pAd,
+       IN PMAC_TABLE_ENTRY     pEntry);
+
+UCHAR RTMPStaFixedTxMode(
+       IN PRTMP_ADAPTER    pAd,
+       IN PMAC_TABLE_ENTRY     pEntry);
+
+VOID RTMPUpdateLegacyTxSetting(
+               UCHAR                           fixed_tx_mode,
+               PMAC_TABLE_ENTRY        pEntry);
+
+BOOLEAN RTMPAutoRateSwitchCheck(
+       IN PRTMP_ADAPTER    pAd);
+
+NDIS_STATUS MlmeInit(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID MlmeHandler(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID MlmeHalt(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID MlmeResetRalinkCounters(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID BuildChannelList(
+       IN PRTMP_ADAPTER pAd);
+
+UCHAR FirstChannel(
+       IN  PRTMP_ADAPTER   pAd);
+
+UCHAR NextChannel(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR channel);
+
+VOID ChangeToCellPowerLimit(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR         AironetCellPowerLimit);
+
+VOID RaiseClock(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UINT32 *x);
+
+VOID LowerClock(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UINT32 *x);
+
+USHORT ShiftInBits(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID ShiftOutBits(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  USHORT data,
+       IN  USHORT count);
+
+VOID EEpromCleanup(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID EWDS(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID EWEN(
+       IN  PRTMP_ADAPTER   pAd);
+
+USHORT RTMP_EEPROM_READ16(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  USHORT Offset);
+
+VOID RTMP_EEPROM_WRITE16(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  USHORT Offset,
+       IN  USHORT Data);
+
+//
+// Prototypes of function definition in rtmp_tkip.c
+//
+VOID    RTMPInitTkipEngine(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pTKey,
+       IN  UCHAR           KeyId,
+       IN  PUCHAR          pTA,
+       IN  PUCHAR          pMICKey,
+       IN  PUCHAR          pTSC,
+       OUT PULONG          pIV16,
+       OUT PULONG          pIV32);
+
+VOID    RTMPInitMICEngine(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pKey,
+       IN  PUCHAR          pDA,
+       IN  PUCHAR          pSA,
+       IN  UCHAR           UserPriority,
+       IN  PUCHAR          pMICKey);
+
+BOOLEAN RTMPTkipCompareMICValue(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pSrc,
+       IN  PUCHAR          pDA,
+       IN  PUCHAR          pSA,
+       IN  PUCHAR          pMICKey,
+       IN      UCHAR                   UserPriority,
+       IN  UINT            Len);
+
+VOID    RTMPCalculateMICValue(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PNDIS_PACKET    pPacket,
+       IN  PUCHAR          pEncap,
+       IN  PCIPHER_KEY     pKey,
+       IN      UCHAR                   apidx);
+
+BOOLEAN RTMPTkipCompareMICValueWithLLC(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pLLC,
+       IN  PUCHAR          pSrc,
+       IN  PUCHAR          pDA,
+       IN  PUCHAR          pSA,
+       IN  PUCHAR          pMICKey,
+       IN  UINT            Len);
+
+VOID    RTMPTkipAppendByte(
+       IN  PTKIP_KEY_INFO  pTkip,
+       IN  UCHAR           uChar);
+
+VOID    RTMPTkipAppend(
+       IN  PTKIP_KEY_INFO  pTkip,
+       IN  PUCHAR          pSrc,
+       IN  UINT            nBytes);
+
+VOID    RTMPTkipGetMIC(
+       IN  PTKIP_KEY_INFO  pTkip);
+
+BOOLEAN RTMPSoftDecryptTKIP(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR       pData,
+       IN ULONG        DataByteCnt,
+       IN UCHAR    UserPriority,
+       IN PCIPHER_KEY  pWpaKey);
+
+BOOLEAN RTMPSoftDecryptAES(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR       pData,
+       IN ULONG        DataByteCnt,
+       IN PCIPHER_KEY  pWpaKey);
+
+#if 0  // removed by AlbertY
+NDIS_STATUS RTMPWPAAddKeyProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PVOID           pBuf);
+#endif
+
+//
+// Prototypes of function definition in cmm_info.c
+//
+NDIS_STATUS RTMPWPARemoveKeyProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PVOID           pBuf);
+
+VOID    RTMPWPARemoveAllKeys(
+       IN  PRTMP_ADAPTER   pAd);
+
+BOOLEAN RTMPCheckStrPrintAble(
+    IN  CHAR *pInPutStr,
+    IN  UCHAR strLen);
+
+VOID    RTMPSetPhyMode(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  ULONG phymode);
+
+VOID   RTMPUpdateHTIE(
+       IN      RT_HT_CAPABILITY        *pRtHt,
+       IN              UCHAR                           *pMcsSet,
+       OUT             HT_CAPABILITY_IE *pHtCapability,
+       OUT             ADD_HT_INFO_IE          *pAddHtInfo);
+
+VOID   RTMPAddWcidAttributeEntry(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   BssIdx,
+       IN      UCHAR                   KeyIdx,
+       IN      UCHAR                   CipherAlg,
+       IN      MAC_TABLE_ENTRY *pEntry);
+
+CHAR *GetEncryptType(
+       CHAR enc);
+
+CHAR *GetAuthMode(
+       CHAR auth);
+
+VOID RTMPIoctlGetSiteSurvey(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq);
+
+VOID RTMPIoctlGetMacTable(
+       IN PRTMP_ADAPTER pAd,
+       IN struct iwreq *wrq);
+
+VOID RTMPIndicateWPA2Status(
+       IN  PRTMP_ADAPTER  pAdapter);
+
+VOID   RTMPOPModeSwitching(
+       IN      PRTMP_ADAPTER   pAd);
+
+#ifdef CONFIG_STA_SUPPORT
+VOID    RTMPAddBSSIDCipher(
+    IN  PRTMP_ADAPTER   pAd,
+       IN      UCHAR   Aid,
+    IN  PNDIS_802_11_KEY    pKey,
+    IN  UCHAR   CipherAlg);
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+VOID   RTMPSetHT(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      OID_SET_HT_PHYMODE *pHTPhyMode);
+
+VOID   RTMPSetIndividualHT(
+       IN      PRTMP_ADAPTER           pAd,
+       IN      UCHAR                           apidx);
+#endif // DOT11_N_SUPPORT //
+
+VOID RTMPSendWirelessEvent(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Event_flag,
+       IN      PUCHAR                  pAddr,
+       IN  UCHAR                       BssIdx,
+       IN      CHAR                    Rssi);
+
+VOID   NICUpdateCntlCounters(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PHEADER_802_11  pHeader,
+       IN    UCHAR                     SubType,
+       IN      PRXWI_STRUC     pRxWI);
+//
+// prototype in wpa.c
+//
+BOOLEAN WpaMsgTypeSubst(
+       IN  UCHAR   EAPType,
+       OUT INT         *MsgType);
+
+VOID WpaPskStateMachineInit(
+       IN  PRTMP_ADAPTER       pAd,
+       IN  STATE_MACHINE       *S,
+       OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID WpaEAPOLKeyAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID    WpaPairMsg1Action(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID    WpaPairMsg3Action(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID    WpaGroupMsg1Action(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID    WpaMacHeaderInit(
+       IN      PRTMP_ADAPTER   pAd,
+       IN OUT  PHEADER_802_11  pHdr80211,
+       IN      UCHAR           wep,
+       IN      PUCHAR          pAddr1);
+
+VOID    Wpa2PairMsg1Action(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  MLME_QUEUE_ELEM *Elem);
+
+VOID    Wpa2PairMsg3Action(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  MLME_QUEUE_ELEM *Elem);
+
+BOOLEAN ParseKeyData(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          pKeyData,
+    IN  UCHAR           KeyDataLen,
+       IN      UCHAR                   bPairewise);
+
+VOID    RTMPToWirelessSta(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pHeader802_3,
+    IN  UINT            HdrLen,
+       IN  PUCHAR          pData,
+    IN  UINT            DataLen,
+    IN BOOLEAN                 is4wayFrame);
+
+VOID    HMAC_SHA1(
+       IN  UCHAR   *text,
+       IN  UINT    text_len,
+       IN  UCHAR   *key,
+       IN  UINT    key_len,
+       IN  UCHAR   *digest);
+
+VOID    PRF(
+       IN  UCHAR   *key,
+       IN  INT     key_len,
+       IN  UCHAR   *prefix,
+       IN  INT     prefix_len,
+       IN  UCHAR   *data,
+       IN  INT     data_len,
+       OUT UCHAR   *output,
+       IN  INT     len);
+
+VOID    CCKMPRF(
+       IN  UCHAR   *key,
+       IN  INT     key_len,
+       IN  UCHAR   *data,
+       IN  INT     data_len,
+       OUT UCHAR   *output,
+       IN  INT     len);
+
+VOID WpaCountPTK(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR   *PMK,
+       IN  UCHAR   *ANonce,
+       IN  UCHAR   *AA,
+       IN  UCHAR   *SNonce,
+       IN  UCHAR   *SA,
+       OUT UCHAR   *output,
+       IN  UINT    len);
+
+VOID    GenRandom(
+       IN  PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   *macAddr,
+       OUT     UCHAR                   *random);
+
+//
+// prototype in aironet.c
+//
+VOID    AironetStateMachineInit(
+       IN  PRTMP_ADAPTER       pAd,
+       IN  STATE_MACHINE       *S,
+       OUT STATE_MACHINE_FUNC  Trans[]);
+
+VOID    AironetMsgAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID    AironetRequestAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID    ChannelLoadRequestAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR           Index);
+
+VOID    NoiseHistRequestAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR           Index);
+
+VOID    BeaconRequestAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR           Index);
+
+VOID    AironetReportAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem);
+
+VOID    ChannelLoadReportAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR           Index);
+
+VOID    NoiseHistReportAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR           Index);
+
+VOID    AironetFinalReportAction(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID    BeaconReportAction(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UCHAR           Index);
+
+VOID    AironetAddBeaconReport(
+       IN  PRTMP_ADAPTER       pAd,
+       IN  ULONG               Index,
+       IN  PMLME_QUEUE_ELEM    pElem);
+
+VOID    AironetCreateBeaconReportFromBssTable(
+       IN  PRTMP_ADAPTER       pAd);
+
+VOID    DBGPRINT_TX_RING(
+       IN PRTMP_ADAPTER  pAd,
+       IN UCHAR          QueIdx);
+
+VOID DBGPRINT_RX_RING(
+       IN PRTMP_ADAPTER  pAd);
+
+CHAR    ConvertToRssi(
+       IN PRTMP_ADAPTER  pAd,
+       IN CHAR                         Rssi,
+       IN UCHAR    RssiNumber);
+
+
+#ifdef DOT11N_DRAFT3
+VOID BuildEffectedChannelList(
+       IN PRTMP_ADAPTER pAd);
+#endif // DOT11N_DRAFT3 //
+
+
+VOID APAsicEvaluateRxAnt(
+       IN PRTMP_ADAPTER        pAd);
+
+
+VOID APAsicRxAntEvalTimeout(
+       IN PRTMP_ADAPTER        pAd);
+
+//
+// function prototype in cmm_wpa.c
+//
+BOOLEAN RTMPCheckWPAframe(
+       IN PRTMP_ADAPTER pAd,
+       IN PMAC_TABLE_ENTRY     pEntry,
+       IN PUCHAR                       pData,
+       IN ULONG                        DataByteCount,
+       IN UCHAR                        FromWhichBSSID);
+
+VOID AES_GTK_KEY_UNWRAP(
+       IN  UCHAR   *key,
+       OUT UCHAR   *plaintext,
+       IN      UCHAR   c_len,
+       IN  UCHAR   *ciphertext);
+
+BOOLEAN RTMPCheckRSNIE(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pData,
+       IN  UCHAR           DataLen,
+       IN  MAC_TABLE_ENTRY *pEntry,
+       OUT     UCHAR                   *Offset);
+
+BOOLEAN RTMPParseEapolKeyData(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pKeyData,
+       IN  UCHAR           KeyDataLen,
+       IN      UCHAR                   GroupKeyIndex,
+       IN      UCHAR                   MsgType,
+       IN      BOOLEAN                 bWPA2,
+       IN  MAC_TABLE_ENTRY *pEntry);
+
+VOID   ConstructEapolMsg(
+       IN      PRTMP_ADAPTER           pAd,
+    IN         UCHAR                           PeerAuthMode,
+    IN         UCHAR                           PeerWepStatus,
+    IN         UCHAR                           MyGroupKeyWepStatus,
+    IN         UCHAR                           MsgType,
+    IN UCHAR                           DefaultKeyIdx,
+    IN         UCHAR                           *ReplayCounter,
+       IN      UCHAR                           *KeyNonce,
+       IN      UCHAR                           *TxRSC,
+       IN      UCHAR                           *PTK,
+       IN      UCHAR                           *GTK,
+       IN      UCHAR                           *RSNIE,
+       IN      UCHAR                           RSNIE_Len,
+    OUT PEAPOL_PACKET       pMsg);
+
+VOID   CalculateMIC(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   PeerWepStatus,
+       IN      UCHAR                   *PTK,
+       OUT PEAPOL_PACKET   pMsg);
+
+NDIS_STATUS    RTMPSoftDecryptBroadCastData(
+       IN      PRTMP_ADAPTER                                   pAd,
+       IN      RX_BLK                                                  *pRxBlk,
+       IN  NDIS_802_11_ENCRYPTION_STATUS       GroupCipher,
+       IN  PCIPHER_KEY                                         pShard_key);
+
+VOID   ConstructEapolKeyData(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   PeerAuthMode,
+       IN      UCHAR                   PeerWepStatus,
+       IN      UCHAR                   GroupKeyWepStatus,
+       IN      UCHAR                   MsgType,
+       IN      UCHAR                   DefaultKeyIdx,
+       IN      BOOLEAN                 bWPA2Capable,
+       IN      UCHAR                   *PTK,
+       IN      UCHAR                   *GTK,
+       IN      UCHAR                   *RSNIE,
+       IN      UCHAR                   RSNIE_LEN,
+       OUT PEAPOL_PACKET   pMsg);
+
+VOID RTMPMakeRSNIE(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  UINT            AuthMode,
+       IN  UINT            WepStatus,
+       IN      UCHAR                   apidx);
+
+//
+// function prototype in ap_wpa.c
+//
+
+BOOLEAN APWpaMsgTypeSubst(
+       IN UCHAR    EAPType,
+       OUT INT *MsgType) ;
+
+MAC_TABLE_ENTRY *PACInquiry(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  ULONG           Wcid);
+
+BOOLEAN RTMPCheckMcast(
+       IN PRTMP_ADAPTER pAd,
+       IN PEID_STRUCT      eid_ptr,
+       IN MAC_TABLE_ENTRY  *pEntry);
+
+BOOLEAN RTMPCheckUcast(
+       IN PRTMP_ADAPTER pAd,
+       IN PEID_STRUCT      eid_ptr,
+       IN MAC_TABLE_ENTRY  *pEntry);
+
+BOOLEAN RTMPCheckAUTH(
+       IN PRTMP_ADAPTER pAd,
+       IN PEID_STRUCT      eid_ptr,
+       IN MAC_TABLE_ENTRY  *pEntry);
+
+VOID WPAStart4WayHS(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MAC_TABLE_ENTRY *pEntry,
+       IN      ULONG                   TimeInterval);
+
+VOID WPAStart2WayGroupHS(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MAC_TABLE_ENTRY *pEntry);
+
+VOID APWpaEAPPacketAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID APWpaEAPOLStartAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID APWpaEAPOLLogoffAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID APWpaEAPOLKeyAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID APWpaEAPOLASFAlertAction(
+       IN  PRTMP_ADAPTER    pAd,
+       IN  MLME_QUEUE_ELEM  *Elem);
+
+VOID HandleCounterMeasure(
+       IN PRTMP_ADAPTER pAd,
+       IN MAC_TABLE_ENTRY  *pEntry);
+
+VOID PeerPairMsg2Action(
+       IN PRTMP_ADAPTER pAd,
+       IN MAC_TABLE_ENTRY  *pEntry,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerPairMsg4Action(
+       IN PRTMP_ADAPTER pAd,
+       IN MAC_TABLE_ENTRY  *pEntry,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID CMTimerExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID WPARetryExec(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3);
+
+VOID EnqueueStartForPSKExec(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3);
+
+VOID RTMPHandleSTAKey(
+    IN PRTMP_ADAPTER    pAdapter,
+    IN MAC_TABLE_ENTRY  *pEntry,
+    IN MLME_QUEUE_ELEM  *Elem);
+
+#if 0 // merge into PeerPairMsg4Action
+VOID Wpa1PeerPairMsg4Action(
+       IN PRTMP_ADAPTER pAd,
+       IN MAC_TABLE_ENTRY  *pEntry,
+       IN MLME_QUEUE_ELEM *Elem);
+
+VOID Wpa2PeerPairMsg4Action(
+       IN  PRTMP_ADAPTER    pAd,
+       IN  PMAC_TABLE_ENTRY pEntry,
+       IN  MLME_QUEUE_ELEM  *Elem);
+#endif // 0 //
+
+VOID PeerGroupMsg2Action(
+       IN  PRTMP_ADAPTER    pAd,
+       IN  PMAC_TABLE_ENTRY pEntry,
+       IN  VOID             *Msg,
+       IN  UINT             MsgLen);
+
+#if 0  // replaced by WPAStart2WayGroupHS
+NDIS_STATUS APWpaHardTransmit(
+       IN  PRTMP_ADAPTER    pAd,
+       IN  PMAC_TABLE_ENTRY pEntry);
+#endif // 0 //
+
+VOID PairDisAssocAction(
+       IN  PRTMP_ADAPTER    pAd,
+       IN  PMAC_TABLE_ENTRY pEntry,
+       IN  USHORT           Reason);
+
+VOID MlmeDeAuthAction(
+       IN  PRTMP_ADAPTER    pAd,
+       IN  PMAC_TABLE_ENTRY pEntry,
+       IN  USHORT           Reason);
+
+VOID GREKEYPeriodicExec(
+       IN  PVOID   SystemSpecific1,
+       IN  PVOID   FunctionContext,
+       IN  PVOID   SystemSpecific2,
+       IN  PVOID   SystemSpecific3);
+
+VOID CountGTK(
+       IN  UCHAR   *PMK,
+       IN  UCHAR   *GNonce,
+       IN  UCHAR   *AA,
+       OUT UCHAR   *output,
+       IN  UINT    len);
+
+VOID    GetSmall(
+       IN  PVOID   pSrc1,
+       IN  PVOID   pSrc2,
+       OUT PUCHAR  out,
+       IN  ULONG   Length);
+
+VOID    GetLarge(
+       IN  PVOID   pSrc1,
+       IN  PVOID   pSrc2,
+       OUT PUCHAR  out,
+       IN  ULONG   Length);
+
+VOID APGenRandom(
+       IN PRTMP_ADAPTER pAd,
+       OUT UCHAR       *random);
+
+VOID AES_GTK_KEY_WRAP(
+       IN UCHAR *key,
+       IN UCHAR *plaintext,
+       IN UCHAR p_len,
+       OUT UCHAR *ciphertext);
+
+VOID    WpaSend(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          pPacket,
+    IN  ULONG           Len);
+
+VOID    APToWirelessSta(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MAC_TABLE_ENTRY *pEntry,
+       IN  PUCHAR          pHeader802_3,
+       IN  UINT            HdrLen,
+       IN  PUCHAR          pData,
+       IN  UINT            DataLen,
+    IN BOOLEAN                 bClearFrame);
+
+VOID RTMPAddPMKIDCache(
+       IN  PRTMP_ADAPTER               pAd,
+       IN      INT                                             apidx,
+       IN      PUCHAR                          pAddr,
+       IN      UCHAR                                   *PMKID,
+       IN      UCHAR                                   *PMK);
+
+INT RTMPSearchPMKIDCache(
+       IN  PRTMP_ADAPTER   pAd,
+       IN      INT                             apidx,
+       IN      PUCHAR          pAddr);
+
+VOID RTMPDeletePMKIDCache(
+       IN  PRTMP_ADAPTER   pAd,
+       IN      INT                             apidx,
+       IN  INT                         idx);
+
+VOID RTMPMaintainPMKIDCache(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID   RTMPSendTriggerFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PVOID                   pBuffer,
+       IN      ULONG                   Length,
+       IN  UCHAR           TxRate,
+       IN      BOOLEAN                 bQosNull);
+
+
+//typedef void (*TIMER_FUNCTION)(unsigned long);
+
+
+/* timeout -- ms */
+VOID RTMP_SetPeriodicTimer(
+       IN      NDIS_MINIPORT_TIMER *pTimer,
+       IN      unsigned long timeout);
+
+VOID RTMP_OS_Init_Timer(
+       IN      PRTMP_ADAPTER pAd,
+       IN      NDIS_MINIPORT_TIMER *pTimer,
+       IN      TIMER_FUNCTION function,
+       IN      PVOID data);
+
+VOID RTMP_OS_Add_Timer(
+       IN      NDIS_MINIPORT_TIMER     *pTimer,
+       IN      unsigned long timeout);
+
+VOID RTMP_OS_Mod_Timer(
+       IN      NDIS_MINIPORT_TIMER     *pTimer,
+       IN      unsigned long timeout);
+
+
+VOID RTMP_OS_Del_Timer(
+       IN      NDIS_MINIPORT_TIMER     *pTimer,
+       OUT     BOOLEAN                          *pCancelled);
+
+
+VOID RTMP_OS_Release_Packet(
+       IN      PRTMP_ADAPTER pAd,
+       IN      PQUEUE_ENTRY  pEntry);
+
+VOID RTMPusecDelay(
+       IN      ULONG   usec);
+
+NDIS_STATUS os_alloc_mem(
+       IN      PRTMP_ADAPTER pAd,
+       OUT     PUCHAR *mem,
+       IN      ULONG  size);
+
+NDIS_STATUS os_free_mem(
+       IN      PRTMP_ADAPTER pAd,
+       IN      PUCHAR mem);
+
+
+void RTMP_AllocateSharedMemory(
+       IN      PRTMP_ADAPTER pAd,
+       IN      ULONG   Length,
+       IN      BOOLEAN Cached,
+       OUT     PVOID   *VirtualAddress,
+       OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+VOID RTMPFreeTxRxRingMemory(
+    IN  PRTMP_ADAPTER   pAd);
+
+NDIS_STATUS AdapterBlockAllocateMemory(
+       IN PVOID        handle,
+       OUT     PVOID   *ppAd);
+
+void RTMP_AllocateTxDescMemory(
+       IN      PRTMP_ADAPTER pAd,
+       IN      UINT    Index,
+       IN      ULONG   Length,
+       IN      BOOLEAN Cached,
+       OUT     PVOID   *VirtualAddress,
+       OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+void RTMP_AllocateFirstTxBuffer(
+       IN      PRTMP_ADAPTER pAd,
+       IN      UINT    Index,
+       IN      ULONG   Length,
+       IN      BOOLEAN Cached,
+       OUT     PVOID   *VirtualAddress,
+       OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+void RTMP_AllocateMgmtDescMemory(
+       IN      PRTMP_ADAPTER pAd,
+       IN      ULONG   Length,
+       IN      BOOLEAN Cached,
+       OUT     PVOID   *VirtualAddress,
+       OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+void RTMP_AllocateRxDescMemory(
+       IN      PRTMP_ADAPTER pAd,
+       IN      ULONG   Length,
+       IN      BOOLEAN Cached,
+       OUT     PVOID   *VirtualAddress,
+       OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+PNDIS_PACKET RTMP_AllocateRxPacketBuffer(
+       IN      PRTMP_ADAPTER pAd,
+       IN      ULONG   Length,
+       IN      BOOLEAN Cached,
+       OUT     PVOID   *VirtualAddress,
+       OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+PNDIS_PACKET RTMP_AllocateTxPacketBuffer(
+       IN      PRTMP_ADAPTER pAd,
+       IN      ULONG   Length,
+       IN      BOOLEAN Cached,
+       OUT     PVOID   *VirtualAddress);
+
+PNDIS_PACKET RTMP_AllocateFragPacketBuffer(
+       IN      PRTMP_ADAPTER pAd,
+       IN      ULONG   Length);
+
+void RTMP_QueryPacketInfo(
+       IN  PNDIS_PACKET pPacket,
+       OUT PACKET_INFO  *pPacketInfo,
+       OUT PUCHAR               *pSrcBufVA,
+       OUT     UINT             *pSrcBufLen);
+
+void RTMP_QueryNextPacketInfo(
+       IN  PNDIS_PACKET *ppPacket,
+       OUT PACKET_INFO  *pPacketInfo,
+       OUT PUCHAR               *pSrcBufVA,
+       OUT     UINT             *pSrcBufLen);
+
+
+BOOLEAN RTMP_FillTxBlkInfo(
+       IN RTMP_ADAPTER *pAd,
+       IN TX_BLK *pTxBlk);
+
+
+PRTMP_SCATTER_GATHER_LIST
+rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg);
+
+
+ void announce_802_3_packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket);
+
+
+UINT BA_Reorder_AMSDU_Annnounce(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket);
+
+
+UINT Handle_AMSDU_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize,
+       IN  UCHAR                       FromWhichBSSID);
+
+
+void convert_802_11_to_802_3_packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      PUCHAR                  p8023hdr,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize,
+       IN  UCHAR                       FromWhichBSSID);
+
+
+PNET_DEV get_netdev_from_bssid(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   FromWhichBSSID);
+
+
+PNDIS_PACKET duplicate_pkt(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pHeader802_3,
+    IN  UINT            HdrLen,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize,
+       IN      UCHAR                   FromWhichBSSID);
+
+
+PNDIS_PACKET duplicate_pkt_with_TKIP_MIC(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pOldPkt);
+
+PNDIS_PACKET duplicate_pkt_with_VLAN(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pHeader802_3,
+    IN  UINT            HdrLen,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize,
+       IN      UCHAR                   FromWhichBSSID);
+
+PNDIS_PACKET duplicate_pkt_with_WPI(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      UINT32                  ext_head_len,
+       IN      UINT32                  ext_tail_len);
+
+UCHAR VLAN_8023_Header_Copy(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pHeader802_3,
+       IN      UINT            HdrLen,
+       OUT PUCHAR                      pData,
+       IN      UCHAR                   FromWhichBSSID);
+
+#ifdef DOT11_N_SUPPORT
+void ba_flush_reordering_timeout_mpdus(
+       IN PRTMP_ADAPTER        pAd,
+       IN PBA_REC_ENTRY        pBAEntry,
+       IN ULONG                        Now32);
+
+
+VOID BAOriSessionSetUp(
+                       IN PRTMP_ADAPTER    pAd,
+                       IN MAC_TABLE_ENTRY      *pEntry,
+                       IN UCHAR                        TID,
+                       IN USHORT                       TimeOut,
+                       IN ULONG                        DelayTime,
+                       IN BOOLEAN              isForced);
+
+VOID BASessionTearDownALL(
+       IN OUT  PRTMP_ADAPTER pAd,
+       IN              UCHAR Wcid);
+#endif // DOT11_N_SUPPORT //
+
+BOOLEAN OS_Need_Clone_Packet(void);
+
+
+VOID build_tx_packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      PUCHAR  pFrame,
+       IN      ULONG   FrameLen);
+
+
+VOID BAOriSessionTearDown(
+       IN OUT  PRTMP_ADAPTER   pAd,
+       IN              UCHAR                   Wcid,
+       IN              UCHAR                   TID,
+       IN              BOOLEAN                 bPassive,
+       IN              BOOLEAN                 bForceSend);
+
+VOID BARecSessionTearDown(
+       IN OUT  PRTMP_ADAPTER   pAd,
+       IN              UCHAR                   Wcid,
+       IN              UCHAR                   TID,
+       IN              BOOLEAN                 bPassive);
+
+BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num);
+void ba_reordering_resource_release(PRTMP_ADAPTER pAd);
+
+ULONG AutoChBssInsertEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pBssid,
+       IN CHAR Ssid[],
+       IN UCHAR SsidLen,
+       IN UCHAR ChannelNo,
+       IN CHAR Rssi);
+
+void AutoChBssTableInit(
+       IN PRTMP_ADAPTER pAd);
+
+void ChannelInfoInit(
+       IN PRTMP_ADAPTER pAd);
+
+void AutoChBssTableDestroy(
+       IN PRTMP_ADAPTER pAd);
+
+void ChannelInfoDestroy(
+       IN PRTMP_ADAPTER pAd);
+
+UCHAR New_ApAutoSelectChannel(
+       IN PRTMP_ADAPTER pAd);
+
+BOOLEAN rtstrmactohex(
+       IN char *s1,
+       IN char *s2);
+
+BOOLEAN rtstrcasecmp(
+       IN char *s1,
+       IN char *s2);
+
+char *rtstrstruncasecmp(
+       IN char *s1,
+       IN char *s2);
+
+char    *rtstrstr(
+       IN      const char * s1,
+       IN      const char * s2);
+
+char *rstrtok(
+       IN char * s,
+       IN const char * ct);
+
+int rtinet_aton(
+       const char *cp,
+       unsigned int *addr);
+
+////////// common ioctl functions //////////
+INT Set_DriverVersion_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_CountryRegion_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_CountryRegionABand_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_WirelessMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_Channel_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ShortSlot_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_TxPower_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_BGProtection_Proc(
+       IN  PRTMP_ADAPTER               pAd,
+       IN  PUCHAR                      arg);
+
+INT Set_TxPreamble_Proc(
+       IN  PRTMP_ADAPTER               pAd,
+       IN  PUCHAR                      arg);
+
+INT Set_RTSThreshold_Proc(
+       IN  PRTMP_ADAPTER               pAd,
+       IN  PUCHAR                      arg);
+
+INT Set_FragThreshold_Proc(
+       IN  PRTMP_ADAPTER               pAd,
+       IN  PUCHAR                      arg);
+
+INT Set_TxBurst_Proc(
+       IN  PRTMP_ADAPTER               pAd,
+       IN  PUCHAR                      arg);
+
+#ifdef AGGREGATION_SUPPORT
+INT    Set_PktAggregate_Proc(
+       IN  PRTMP_ADAPTER               pAd,
+       IN  PUCHAR                      arg);
+#endif
+
+INT    Set_IEEE80211H_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+#ifdef DBG
+INT    Set_Debug_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif
+
+INT    Show_DescInfo_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ResetStatCounter_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+#ifdef DOT11_N_SUPPORT
+INT    Set_BASetup_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_BADecline_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_BAOriTearDown_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_BARecTearDown_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtBw_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtMcs_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtGi_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtOpMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtStbc_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtHtc_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtExtcha_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtMpduDensity_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtBaWinSize_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtRdg_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtLinkAdapt_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtAmsdu_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtAutoBa_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtProtect_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtMimoPs_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+
+INT    Set_ForceShortGI_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_ForceGF_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    SetCommonHT(
+       IN      PRTMP_ADAPTER   pAd);
+
+INT    Set_SendPSMPAction_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT    Set_HtMIMOPSmode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+
+INT    Set_HtTxBASize_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif // DOT11_N_SUPPORT //
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+//Dls ,        kathy
+VOID RTMPSendDLSTearDownFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pDA);
+
+#ifdef DOT11_N_SUPPORT
+//Block ACK
+VOID QueryBATABLE(
+       IN  PRTMP_ADAPTER pAd,
+       OUT PQUERYBA_TABLE pBAT);
+#endif // DOT11_N_SUPPORT //
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+INT        WpaCheckEapCode(
+       IN  PRTMP_ADAPTER       pAd,
+       IN  PUCHAR                              pFrame,
+       IN  USHORT                              FrameLen,
+       IN  USHORT                              OffSet);
+
+VOID    WpaSendMicFailureToWpaSupplicant(
+    IN  PRTMP_ADAPTER       pAd,
+    IN  BOOLEAN             bUnicast);
+
+VOID    SendAssocIEsToWpaSupplicant(
+    IN  PRTMP_ADAPTER       pAd);
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+int wext_notify_event_assoc(
+       IN  RTMP_ADAPTER *pAd);
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+#endif // CONFIG_STA_SUPPORT //
+
+
+
+#ifdef DOT11_N_SUPPORT
+VOID Handle_BSS_Width_Trigger_Events(
+       IN PRTMP_ADAPTER pAd);
+
+void build_ext_channel_switch_ie(
+       IN PRTMP_ADAPTER pAd,
+       IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE);
+#endif // DOT11_N_SUPPORT //
+
+
+BOOLEAN APRxDoneInterruptHandle(
+       IN      PRTMP_ADAPTER   pAd);
+
+BOOLEAN STARxDoneInterruptHandle(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      BOOLEAN                 argc);
+
+#ifdef DOT11_N_SUPPORT
+// AMPDU packet indication
+VOID Indicate_AMPDU_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID);
+
+// AMSDU packet indication
+VOID Indicate_AMSDU_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID);
+#endif // DOT11_N_SUPPORT //
+
+// Normal legacy Rx packet indication
+VOID Indicate_Legacy_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID);
+
+VOID Indicate_EAPOL_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID);
+
+void  update_os_packet_info(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID);
+
+void wlan_802_11_to_802_3_packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      PUCHAR                  pHeader802_3,
+       IN  UCHAR                       FromWhichBSSID);
+
+UINT deaggregate_AMSDU_announce(
+       IN      PRTMP_ADAPTER   pAd,
+       PNDIS_PACKET            pPacket,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize);
+
+
+#ifdef CONFIG_STA_SUPPORT
+// remove LLC and get 802_3 Header
+#define  RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(_pRxBlk, _pHeader802_3)   \
+{                                                                                                                                                              \
+       PUCHAR _pRemovedLLCSNAP = NULL, _pDA, _pSA;                                 \
+                                                                                                                                                               \
+       if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_MESH))                                    \
+       {                                                                           \
+               _pDA = _pRxBlk->pHeader->Addr3;                                         \
+               _pSA = (PUCHAR)_pRxBlk->pHeader + sizeof(HEADER_802_11);                \
+       }                                                                           \
+       else                                                                        \
+       {                                                                           \
+               if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_INFRA))                               \
+               {                                                                       \
+                       _pDA = _pRxBlk->pHeader->Addr1;                                     \
+               if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_DLS))                                                                 \
+                       _pSA = _pRxBlk->pHeader->Addr2;                                                                         \
+               else                                                                                                                                    \
+                       _pSA = _pRxBlk->pHeader->Addr3;                                     \
+               }                                                                       \
+               else                                                                    \
+               {                                                                       \
+                       _pDA = _pRxBlk->pHeader->Addr1;                                     \
+                       _pSA = _pRxBlk->pHeader->Addr2;                                     \
+               }                                                                       \
+       }                                                                           \
+                                                                                                                                                               \
+       CONVERT_TO_802_3(_pHeader802_3, _pDA, _pSA, _pRxBlk->pData,                             \
+               _pRxBlk->DataSize, _pRemovedLLCSNAP);                                   \
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+BOOLEAN APFowardWirelessStaToWirelessSta(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      ULONG                   FromWhichBSSID);
+
+VOID Announce_or_Forward_802_3_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      UCHAR                   FromWhichBSSID);
+
+VOID Sta_Announce_or_Forward_802_3_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      UCHAR                   FromWhichBSSID);
+
+
+#ifdef CONFIG_STA_SUPPORT
+#define ANNOUNCE_OR_FORWARD_802_3_PACKET(_pAd, _pPacket, _FromWhichBSS)\
+                       Sta_Announce_or_Forward_802_3_Packet(_pAd, _pPacket, _FromWhichBSS);
+                       //announce_802_3_packet(_pAd, _pPacket);
+#endif // CONFIG_STA_SUPPORT //
+
+
+PNDIS_PACKET DuplicatePacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      UCHAR                   FromWhichBSSID);
+
+
+PNDIS_PACKET ClonePacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize);
+
+
+// Normal, AMPDU or AMSDU
+VOID CmmRxnonRalinkFrameIndicate(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID);
+
+VOID CmmRxRalinkFrameIndicate(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MAC_TABLE_ENTRY *pEntry,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID);
+
+VOID Update_Rssi_Sample(
+       IN PRTMP_ADAPTER        pAd,
+       IN RSSI_SAMPLE          *pRssi,
+       IN PRXWI_STRUC          pRxWI);
+
+PNDIS_PACKET GetPacketFromRxRing(
+       IN              PRTMP_ADAPTER   pAd,
+       OUT             PRT28XX_RXD_STRUC               pSaveRxD,
+       OUT             BOOLEAN                 *pbReschedule,
+       IN OUT  UINT32                  *pRxPending);
+
+PNDIS_PACKET RTMPDeFragmentDataFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk);
+
+////////////////////////////////////////
+
+
+
+
+
+#ifdef SNMP_SUPPORT
+//for snmp , kathy
+typedef struct _DefaultKeyIdxValue
+{
+       UCHAR   KeyIdx;
+       UCHAR   Value[16];
+} DefaultKeyIdxValue, *PDefaultKeyIdxValue;
+#endif
+
+
+#ifdef CONFIG_STA_SUPPORT
+enum {
+       DIDmsg_lnxind_wlansniffrm               = 0x00000044,
+       DIDmsg_lnxind_wlansniffrm_hosttime      = 0x00010044,
+       DIDmsg_lnxind_wlansniffrm_mactime       = 0x00020044,
+       DIDmsg_lnxind_wlansniffrm_channel       = 0x00030044,
+       DIDmsg_lnxind_wlansniffrm_rssi          = 0x00040044,
+       DIDmsg_lnxind_wlansniffrm_sq            = 0x00050044,
+       DIDmsg_lnxind_wlansniffrm_signal        = 0x00060044,
+       DIDmsg_lnxind_wlansniffrm_noise         = 0x00070044,
+       DIDmsg_lnxind_wlansniffrm_rate          = 0x00080044,
+       DIDmsg_lnxind_wlansniffrm_istx          = 0x00090044,
+       DIDmsg_lnxind_wlansniffrm_frmlen        = 0x000A0044
+};
+enum {
+       P80211ENUM_msgitem_status_no_value      = 0x00
+};
+enum {
+       P80211ENUM_truth_false                  = 0x00,
+       P80211ENUM_truth_true                   = 0x01
+};
+
+/* Definition from madwifi */
+typedef struct {
+        UINT32 did;
+        UINT16 status;
+        UINT16 len;
+        UINT32 data;
+} p80211item_uint32_t;
+
+typedef struct {
+        UINT32 msgcode;
+        UINT32 msglen;
+#define WLAN_DEVNAMELEN_MAX 16
+        UINT8 devname[WLAN_DEVNAMELEN_MAX];
+        p80211item_uint32_t hosttime;
+        p80211item_uint32_t mactime;
+        p80211item_uint32_t channel;
+        p80211item_uint32_t rssi;
+        p80211item_uint32_t sq;
+        p80211item_uint32_t signal;
+        p80211item_uint32_t noise;
+        p80211item_uint32_t rate;
+        p80211item_uint32_t istx;
+        p80211item_uint32_t frmlen;
+} wlan_ng_prism2_header;
+
+/* The radio capture header precedes the 802.11 header. */
+typedef struct PACKED _ieee80211_radiotap_header {
+    UINT8      it_version;     /* Version 0. Only increases
+                                * for drastic changes,
+                                * introduction of compatible
+                                * new fields does not count.
+                                */
+    UINT8      it_pad;
+    UINT16     it_len;         /* length of the whole
+                                * header in bytes, including
+                                * it_version, it_pad,
+                                * it_len, and data fields.
+                                */
+    UINT32   it_present;       /* A bitmap telling which
+                                        * fields are present. Set bit 31
+                                        * (0x80000000) to extend the
+                                        * bitmap by another 32 bits.
+                                        * Additional extensions are made
+                                        * by setting bit 31.
+                                        */
+}ieee80211_radiotap_header ;
+
+enum ieee80211_radiotap_type {
+    IEEE80211_RADIOTAP_TSFT = 0,
+    IEEE80211_RADIOTAP_FLAGS = 1,
+    IEEE80211_RADIOTAP_RATE = 2,
+    IEEE80211_RADIOTAP_CHANNEL = 3,
+    IEEE80211_RADIOTAP_FHSS = 4,
+    IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+    IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+    IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+    IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+    IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+    IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+    IEEE80211_RADIOTAP_ANTENNA = 11,
+    IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+    IEEE80211_RADIOTAP_DB_ANTNOISE = 13
+};
+
+#define WLAN_RADIOTAP_PRESENT (                        \
+       (1 << IEEE80211_RADIOTAP_TSFT)  |       \
+       (1 << IEEE80211_RADIOTAP_FLAGS) |       \
+       (1 << IEEE80211_RADIOTAP_RATE)  |       \
+        0)
+
+typedef struct _wlan_radiotap_header {
+       ieee80211_radiotap_header wt_ihdr;
+       INT64 wt_tsft;
+       UINT8 wt_flags;
+       UINT8 wt_rate;
+} wlan_radiotap_header;
+/* Definition from madwifi */
+
+void send_monitor_packets(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk);
+
+#if WIRELESS_EXT >= 12
+// This function will be called when query /proc
+struct iw_statistics *rt28xx_get_wireless_stats(
+    IN struct net_device *net_dev);
+#endif
+
+VOID    RTMPSetDesiredRates(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  LONG            Rates);
+#endif // CONFIG_STA_SUPPORT //
+
+INT    Set_FixedTxMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+INT    Set_OpMode_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+static inline char* GetPhyMode(
+       int Mode)
+{
+       switch(Mode)
+       {
+               case MODE_CCK:
+                       return "CCK";
+
+               case MODE_OFDM:
+                       return "OFDM";
+#ifdef DOT11_N_SUPPORT
+               case MODE_HTMIX:
+                       return "HTMIX";
+
+               case MODE_HTGREENFIELD:
+                       return "GREEN";
+#endif // DOT11_N_SUPPORT //
+               default:
+                       return "N/A";
+       }
+}
+
+
+static inline char* GetBW(
+       int BW)
+{
+       switch(BW)
+       {
+               case BW_10:
+                       return "10M";
+
+               case BW_20:
+                       return "20M";
+#ifdef DOT11_N_SUPPORT
+               case BW_40:
+                       return "40M";
+#endif // DOT11_N_SUPPORT //
+               default:
+                       return "N/A";
+       }
+}
+
+
+VOID RT28xxThreadTerminate(
+       IN RTMP_ADAPTER *pAd);
+
+BOOLEAN RT28XXChipsetCheck(
+       IN void *_dev_p);
+
+BOOLEAN RT28XXNetDevInit(
+       IN void                                 *_dev_p,
+       IN struct  net_device   *net_dev,
+       IN RTMP_ADAPTER                 *pAd);
+
+BOOLEAN RT28XXProbePostConfig(
+       IN void                                 *_dev_p,
+       IN RTMP_ADAPTER                 *pAd,
+       IN INT32                                argc);
+
+VOID RT28XXDMADisable(
+       IN RTMP_ADAPTER                 *pAd);
+
+VOID RT28XXDMAEnable(
+       IN RTMP_ADAPTER                 *pAd);
+
+VOID RT28xx_UpdateBeaconToAsic(
+       IN RTMP_ADAPTER * pAd,
+       IN INT apidx,
+       IN ULONG BeaconLen,
+       IN ULONG UpdatePos);
+
+INT rt28xx_ioctl(
+       IN      struct net_device       *net_dev,
+       IN      OUT     struct ifreq    *rq,
+       IN      INT                     cmd);
+
+
+#ifdef CONFIG_STA_SUPPORT
+INT rt28xx_sta_ioctl(
+       IN      struct net_device       *net_dev,
+       IN      OUT     struct ifreq    *rq,
+       IN      INT                     cmd);
+#endif // CONFIG_STA_SUPPORT //
+
+BOOLEAN RT28XXSecurityKeyAdd(
+       IN              PRTMP_ADAPTER           pAd,
+       IN              ULONG                           apidx,
+       IN              ULONG                           KeyIdx,
+       IN              MAC_TABLE_ENTRY         *pEntry);
+
+////////////////////////////////////////
+PNDIS_PACKET GetPacketFromRxRing(
+       IN              PRTMP_ADAPTER   pAd,
+       OUT             PRT28XX_RXD_STRUC       pSaveRxD,
+       OUT             BOOLEAN                 *pbReschedule,
+       IN OUT  UINT32                  *pRxPending);
+
+
+void kill_thread_task(PRTMP_ADAPTER pAd);
+
+void tbtt_tasklet(unsigned long data);
+
+
+VOID AsicTurnOffRFClk(
+       IN PRTMP_ADAPTER    pAd,
+       IN      UCHAR           Channel);
+
+VOID AsicTurnOnRFClk(
+       IN PRTMP_ADAPTER        pAd,
+       IN      UCHAR                   Channel);
+
+#ifdef RT2870
+//
+// Function Prototype in rtusb_bulk.c
+//
+VOID   RTUSBInitTxDesc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTX_CONTEXT             pTxContext,
+       IN      UCHAR                   BulkOutPipeId,
+       IN      usb_complete_t  Func);
+
+VOID   RTUSBInitHTTxDesc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PHT_TX_CONTEXT  pTxContext,
+       IN      UCHAR                   BulkOutPipeId,
+       IN      ULONG                   BulkOutSize,
+       IN      usb_complete_t  Func);
+
+VOID   RTUSBInitRxDesc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PRX_CONTEXT             pRxContext);
+
+VOID RTUSBCleanUpDataBulkOutQueue(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID RTUSBCancelPendingBulkOutIRP(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID RTUSBBulkOutDataPacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   BulkOutPipeId,
+       IN      UCHAR                   Index);
+
+VOID RTUSBBulkOutNullFrame(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID RTUSBBulkOutRTSFrame(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID RTUSBCancelPendingBulkInIRP(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID RTUSBCancelPendingIRPs(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID RTUSBBulkOutMLMEPacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Index);
+
+VOID RTUSBBulkOutPsPoll(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID RTUSBCleanUpMLMEBulkOutQueue(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID RTUSBKickBulkOut(
+       IN      PRTMP_ADAPTER pAd);
+
+VOID   RTUSBBulkReceive(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID DoBulkIn(
+       IN RTMP_ADAPTER *pAd);
+
+VOID RTUSBInitRxDesc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN  PRX_CONTEXT         pRxContext);
+
+VOID RTUSBBulkRxHandle(
+       IN unsigned long data);
+
+//
+// Function Prototype in rtusb_io.c
+//
+NTSTATUS RTUSBMultiRead(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       OUT     PUCHAR                  pData,
+       IN      USHORT                  length);
+
+NTSTATUS RTUSBMultiWrite(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       IN      PUCHAR                  pData,
+       IN      USHORT                  length);
+
+NTSTATUS RTUSBMultiWrite_OneByte(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       IN      PUCHAR                  pData);
+
+NTSTATUS RTUSBReadBBPRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Id,
+       IN      PUCHAR                  pValue);
+
+NTSTATUS RTUSBWriteBBPRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Id,
+       IN      UCHAR                   Value);
+
+NTSTATUS RTUSBWriteRFRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UINT32                  Value);
+
+NTSTATUS       RT30xxWriteRFRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   RegID,
+       IN      UCHAR                   Value);
+
+NTSTATUS       RT30xxReadRFRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   RegID,
+       IN      PUCHAR                  pValue);
+
+NTSTATUS RTUSB_VendorRequest(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UINT32                  TransferFlags,
+       IN      UCHAR                   ReservedBits,
+       IN      UCHAR                   Request,
+       IN      USHORT                  Value,
+       IN      USHORT                  Index,
+       IN      PVOID                   TransferBuffer,
+       IN      UINT32                  TransferBufferLength);
+
+NTSTATUS RTUSBReadEEPROM(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       OUT     PUCHAR                  pData,
+       IN      USHORT                  length);
+
+NTSTATUS RTUSBWriteEEPROM(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       IN      PUCHAR                  pData,
+       IN      USHORT                  length);
+
+VOID RTUSBPutToSleep(
+       IN      PRTMP_ADAPTER   pAd);
+
+NTSTATUS RTUSBWakeUp(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID RTUSBInitializeCmdQ(
+       IN      PCmdQ   cmdq);
+
+NDIS_STATUS    RTUSBEnqueueCmdFromNdis(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      NDIS_OID                Oid,
+       IN      BOOLEAN                 SetInformation,
+       IN      PVOID                   pInformationBuffer,
+       IN      UINT32                  InformationBufferLength);
+
+NDIS_STATUS RTUSBEnqueueInternalCmd(
+       IN      PRTMP_ADAPTER   pAd,
+       IN NDIS_OID                     Oid,
+       IN PVOID                        pInformationBuffer,
+       IN UINT32                       InformationBufferLength);
+
+VOID RTUSBDequeueCmd(
+       IN      PCmdQ           cmdq,
+       OUT     PCmdQElmt       *pcmdqelmt);
+
+INT RTUSBCmdThread(
+       IN OUT PVOID Context);
+
+INT TimerQThread(
+       IN OUT PVOID Context);
+
+RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert(
+       IN RTMP_ADAPTER *pAd,
+       IN RALINK_TIMER_STRUCT *pTimer);
+
+BOOLEAN RT2870_TimerQ_Remove(
+       IN RTMP_ADAPTER *pAd,
+       IN RALINK_TIMER_STRUCT *pTimer);
+
+void RT2870_TimerQ_Exit(
+       IN RTMP_ADAPTER *pAd);
+
+void RT2870_TimerQ_Init(
+       IN RTMP_ADAPTER *pAd);
+
+VOID RT2870_BssBeaconExit(
+       IN RTMP_ADAPTER *pAd);
+
+VOID RT2870_BssBeaconStop(
+       IN RTMP_ADAPTER *pAd);
+
+VOID RT2870_BssBeaconStart(
+       IN RTMP_ADAPTER * pAd);
+
+VOID RT2870_BssBeaconInit(
+       IN RTMP_ADAPTER *pAd);
+
+VOID RT2870_WatchDog(
+       IN RTMP_ADAPTER *pAd);
+
+NTSTATUS RTUSBWriteMACRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       IN      UINT32                  Value);
+
+NTSTATUS RTUSBReadMACRegister(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      USHORT                  Offset,
+       OUT     PUINT32                 pValue);
+
+NTSTATUS RTUSBSingleWrite(
+       IN      RTMP_ADAPTER    *pAd,
+       IN      USHORT                  Offset,
+       IN      USHORT                  Value);
+
+NTSTATUS RTUSBFirmwareRun(
+       IN      PRTMP_ADAPTER   pAd);
+
+NTSTATUS RTUSBFirmwareWrite(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR               pFwImage,
+       IN ULONG                FwLen);
+
+NTSTATUS       RTUSBFirmwareOpmode(
+       IN      PRTMP_ADAPTER   pAd,
+       OUT     PUINT32                 pValue);
+
+NTSTATUS       RTUSBVenderReset(
+       IN      PRTMP_ADAPTER   pAd);
+
+NDIS_STATUS RTUSBSetHardWareRegister(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PVOID                   pBuf);
+
+NDIS_STATUS RTUSBQueryHardWareRegister(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PVOID                   pBuf);
+
+VOID CMDHandler(
+    IN PRTMP_ADAPTER pAd);
+
+
+NDIS_STATUS     CreateThreads(
+       IN      struct net_device *net_dev );
+
+
+VOID MacTableInitialize(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID MlmeSetPsm(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT psm);
+
+NDIS_STATUS RTMPWPAAddKeyProc(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PVOID           pBuf);
+
+VOID AsicRxAntEvalAction(
+       IN PRTMP_ADAPTER pAd);
+
+#if 0 // Mark because not used in RT28xx.
+NTSTATUS RTUSBRxPacket(
+       IN      PRTMP_ADAPTER  pAd,
+       IN    BOOLEAN          bBulkReceive);
+
+VOID RTUSBDequeueMLMEPacket(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID RTUSBCleanUpMLMEWaitQueue(
+       IN      PRTMP_ADAPTER   pAd);
+#endif
+
+void append_pkt(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pHeader802_3,
+    IN  UINT            HdrLen,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize,
+       OUT  PNDIS_PACKET       *ppPacket);
+
+UINT deaggregate_AMSDU_announce(
+       IN      PRTMP_ADAPTER   pAd,
+       PNDIS_PACKET            pPacket,
+       IN      PUCHAR                  pData,
+       IN      ULONG                   DataSize);
+
+NDIS_STATUS    RTMPCheckRxError(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PHEADER_802_11  pHeader,
+       IN      PRXWI_STRUC     pRxWI,
+       IN      PRT28XX_RXD_STRUC       pRxINFO);
+
+
+VOID RTUSBMlmeHardTransmit(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PMGMT_STRUC             pMgmt);
+
+INT MlmeThread(
+       IN PVOID Context);
+
+#if 0
+VOID    RTUSBResumeMsduTransmission(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID    RTUSBSuspendMsduTransmission(
+       IN      PRTMP_ADAPTER   pAd);
+#endif
+
+//
+// Function Prototype in rtusb_data.c
+//
+NDIS_STATUS    RTUSBFreeDescriptorRequest(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   BulkOutPipeId,
+       IN      UINT32                  NumberRequired);
+
+
+BOOLEAN        RTUSBNeedQueueBackForAgg(
+       IN RTMP_ADAPTER *pAd,
+       IN UCHAR                BulkOutPipeId);
+
+
+VOID RTMPWriteTxInfo(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PTXINFO_STRUC   pTxInfo,
+       IN        USHORT                USBDMApktLen,
+       IN        BOOLEAN               bWiv,
+       IN        UCHAR                 QueueSel,
+       IN        UCHAR                 NextValid,
+       IN        UCHAR                 TxBurst);
+
+//
+// Function Prototype in cmm_data_2870.c
+//
+USHORT RtmpUSB_WriteSubTxResource(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      BOOLEAN                 bIsLast,
+       OUT     USHORT                  *FreeNumber);
+
+USHORT RtmpUSB_WriteSingleTxResource(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      BOOLEAN                 bIsLast,
+       OUT     USHORT                  *FreeNumber);
+
+USHORT RtmpUSB_WriteFragTxResource(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      UCHAR                   fragNum,
+       OUT     USHORT                  *FreeNumber);
+
+USHORT RtmpUSB_WriteMultiTxResource(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      UCHAR                   frameNum,
+       OUT     USHORT                  *FreeNumber);
+
+VOID RtmpUSB_FinalWriteTxResource(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      USHORT                  totalMPDUSize,
+       IN      USHORT                  TxIdx);
+
+VOID RtmpUSBDataLastTxIdx(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   QueIdx,
+       IN      USHORT                  TxIdx);
+
+VOID RtmpUSBDataKickOut(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk,
+       IN      UCHAR                   QueIdx);
+
+
+int RtmpUSBMgmtKickOut(
+       IN RTMP_ADAPTER         *pAd,
+       IN UCHAR                        QueIdx,
+       IN PNDIS_PACKET         pPacket,
+       IN PUCHAR                       pSrcBufVA,
+       IN UINT                         SrcBufLen);
+
+VOID RtmpUSBNullFrameKickOut(
+       IN RTMP_ADAPTER *pAd,
+       IN UCHAR                QueIdx,
+       IN UCHAR                *pNullFrame,
+       IN UINT32               frameLen);
+
+VOID RT28xxUsbStaAsicForceWakeup(
+       IN PRTMP_ADAPTER pAd,
+       IN BOOLEAN       bFromTx);
+
+VOID RT28xxUsbStaAsicSleepThenAutoWakeup(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT TbttNumToNextWakeUp);
+
+VOID RT28xxUsbMlmeRadioOn(
+       IN PRTMP_ADAPTER pAd);
+
+VOID RT28xxUsbMlmeRadioOFF(
+       IN PRTMP_ADAPTER pAd);
+#endif // RT2870 //
+
+////////////////////////////////////////
+
+VOID QBSS_LoadInit(
+       IN              RTMP_ADAPTER    *pAd);
+
+UINT32 QBSS_LoadElementAppend(
+       IN              RTMP_ADAPTER    *pAd,
+       OUT             UINT8                   *buf_p);
+
+VOID QBSS_LoadUpdate(
+       IN              RTMP_ADAPTER    *pAd);
+
+///////////////////////////////////////
+INT RTMPShowCfgValue(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pName,
+       IN      PUCHAR                  pBuf);
+
+PCHAR   RTMPGetRalinkAuthModeStr(
+    IN  NDIS_802_11_AUTHENTICATION_MODE authMode);
+
+PCHAR   RTMPGetRalinkEncryModeStr(
+    IN  USHORT encryMode);
+//////////////////////////////////////
+
+#ifdef CONFIG_STA_SUPPORT
+VOID AsicStaBbpTuning(
+       IN PRTMP_ADAPTER pAd);
+
+BOOLEAN StaAddMacTableEntry(
+       IN  PRTMP_ADAPTER               pAd,
+       IN  PMAC_TABLE_ENTRY    pEntry,
+       IN  UCHAR                               MaxSupportedRateIn500Kbps,
+       IN  HT_CAPABILITY_IE    *pHtCapability,
+       IN  UCHAR                               HtCapabilityLen,
+       IN  USHORT                      CapabilityInfo);
+#endif // CONFIG_STA_SUPPORT //
+
+void RTMP_IndicateMediaState(
+       IN      PRTMP_ADAPTER   pAd);
+
+VOID ReSyncBeaconTime(
+       IN  PRTMP_ADAPTER   pAd);
+
+VOID RTMPSetAGCInitValue(
+       IN PRTMP_ADAPTER        pAd,
+       IN UCHAR                        BandWidth);
+
+int rt28xx_close(IN PNET_DEV dev);
+int rt28xx_open(IN PNET_DEV dev);
+
+__inline INT VIRTUAL_IF_UP(PRTMP_ADAPTER pAd)
+{
+extern VOID MeshMakeBeacon(IN PRTMP_ADAPTER pAd, IN UCHAR idx);
+extern VOID MeshUpdateBeaconFrame(IN PRTMP_ADAPTER pAd, IN UCHAR idx);
+
+       if (VIRTUAL_IF_NUM(pAd) == 0)
+       {
+               if (rt28xx_open(pAd->net_dev) != 0)
+                       return -1;
+       }
+       else
+       {
+       }
+       VIRTUAL_IF_INC(pAd);
+       return 0;
+}
+
+__inline VOID VIRTUAL_IF_DOWN(PRTMP_ADAPTER pAd)
+{
+       VIRTUAL_IF_DEC(pAd);
+       if (VIRTUAL_IF_NUM(pAd) == 0)
+               rt28xx_close(pAd->net_dev);
+       return;
+}
+
+
+#endif  // __RTMP_H__
+
diff --git a/drivers/staging/rt2870/rtmp_ckipmic.h b/drivers/staging/rt2870/rtmp_ckipmic.h
new file mode 100644 (file)
index 0000000..a3d949a
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       rtmp_ckipmic.h
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Name            Date                    Modification logs
+*/
+#ifndef        __RTMP_CKIPMIC_H__
+#define        __RTMP_CKIPMIC_H__
+
+typedef        struct  _MIC_CONTEXT    {
+       /* --- MMH context                            */
+       UCHAR           CK[16];                         /* the key                                    */
+       UCHAR           coefficient[16];        /* current aes counter mode coefficients      */
+       ULONGLONG       accum;                          /* accumulated mic, reduced to u32 in final() */
+       UINT            position;                       /* current position (byte offset) in message  */
+       UCHAR           part[4];                        /* for conversion of message to u32 for mmh   */
+}      MIC_CONTEXT, *PMIC_CONTEXT;
+
+VOID   CKIP_key_permute(
+       OUT     UCHAR   *PK,                    /* output permuted key */
+       IN      UCHAR   *CK,                    /* input CKIP key */
+       IN      UCHAR   toDsFromDs,             /* input toDs/FromDs bits */
+       IN      UCHAR   *piv);                  /* input pointer to IV */
+
+VOID   RTMPCkipMicInit(
+       IN      PMIC_CONTEXT            pContext,
+       IN      PUCHAR                          CK);
+
+VOID RTMPMicUpdate(
+    IN  PMIC_CONTEXT        pContext,
+    IN  PUCHAR              pOctets,
+    IN  INT                 len);
+
+ULONG RTMPMicGetCoefficient(
+    IN  PMIC_CONTEXT         pContext);
+
+VOID xor_128(
+    IN  PUCHAR              a,
+    IN  PUCHAR              b,
+    OUT PUCHAR              out);
+
+UCHAR RTMPCkipSbox(
+    IN  UCHAR               a);
+
+VOID xor_32(
+    IN  PUCHAR              a,
+    IN  PUCHAR              b,
+    OUT PUCHAR              out);
+
+VOID next_key(
+    IN  PUCHAR              key,
+    IN  INT                 round);
+
+VOID byte_sub(
+    IN  PUCHAR              in,
+    OUT PUCHAR              out);
+
+VOID shift_row(
+    IN  PUCHAR              in,
+    OUT PUCHAR              out);
+
+VOID mix_column(
+    IN  PUCHAR              in,
+    OUT PUCHAR              out);
+
+VOID RTMPAesEncrypt(
+    IN  PUCHAR              key,
+    IN  PUCHAR              data,
+    IN  PUCHAR              ciphertext);
+
+VOID RTMPMicFinal(
+    IN  PMIC_CONTEXT        pContext,
+    OUT UCHAR               digest[4]);
+
+VOID RTMPCkipInsertCMIC(
+    IN  PRTMP_ADAPTER   pAd,
+    OUT PUCHAR          pMIC,
+    IN  PUCHAR          p80211hdr,
+    IN  PNDIS_PACKET    pPacket,
+    IN  PCIPHER_KEY     pKey,
+    IN  PUCHAR          mic_snap);
+
+#endif //__RTMP_CKIPMIC_H__
diff --git a/drivers/staging/rt2870/rtmp_def.h b/drivers/staging/rt2870/rtmp_def.h
new file mode 100644 (file)
index 0000000..9b86325
--- /dev/null
@@ -0,0 +1,1622 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    rtmp_def.h
+
+    Abstract:
+    Miniport related definition header
+
+    Revision History:
+    Who         When          What
+    --------    ----------    ----------------------------------------------
+    Paul Lin    08-01-2002    created
+    John Chang  08-05-2003    add definition for 11g & other drafts
+*/
+#ifndef __RTMP_DEF_H__
+#define __RTMP_DEF_H__
+
+#include "oid.h"
+
+//
+//  Debug information verbosity: lower values indicate higher urgency
+//
+#define RT_DEBUG_OFF        0
+#define RT_DEBUG_ERROR      1
+#define RT_DEBUG_WARN       2
+#define RT_DEBUG_TRACE      3
+#define RT_DEBUG_INFO       4
+#define RT_DEBUG_LOUD       5
+
+#define NIC_TAG             ((ULONG)'0682')
+#define NIC_DBG_STRING      ("**RT28xx**")
+
+#ifdef SNMP_SUPPORT
+// for snmp
+// to get manufacturer OUI, kathy, 2008_0220
+#define ManufacturerOUI_LEN                    3
+#define ManufacturerNAME                       ("Ralink Technology Company.")
+#define        ResourceTypeIdName                      ("Ralink_ID")
+#endif
+
+
+//#define PACKED
+
+#define RALINK_2883_VERSION            ((UINT32)0x28830300)
+#define RALINK_2880E_VERSION   ((UINT32)0x28720200)
+#define RALINK_3070_VERSION            ((UINT32)0x30700200)
+
+//
+// NDIS version in use by the NIC driver.
+// The high byte is the major version. The low byte is the minor version.
+//
+#ifdef  NDIS51_MINIPORT
+#define NIC_DRIVER_VERSION      0x0501
+#else
+#define NIC_DRIVER_VERSION      0x0500
+#endif
+
+//
+// NDIS media type, current is ethernet, change if native wireless supported
+//
+#define NIC_MEDIA_TYPE          NdisMedium802_3
+#define NIC_PCI_HDR_LENGTH      0xe2
+#define NIC_MAX_PACKET_SIZE     2304
+#define NIC_HEADER_SIZE         14
+#define MAX_MAP_REGISTERS_NEEDED 32
+#define MIN_MAP_REGISTERS_NEEDED 2   //Todo: should consider fragment issue.
+
+//
+// interface type, we use PCI
+//
+#define NIC_INTERFACE_TYPE      NdisInterfacePci
+#define NIC_INTERRUPT_MODE      NdisInterruptLevelSensitive
+
+//
+// buffer size passed in NdisMQueryAdapterResources
+// We should only need three adapter resources (IO, interrupt and memory),
+// Some devices get extra resources, so have room for 10 resources
+//                    UF_SIZE   (sizeof(NDIS_RESOURCE_LIST) + (10*sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)))
+
+
+#define NIC_RESOURCE_B//
+// IO space length
+//
+#define NIC_MAP_IOSPACE_LENGTH  sizeof(CSR_STRUC)
+
+#define MAX_RX_PKT_LEN 1520
+
+//
+// Entry number for each DMA descriptor ring
+//
+
+
+#ifdef RT2870
+#define TX_RING_SIZE            8 // 1
+#define PRIO_RING_SIZE          8
+#define MGMT_RING_SIZE       32 // PRIO_RING_SIZE
+#define RX_RING_SIZE            8
+#define MAX_TX_PROCESS          4
+#define LOCAL_TXBUF_SIZE        2048
+#endif // RT2870 //
+
+#ifdef MULTIPLE_CARD_SUPPORT
+// MC: Multple Cards
+#define MAX_NUM_OF_MULTIPLE_CARD               32
+#endif // MULTIPLE_CARD_SUPPORT //
+
+#define MAX_RX_PROCESS          128 //64 //32
+#define NUM_OF_LOCAL_TXBUF      2
+#define TXD_SIZE                16
+#define TXWI_SIZE               16
+#define RXD_SIZE                       16
+#define RXWI_SIZE              16
+// TXINFO_SIZE + TXWI_SIZE + 802.11 Header Size + AMSDU sub frame header
+#define TX_DMA_1ST_BUFFER_SIZE  96    // only the 1st physical buffer is pre-allocated
+#define MGMT_DMA_BUFFER_SIZE    1536 //2048
+#define RX_BUFFER_AGGRESIZE     3840 //3904 //3968 //4096 //2048 //4096
+#define RX_BUFFER_NORMSIZE      3840 //3904 //3968 //4096 //2048 //4096
+#define TX_BUFFER_NORMSIZE             RX_BUFFER_NORMSIZE
+#define MAX_FRAME_SIZE          2346                    // Maximum 802.11 frame size
+#define MAX_AGGREGATION_SIZE    3840 //3904 //3968 //4096
+#define MAX_NUM_OF_TUPLE_CACHE  2
+#define MAX_MCAST_LIST_SIZE     32
+#define MAX_LEN_OF_VENDOR_DESC  64
+//#define MAX_SIZE_OF_MCAST_PSQ   (NUM_OF_LOCAL_TXBUF >> 2) // AP won't spend more than 1/4 of total buffers on M/BCAST PSQ
+#define MAX_SIZE_OF_MCAST_PSQ               32
+
+#define MAX_RX_PROCESS_CNT     (RX_RING_SIZE)
+
+
+#define MAX_PACKETS_IN_QUEUE                           (512) //(512)    // to pass WMM A5-WPAPSK
+#define MAX_PACKETS_IN_MCAST_PS_QUEUE          32
+#define MAX_PACKETS_IN_PS_QUEUE                                128     //32
+#define WMM_NUM_OF_AC                       4  /* AC0, AC1, AC2, and AC3 */
+
+
+
+// RxFilter
+#define STANORMAL       0x17f97
+#define APNORMAL        0x15f97
+//
+//  RTMP_ADAPTER flags
+//
+#define fRTMP_ADAPTER_MAP_REGISTER          0x00000001
+#define fRTMP_ADAPTER_INTERRUPT_IN_USE      0x00000002
+#define fRTMP_ADAPTER_HARDWARE_ERROR        0x00000004
+#define fRTMP_ADAPTER_SCATTER_GATHER        0x00000008
+#define fRTMP_ADAPTER_SEND_PACKET_ERROR     0x00000010
+#define fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS 0x00000020
+#define fRTMP_ADAPTER_HALT_IN_PROGRESS      0x00000040
+#define fRTMP_ADAPTER_RESET_IN_PROGRESS     0x00000080
+#define fRTMP_ADAPTER_NIC_NOT_EXIST         0x00000100
+#define fRTMP_ADAPTER_TX_RING_ALLOCATED     0x00000200
+#define fRTMP_ADAPTER_REMOVE_IN_PROGRESS    0x00000400
+#define fRTMP_ADAPTER_MIMORATE_INUSED       0x00000800
+#define fRTMP_ADAPTER_RX_RING_ALLOCATED     0x00001000
+#define fRTMP_ADAPTER_INTERRUPT_ACTIVE      0x00002000
+#define fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS  0x00004000
+#define        fRTMP_ADAPTER_REASSOC_IN_PROGRESS       0x00008000
+#define        fRTMP_ADAPTER_MEDIA_STATE_PENDING       0x00010000
+#define        fRTMP_ADAPTER_RADIO_OFF                         0x00020000
+#define fRTMP_ADAPTER_BULKOUT_RESET                    0x00040000
+#define        fRTMP_ADAPTER_BULKIN_RESET                      0x00080000
+#define fRTMP_ADAPTER_RDG_ACTIVE                       0x00100000
+#define fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE 0x00200000
+#define fRTMP_ADAPTER_SCAN_2040                        0x04000000
+#define        fRTMP_ADAPTER_RADIO_MEASUREMENT         0x08000000
+
+#define fRTMP_ADAPTER_START_UP                         0x10000000      //Devive already initialized and enabled Tx/Rx.
+#define fRTMP_ADAPTER_MEDIA_STATE_CHANGE    0x20000000
+#define fRTMP_ADAPTER_IDLE_RADIO_OFF        0x40000000
+
+// Lock bit for accessing different ring buffers
+//#define fRTMP_ADAPTER_TX_RING_BUSY        0x80000000
+//#define fRTMP_ADAPTER_MGMT_RING_BUSY      0x40000000
+//#define fRTMP_ADAPTER_ATIM_RING_BUSY      0x20000000
+//#define fRTMP_ADAPTER_RX_RING_BUSY        0x10000000
+
+// Lock bit for accessing different queue
+//#define   fRTMP_ADAPTER_TX_QUEUE_BUSY     0x08000000
+//#define   fRTMP_ADAPTER_MGMT_QUEUE_BUSY   0x04000000
+
+//
+//  STA operation status flags
+//
+#define fOP_STATUS_INFRA_ON                 0x00000001
+#define fOP_STATUS_ADHOC_ON                 0x00000002
+#define fOP_STATUS_BG_PROTECTION_INUSED     0x00000004
+#define fOP_STATUS_SHORT_SLOT_INUSED        0x00000008
+#define fOP_STATUS_SHORT_PREAMBLE_INUSED    0x00000010
+#define fOP_STATUS_RECEIVE_DTIM             0x00000020
+//#define fOP_STATUS_TX_RATE_SWITCH_ENABLED   0x00000040
+#define fOP_STATUS_MEDIA_STATE_CONNECTED    0x00000080
+#define fOP_STATUS_WMM_INUSED               0x00000100
+#define fOP_STATUS_AGGREGATION_INUSED       0x00000200
+#define fOP_STATUS_DOZE                     0x00000400  // debug purpose
+#define fOP_STATUS_PIGGYBACK_INUSED         0x00000800  // piggy-back, and aggregation
+#define fOP_STATUS_APSD_INUSED                         0x00001000
+#define fOP_STATUS_TX_AMSDU_INUSED                     0x00002000
+#define fOP_STATUS_MAX_RETRY_ENABLED           0x00004000
+#define fOP_STATUS_WAKEUP_NOW               0x00008000
+#define fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE       0x00020000
+
+#ifdef DOT11N_DRAFT3
+#define fOP_STATUS_SCAN_2040                       0x00040000
+#endif // DOT11N_DRAFT3 //
+
+#define CCKSETPROTECT          0x1
+#define OFDMSETPROTECT         0x2
+#define MM20SETPROTECT         0x4
+#define MM40SETPROTECT         0x8
+#define GF20SETPROTECT         0x10
+#define GR40SETPROTECT         0x20
+#define ALLN_SETPROTECT                (GR40SETPROTECT | GF20SETPROTECT | MM40SETPROTECT | MM20SETPROTECT)
+
+//
+//  AP's client table operation status flags
+//
+#define fCLIENT_STATUS_WMM_CAPABLE          0x00000001  // CLIENT can parse QOS DATA frame
+#define fCLIENT_STATUS_AGGREGATION_CAPABLE  0x00000002  // CLIENT can receive Ralink's proprietary TX aggregation frame
+#define fCLIENT_STATUS_PIGGYBACK_CAPABLE    0x00000004  // CLIENT support piggy-back
+#define fCLIENT_STATUS_AMSDU_INUSED                    0x00000008
+#define fCLIENT_STATUS_SGI20_CAPABLE           0x00000010
+#define fCLIENT_STATUS_SGI40_CAPABLE           0x00000020
+#define fCLIENT_STATUS_TxSTBC_CAPABLE          0x00000040
+#define fCLIENT_STATUS_RxSTBC_CAPABLE          0x00000080
+#define fCLIENT_STATUS_HTC_CAPABLE                     0x00000100
+#define fCLIENT_STATUS_RDG_CAPABLE                     0x00000200
+#define fCLIENT_STATUS_MCSFEEDBACK_CAPABLE  0x00000400
+#define fCLIENT_STATUS_APSD_CAPABLE         0x00000800  /* UAPSD STATION */
+
+#ifdef DOT11N_DRAFT3
+#define fCLIENT_STATUS_BSSCOEXIST_CAPABLE      0x00001000
+#endif // DOT11N_DRAFT3 //
+
+#define fCLIENT_STATUS_RALINK_CHIPSET          0x00100000
+//
+//  STA configuration flags
+//
+//#define fSTA_CFG_ENABLE_TX_BURST          0x00000001
+
+// 802.11n Operating Mode Definition. 0-3 also used in ASICUPdateProtect switch case
+#define HT_NO_PROTECT  0
+#define HT_LEGACY_PROTECT      1
+#define HT_40_PROTECT  2
+#define HT_2040_PROTECT        3
+#define HT_RTSCTS_6M   7
+//following is our own definition in order to turn on our ASIC protection register in INFRASTRUCTURE.
+#define HT_ATHEROS     8       // rt2860c has problem with atheros chip. we need to turn on RTS/CTS .
+#define HT_FORCERTSCTS 9       // Force turn on RTS/CTS first. then go to evaluate if this force RTS is necessary.
+
+//
+// RX Packet Filter control flags. Apply on pAd->PacketFilter
+//
+#define fRX_FILTER_ACCEPT_DIRECT            NDIS_PACKET_TYPE_DIRECTED
+#define fRX_FILTER_ACCEPT_MULTICAST         NDIS_PACKET_TYPE_MULTICAST
+#define fRX_FILTER_ACCEPT_BROADCAST         NDIS_PACKET_TYPE_BROADCAST
+#define fRX_FILTER_ACCEPT_ALL_MULTICAST     NDIS_PACKET_TYPE_ALL_MULTICAST
+
+//
+// Error code section
+//
+// NDIS_ERROR_CODE_ADAPTER_NOT_FOUND
+#define ERRLOG_READ_PCI_SLOT_FAILED     0x00000101L
+#define ERRLOG_WRITE_PCI_SLOT_FAILED    0x00000102L
+#define ERRLOG_VENDOR_DEVICE_NOMATCH    0x00000103L
+
+// NDIS_ERROR_CODE_ADAPTER_DISABLED
+#define ERRLOG_BUS_MASTER_DISABLED      0x00000201L
+
+// NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION
+#define ERRLOG_INVALID_SPEED_DUPLEX     0x00000301L
+#define ERRLOG_SET_SECONDARY_FAILED     0x00000302L
+
+// NDIS_ERROR_CODE_OUT_OF_RESOURCES
+#define ERRLOG_OUT_OF_MEMORY            0x00000401L
+#define ERRLOG_OUT_OF_SHARED_MEMORY     0x00000402L
+#define ERRLOG_OUT_OF_MAP_REGISTERS     0x00000403L
+#define ERRLOG_OUT_OF_BUFFER_POOL       0x00000404L
+#define ERRLOG_OUT_OF_NDIS_BUFFER       0x00000405L
+#define ERRLOG_OUT_OF_PACKET_POOL       0x00000406L
+#define ERRLOG_OUT_OF_NDIS_PACKET       0x00000407L
+#define ERRLOG_OUT_OF_LOOKASIDE_MEMORY  0x00000408L
+
+// NDIS_ERROR_CODE_HARDWARE_FAILURE
+#define ERRLOG_SELFTEST_FAILED          0x00000501L
+#define ERRLOG_INITIALIZE_ADAPTER       0x00000502L
+#define ERRLOG_REMOVE_MINIPORT          0x00000503L
+
+// NDIS_ERROR_CODE_RESOURCE_CONFLICT
+#define ERRLOG_MAP_IO_SPACE             0x00000601L
+#define ERRLOG_QUERY_ADAPTER_RESOURCES  0x00000602L
+#define ERRLOG_NO_IO_RESOURCE           0x00000603L
+#define ERRLOG_NO_INTERRUPT_RESOURCE    0x00000604L
+#define ERRLOG_NO_MEMORY_RESOURCE       0x00000605L
+
+
+// WDS definition
+#define        MAX_WDS_ENTRY               4
+#define WDS_PAIRWISE_KEY_OFFSET     60    // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table
+
+#define        WDS_DISABLE_MODE            0
+#define        WDS_RESTRICT_MODE           1
+#define        WDS_BRIDGE_MODE             2
+#define        WDS_REPEATER_MODE           3
+#define        WDS_LAZY_MODE               4
+
+
+#define MAX_MESH_NUM                           0
+
+#define MAX_APCLI_NUM                          0
+#ifdef APCLI_SUPPORT
+#undef MAX_APCLI_NUM
+#define MAX_APCLI_NUM                          1
+#endif // APCLI_SUPPORT //
+
+#define MAX_MBSSID_NUM                         1
+
+/* sanity check for apidx */
+#define MBSS_MR_APIDX_SANITY_CHECK(apidx) \
+    { if (apidx > MAX_MBSSID_NUM) { \
+          printk("%s> Error! apidx = %d > MAX_MBSSID_NUM!\n", __FUNCTION__, apidx); \
+         apidx = MAIN_MBSSID; } }
+
+#define VALID_WCID(_wcid)      ((_wcid) > 0 && (_wcid) < MAX_LEN_OF_MAC_TABLE )
+
+#define MAIN_MBSSID                 0
+#define FIRST_MBSSID                1
+
+
+#define MAX_BEACON_SIZE                                512
+// If the MAX_MBSSID_NUM is larger than 6,
+// it shall reserve some WCID space(wcid 222~253) for beacon frames.
+// -   these wcid 238~253 are reserved for beacon#6(ra6).
+// -   these wcid 222~237 are reserved for beacon#7(ra7).
+#if defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 8)
+#define HW_RESERVED_WCID       222
+#elif defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 7)
+#define HW_RESERVED_WCID       238
+#else
+#define HW_RESERVED_WCID       255
+#endif
+
+// Then dedicate wcid of DFS and Carrier-Sense.
+#define DFS_CTS_WCID           (HW_RESERVED_WCID - 1)
+#define CS_CTS_WCID            (HW_RESERVED_WCID - 2)
+#define LAST_SPECIFIC_WCID     (HW_RESERVED_WCID - 2)
+
+// If MAX_MBSSID_NUM is 8, the maximum available wcid for the associated STA is 211.
+// If MAX_MBSSID_NUM is 7, the maximum available wcid for the associated STA is 228.
+#define MAX_AVAILABLE_CLIENT_WCID      (LAST_SPECIFIC_WCID - MAX_MBSSID_NUM - 1)
+
+// TX need WCID to find Cipher Key
+// these wcid 212 ~ 219 are reserved for bc/mc packets if MAX_MBSSID_NUM is 8.
+#define GET_GroupKey_WCID(__wcid, __bssidx) \
+       {                                                                               \
+               __wcid = LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM) + __bssidx;      \
+       }
+
+#define IsGroupKeyWCID(__wcid) (((__wcid) < LAST_SPECIFIC_WCID) && ((__wcid) >= (LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM))))
+
+
+// definition to support multiple BSSID
+#define BSS0                            0
+#define BSS1                            1
+#define BSS2                            2
+#define BSS3                            3
+#define BSS4                            4
+#define BSS5                            5
+#define BSS6                            6
+#define BSS7                            7
+
+
+//============================================================
+// Length definitions
+#define PEER_KEY_NO                     2
+#define MAC_ADDR_LEN                    6
+#define TIMESTAMP_LEN                   8
+#define MAX_LEN_OF_SUPPORTED_RATES      MAX_LENGTH_OF_SUPPORT_RATES // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
+#define MAX_LEN_OF_KEY                  32      // 32 octets == 256 bits, Redefine for WPA
+#define MAX_NUM_OF_CHANNELS             MAX_NUM_OF_CHS      // 14 channels @2.4G +  12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination
+#define MAX_NUM_OF_11JCHANNELS             20      // 14 channels @2.4G +  12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination
+#define MAX_LEN_OF_SSID                 32
+#define CIPHER_TEXT_LEN                 128
+#define HASH_TABLE_SIZE                 256
+#define MAX_VIE_LEN                     1024   // New for WPA cipher suite variable IE sizes.
+#define MAX_SUPPORT_MCS             32
+
+//============================================================
+// ASIC WCID Table definition.
+//============================================================
+#define BSSID_WCID             1       // in infra mode, always put bssid with this WCID
+#define MCAST_WCID     0x0
+#define BSS0Mcast_WCID 0x0
+#define BSS1Mcast_WCID 0xf8
+#define BSS2Mcast_WCID 0xf9
+#define BSS3Mcast_WCID 0xfa
+#define BSS4Mcast_WCID 0xfb
+#define BSS5Mcast_WCID 0xfc
+#define BSS6Mcast_WCID 0xfd
+#define BSS7Mcast_WCID 0xfe
+#define RESERVED_WCID          0xff
+
+#define MAX_NUM_OF_ACL_LIST                            MAX_NUMBER_OF_ACL
+
+#define MAX_LEN_OF_MAC_TABLE            MAX_NUMBER_OF_MAC // if MAX_MBSSID_NUM is 8, this value can't be larger than 211
+
+#if MAX_LEN_OF_MAC_TABLE>MAX_AVAILABLE_CLIENT_WCID
+#error MAX_LEN_OF_MAC_TABLE can not be larger than MAX_AVAILABLE_CLIENT_WCID!!!!
+#endif
+
+#define MAX_NUM_OF_WDS_LINK_PERBSSID               3
+#define MAX_NUM_OF_WDS_LINK                (MAX_NUM_OF_WDS_LINK_PERBSSID*MAX_MBSSID_NUM)
+#define MAX_NUM_OF_EVENT                MAX_NUMBER_OF_EVENT
+#define WDS_LINK_START_WCID                            (MAX_LEN_OF_MAC_TABLE-1)
+
+#define NUM_OF_TID                     8
+#define MAX_AID_BA                    4
+#define MAX_LEN_OF_BA_REC_TABLE          ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)//   (NUM_OF_TID*MAX_AID_BA + 32)       //Block ACK recipient
+#define MAX_LEN_OF_BA_ORI_TABLE          ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)//   (NUM_OF_TID*MAX_AID_BA + 32)   // Block ACK originator
+#define MAX_LEN_OF_BSS_TABLE             64
+#define MAX_REORDERING_MPDU_NUM                         512
+
+// key related definitions
+#define SHARE_KEY_NUM                   4
+#define MAX_LEN_OF_SHARE_KEY            16    // byte count
+#define MAX_LEN_OF_PEER_KEY             16    // byte count
+#define PAIRWISE_KEY_NUM                64    // in MAC ASIC pairwise key table
+#define GROUP_KEY_NUM                   4
+#define PMK_LEN                         32
+#define WDS_PAIRWISE_KEY_OFFSET         60    // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table
+#define        PMKID_NO                        4     // Number of PMKID saved supported
+#define MAX_LEN_OF_MLME_BUFFER          2048
+
+// power status related definitions
+#define PWR_ACTIVE                      0
+#define PWR_SAVE                        1
+#define PWR_MMPS                        2                      //MIMO power save
+//#define PWR_UNKNOWN                   2
+
+// Auth and Assoc mode related definitions
+#define AUTH_MODE_OPEN                  0x00
+#define AUTH_MODE_KEY                   0x01
+//#define AUTH_MODE_AUTO_SWITCH         0x03
+//#define AUTH_MODE_DEAUTH              0x04
+//#define AUTH_MODE_UPLAYER             0x05 // reserved for 802.11i use
+
+// BSS Type definitions
+#define BSS_ADHOC                       0  // = Ndis802_11IBSS
+#define BSS_INFRA                       1  // = Ndis802_11Infrastructure
+#define BSS_ANY                         2  // = Ndis802_11AutoUnknown
+#define BSS_MONITOR                                3  // = Ndis802_11Monitor
+
+
+// Reason code definitions
+#define REASON_RESERVED                 0
+#define REASON_UNSPECIFY                1
+#define REASON_NO_LONGER_VALID          2
+#define REASON_DEAUTH_STA_LEAVING       3
+#define REASON_DISASSOC_INACTIVE        4
+#define REASON_DISASSPC_AP_UNABLE       5
+#define REASON_CLS2ERR                  6
+#define REASON_CLS3ERR                  7
+#define REASON_DISASSOC_STA_LEAVING     8
+#define REASON_STA_REQ_ASSOC_NOT_AUTH   9
+#define REASON_INVALID_IE               13
+#define REASON_MIC_FAILURE              14
+#define REASON_4_WAY_TIMEOUT            15
+#define REASON_GROUP_KEY_HS_TIMEOUT     16
+#define REASON_IE_DIFFERENT             17
+#define REASON_MCIPHER_NOT_VALID        18
+#define REASON_UCIPHER_NOT_VALID        19
+#define REASON_AKMP_NOT_VALID           20
+#define REASON_UNSUPPORT_RSNE_VER       21
+#define REASON_INVALID_RSNE_CAP         22
+#define REASON_8021X_AUTH_FAIL          23
+#define REASON_CIPHER_SUITE_REJECTED    24
+#define REASON_DECLINED                 37
+
+#define REASON_QOS_UNSPECIFY              32
+#define REASON_QOS_LACK_BANDWIDTH         33
+#define REASON_POOR_CHANNEL_CONDITION     34
+#define REASON_QOS_OUTSIDE_TXOP_LIMITION  35
+#define REASON_QOS_QSTA_LEAVING_QBSS      36
+#define REASON_QOS_UNWANTED_MECHANISM     37
+#define REASON_QOS_MECH_SETUP_REQUIRED    38
+#define REASON_QOS_REQUEST_TIMEOUT        39
+#define REASON_QOS_CIPHER_NOT_SUPPORT     45
+
+// Status code definitions
+#define MLME_SUCCESS                    0
+#define MLME_UNSPECIFY_FAIL             1
+#define MLME_CANNOT_SUPPORT_CAP         10
+#define MLME_REASSOC_DENY_ASSOC_EXIST   11
+#define MLME_ASSOC_DENY_OUT_SCOPE       12
+#define MLME_ALG_NOT_SUPPORT            13
+#define MLME_SEQ_NR_OUT_OF_SEQUENCE     14
+#define MLME_REJ_CHALLENGE_FAILURE      15
+#define MLME_REJ_TIMEOUT                  16
+#define MLME_ASSOC_REJ_UNABLE_HANDLE_STA  17
+#define MLME_ASSOC_REJ_DATA_RATE          18
+
+#define MLME_ASSOC_REJ_NO_EXT_RATE        22
+#define MLME_ASSOC_REJ_NO_EXT_RATE_PBCC   23
+#define MLME_ASSOC_REJ_NO_CCK_OFDM        24
+
+#define MLME_QOS_UNSPECIFY                32
+#define MLME_REQUEST_DECLINED             37
+#define MLME_REQUEST_WITH_INVALID_PARAM   38
+#define MLME_DLS_NOT_ALLOW_IN_QBSS        48
+#define MLME_DEST_STA_NOT_IN_QBSS         49
+#define MLME_DEST_STA_IS_NOT_A_QSTA       50
+
+#define MLME_INVALID_FORMAT             0x51
+#define MLME_FAIL_NO_RESOURCE           0x52
+#define MLME_STATE_MACHINE_REJECT       0x53
+#define MLME_MAC_TABLE_FAIL             0x54
+
+// IE code
+#define IE_SSID                         0
+#define IE_SUPP_RATES                   1
+#define IE_FH_PARM                      2
+#define IE_DS_PARM                      3
+#define IE_CF_PARM                      4
+#define IE_TIM                          5
+#define IE_IBSS_PARM                    6
+#define IE_COUNTRY                      7     // 802.11d
+#define IE_802_11D_REQUEST              10    // 802.11d
+#define IE_QBSS_LOAD                    11    // 802.11e d9
+#define IE_EDCA_PARAMETER               12    // 802.11e d9
+#define IE_TSPEC                        13    // 802.11e d9
+#define IE_TCLAS                        14    // 802.11e d9
+#define IE_SCHEDULE                     15    // 802.11e d9
+#define IE_CHALLENGE_TEXT               16
+#define IE_POWER_CONSTRAINT             32    // 802.11h d3.3
+#define IE_POWER_CAPABILITY             33    // 802.11h d3.3
+#define IE_TPC_REQUEST                  34    // 802.11h d3.3
+#define IE_TPC_REPORT                   35    // 802.11h d3.3
+#define IE_SUPP_CHANNELS                36    // 802.11h d3.3
+#define IE_CHANNEL_SWITCH_ANNOUNCEMENT  37    // 802.11h d3.3
+#define IE_MEASUREMENT_REQUEST          38    // 802.11h d3.3
+#define IE_MEASUREMENT_REPORT           39    // 802.11h d3.3
+#define IE_QUIET                        40    // 802.11h d3.3
+#define IE_IBSS_DFS                     41    // 802.11h d3.3
+#define IE_ERP                          42    // 802.11g
+#define IE_TS_DELAY                     43    // 802.11e d9
+#define IE_TCLAS_PROCESSING             44    // 802.11e d9
+#define IE_QOS_CAPABILITY               46    // 802.11e d6
+#define IE_HT_CAP                       45    // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD
+#define IE_AP_CHANNEL_REPORT                   51    // 802.11k d6
+#define IE_HT_CAP2                         52    // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD
+#define IE_RSN                          48    // 802.11i d3.0
+#define IE_WPA2                         48    // WPA2
+#define IE_EXT_SUPP_RATES               50    // 802.11g
+#define IE_SUPP_REG_CLASS               59    // 802.11y. Supported regulatory classes.
+#define IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT     60      // 802.11n
+#define IE_ADD_HT                         61    // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD
+#define IE_ADD_HT2                        53    // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD
+
+
+// For 802.11n D3.03
+//#define IE_NEW_EXT_CHA_OFFSET             62    // 802.11n d1. New extension channel offset elemet
+#define IE_SECONDARY_CH_OFFSET         62      // 802.11n D3.03        Secondary Channel Offset element
+#define IE_WAPI                                                        68              // WAPI information element
+#define IE_2040_BSS_COEXIST               72    // 802.11n D3.0.3
+#define IE_2040_BSS_INTOLERANT_REPORT     73    // 802.11n D3.03
+#define IE_OVERLAPBSS_SCAN_PARM           74    // 802.11n D3.03
+#define IE_EXT_CAPABILITY                127   // 802.11n D3.03
+
+
+#define IE_WPA                          221   // WPA
+#define IE_VENDOR_SPECIFIC              221   // Wifi WMM (WME)
+
+#define OUI_BROADCOM_HT              51   //
+#define OUI_BROADCOM_HTADD              52   //
+#define OUI_PREN_HT_CAP              51   //
+#define OUI_PREN_ADD_HT              52   //
+
+// CCX information
+#define IE_AIRONET_CKIP                 133   // CCX1.0 ID 85H for CKIP
+#define IE_AP_TX_POWER                  150   // CCX 2.0 for AP transmit power
+#define IE_MEASUREMENT_CAPABILITY       221   // CCX 2.0
+#define IE_CCX_V2                       221
+#define IE_AIRONET_IPADDRESS            149   // CCX ID 95H for IP Address
+#define IE_AIRONET_CCKMREASSOC          156   // CCX ID 9CH for CCKM Reassociation Request element
+#define CKIP_NEGOTIATION_LENGTH         30
+#define AIRONET_IPADDRESS_LENGTH        10
+#define AIRONET_CCKMREASSOC_LENGTH      24
+
+// ========================================================
+// MLME state machine definition
+// ========================================================
+
+// STA MLME state mahcines
+#define ASSOC_STATE_MACHINE             1
+#define AUTH_STATE_MACHINE              2
+#define AUTH_RSP_STATE_MACHINE          3
+#define SYNC_STATE_MACHINE              4
+#define MLME_CNTL_STATE_MACHINE         5
+#define WPA_PSK_STATE_MACHINE           6
+#define LEAP_STATE_MACHINE              7
+#define AIRONET_STATE_MACHINE           8
+#define ACTION_STATE_MACHINE           9
+
+// AP MLME state machines
+#define AP_ASSOC_STATE_MACHINE          11
+#define AP_AUTH_STATE_MACHINE           12
+#define AP_AUTH_RSP_STATE_MACHINE       13
+#define AP_SYNC_STATE_MACHINE           14
+#define AP_CNTL_STATE_MACHINE           15
+#define AP_WPA_STATE_MACHINE            16
+
+#ifdef QOS_DLS_SUPPORT
+#define DLS_STATE_MACHINE               26
+#endif // QOS_DLS_SUPPORT //
+
+//
+// STA's CONTROL/CONNECT state machine: states, events, total function #
+//
+#define CNTL_IDLE                       0
+#define CNTL_WAIT_DISASSOC              1
+#define CNTL_WAIT_JOIN                  2
+#define CNTL_WAIT_REASSOC               3
+#define CNTL_WAIT_START                 4
+#define CNTL_WAIT_AUTH                  5
+#define CNTL_WAIT_ASSOC                 6
+#define CNTL_WAIT_AUTH2                 7
+#define CNTL_WAIT_OID_LIST_SCAN         8
+#define CNTL_WAIT_OID_DISASSOC          9
+#ifdef RT2870
+#define CNTL_WAIT_SCAN_FOR_CONNECT      10
+#endif // RT2870 //
+
+#define MT2_ASSOC_CONF                  34
+#define MT2_AUTH_CONF                   35
+#define MT2_DEAUTH_CONF                 36
+#define MT2_DISASSOC_CONF               37
+#define MT2_REASSOC_CONF                38
+#define MT2_PWR_MGMT_CONF               39
+#define MT2_JOIN_CONF                   40
+#define MT2_SCAN_CONF                   41
+#define MT2_START_CONF                  42
+#define MT2_GET_CONF                    43
+#define MT2_SET_CONF                    44
+#define MT2_RESET_CONF                  45
+#define MT2_MLME_ROAMING_REQ            52
+
+#define CNTL_FUNC_SIZE                  1
+
+//
+// STA's ASSOC state machine: states, events, total function #
+//
+#define ASSOC_IDLE                      0
+#define ASSOC_WAIT_RSP                  1
+#define REASSOC_WAIT_RSP                2
+#define DISASSOC_WAIT_RSP               3
+#define MAX_ASSOC_STATE                 4
+
+#define ASSOC_MACHINE_BASE              0
+#define MT2_MLME_ASSOC_REQ              0
+#define MT2_MLME_REASSOC_REQ            1
+#define MT2_MLME_DISASSOC_REQ           2
+#define MT2_PEER_DISASSOC_REQ           3
+#define MT2_PEER_ASSOC_REQ              4
+#define MT2_PEER_ASSOC_RSP              5
+#define MT2_PEER_REASSOC_REQ            6
+#define MT2_PEER_REASSOC_RSP            7
+#define MT2_DISASSOC_TIMEOUT            8
+#define MT2_ASSOC_TIMEOUT               9
+#define MT2_REASSOC_TIMEOUT             10
+#define MAX_ASSOC_MSG                   11
+
+#define ASSOC_FUNC_SIZE                 (MAX_ASSOC_STATE * MAX_ASSOC_MSG)
+
+//
+// ACT state machine: states, events, total function #
+//
+#define ACT_IDLE                      0
+#define MAX_ACT_STATE                 1
+
+#define ACT_MACHINE_BASE              0
+
+//Those PEER_xx_CATE number is based on real Categary value in IEEE spec. Please don'es modify it by your self.
+//Category
+#define MT2_PEER_SPECTRUM_CATE              0
+#define MT2_PEER_QOS_CATE              1
+#define MT2_PEER_DLS_CATE             2
+#define MT2_PEER_BA_CATE             3
+#define MT2_PEER_PUBLIC_CATE             4
+#define MT2_PEER_RM_CATE             5
+#define MT2_PEER_HT_CATE             7 //      7.4.7
+#define MAX_PEER_CATE_MSG                   7
+#define MT2_MLME_ADD_BA_CATE             8
+#define MT2_MLME_ORI_DELBA_CATE             9
+#define MT2_MLME_REC_DELBA_CATE             10
+#define MT2_MLME_QOS_CATE              11
+#define MT2_MLME_DLS_CATE             12
+#define MT2_ACT_INVALID             13
+#define MAX_ACT_MSG                   14
+
+//Category field
+#define CATEGORY_SPECTRUM              0
+#define CATEGORY_QOS                   1
+#define CATEGORY_DLS                   2
+#define CATEGORY_BA                    3
+#define CATEGORY_PUBLIC                4
+#define CATEGORY_RM                    5
+#define CATEGORY_HT                    7
+
+
+// DLS Action frame definition
+#define ACTION_DLS_REQUEST                     0
+#define ACTION_DLS_RESPONSE                    1
+#define ACTION_DLS_TEARDOWN                    2
+
+//Spectrum  Action field value 802.11h 7.4.1
+#define SPEC_MRQ       0       // Request
+#define SPEC_MRP       1       //Report
+#define SPEC_TPCRQ     2
+#define SPEC_TPCRP     3
+#define SPEC_CHANNEL_SWITCH    4
+
+
+//BA  Action field value
+#define ADDBA_REQ      0
+#define ADDBA_RESP     1
+#define DELBA   2
+
+//Public's  Action field value in Public Category.  Some in 802.11y and some in 11n
+#define ACTION_BSS_2040_COEXIST                                0       // 11n
+#define ACTION_DSE_ENABLEMENT                                  1       // 11y D9.0
+#define ACTION_DSE_DEENABLEMENT                                2       // 11y D9.0
+#define ACTION_DSE_REG_LOCATION_ANNOUNCE       3       // 11y D9.0
+#define ACTION_EXT_CH_SWITCH_ANNOUNCE          4       // 11y D9.0
+#define ACTION_DSE_MEASUREMENT_REQ                     5       // 11y D9.0
+#define ACTION_DSE_MEASUREMENT_REPORT          6       // 11y D9.0
+#define ACTION_MEASUREMENT_PILOT_ACTION                7       // 11y D9.0
+#define ACTION_DSE_POWER_CONSTRAINT                    8       // 11y D9.0
+
+
+//HT  Action field value
+#define NOTIFY_BW_ACTION                               0
+#define SMPS_ACTION                                            1
+#define PSMP_ACTION                                    2
+#define SETPCO_ACTION                                  3
+#define MIMO_CHA_MEASURE_ACTION                        4
+#define MIMO_N_BEACONFORM                              5
+#define MIMO_BEACONFORM                                        6
+#define ANTENNA_SELECT                                 7
+#define HT_INFO_EXCHANGE                               8
+
+#define ACT_FUNC_SIZE                 (MAX_ACT_STATE * MAX_ACT_MSG)
+//
+// STA's AUTHENTICATION state machine: states, evvents, total function #
+//
+#define AUTH_REQ_IDLE                   0
+#define AUTH_WAIT_SEQ2                  1
+#define AUTH_WAIT_SEQ4                  2
+#define MAX_AUTH_STATE                  3
+
+#define AUTH_MACHINE_BASE               0
+#define MT2_MLME_AUTH_REQ               0
+#define MT2_PEER_AUTH_EVEN              1
+#define MT2_AUTH_TIMEOUT                2
+#define MAX_AUTH_MSG                    3
+
+#define AUTH_FUNC_SIZE                  (MAX_AUTH_STATE * MAX_AUTH_MSG)
+
+//
+// STA's AUTH_RSP state machine: states, events, total function #
+//
+#define AUTH_RSP_IDLE                   0
+#define AUTH_RSP_WAIT_CHAL              1
+#define MAX_AUTH_RSP_STATE              2
+
+#define AUTH_RSP_MACHINE_BASE           0
+#define MT2_AUTH_CHALLENGE_TIMEOUT      0
+#define MT2_PEER_AUTH_ODD               1
+#define MT2_PEER_DEAUTH                 2
+#define MAX_AUTH_RSP_MSG                3
+
+#define AUTH_RSP_FUNC_SIZE              (MAX_AUTH_RSP_STATE * MAX_AUTH_RSP_MSG)
+
+//
+// STA's SYNC state machine: states, events, total function #
+//
+#define SYNC_IDLE                       0  // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state
+#define JOIN_WAIT_BEACON                1
+#define SCAN_LISTEN                     2
+#define MAX_SYNC_STATE                  3
+
+#define SYNC_MACHINE_BASE               0
+#define MT2_MLME_SCAN_REQ               0
+#define MT2_MLME_JOIN_REQ               1
+#define MT2_MLME_START_REQ              2
+#define MT2_PEER_BEACON                 3
+#define MT2_PEER_PROBE_RSP              4
+#define MT2_PEER_ATIM                   5
+#define MT2_SCAN_TIMEOUT                6
+#define MT2_BEACON_TIMEOUT              7
+#define MT2_ATIM_TIMEOUT                8
+#define MT2_PEER_PROBE_REQ              9
+#define MAX_SYNC_MSG                    10
+
+#define SYNC_FUNC_SIZE                  (MAX_SYNC_STATE * MAX_SYNC_MSG)
+
+//Messages for the DLS state machine
+#define DLS_IDLE                                               0
+#define MAX_DLS_STATE                                  1
+
+#define DLS_MACHINE_BASE                               0
+#define MT2_MLME_DLS_REQ                           0
+#define MT2_PEER_DLS_REQ                           1
+#define MT2_PEER_DLS_RSP                           2
+#define MT2_MLME_DLS_TEAR_DOWN             3
+#define MT2_PEER_DLS_TEAR_DOWN             4
+#define MAX_DLS_MSG                                    5
+
+#define DLS_FUNC_SIZE                                  (MAX_DLS_STATE * MAX_DLS_MSG)
+
+//
+// STA's WPA-PSK State machine: states, events, total function #
+//
+#define WPA_PSK_IDLE                                   0
+#define MAX_WPA_PSK_STATE                              1
+
+#define WPA_MACHINE_BASE                0
+#define MT2_EAPPacket                   0
+#define MT2_EAPOLStart                  1
+#define MT2_EAPOLLogoff                 2
+#define MT2_EAPOLKey                    3
+#define MT2_EAPOLASFAlert               4
+#define MAX_WPA_PSK_MSG                 5
+
+#define        WPA_PSK_FUNC_SIZE                               (MAX_WPA_PSK_STATE * MAX_WPA_PSK_MSG)
+
+//
+// STA's CISCO-AIRONET State machine: states, events, total function #
+//
+#define AIRONET_IDLE                                   0
+#define        AIRONET_SCANNING                                1
+#define MAX_AIRONET_STATE                              2
+
+#define AIRONET_MACHINE_BASE               0
+#define MT2_AIRONET_MSG                                    0
+#define MT2_AIRONET_SCAN_REQ               1
+#define MT2_AIRONET_SCAN_DONE              2
+#define MAX_AIRONET_MSG                                    3
+
+#define        AIRONET_FUNC_SIZE                               (MAX_AIRONET_STATE * MAX_AIRONET_MSG)
+
+//
+// AP's CONTROL/CONNECT state machine: states, events, total function #
+//
+#define AP_CNTL_FUNC_SIZE               1
+
+//
+// AP's ASSOC state machine: states, events, total function #
+//
+#define AP_ASSOC_IDLE                   0
+#define AP_MAX_ASSOC_STATE              1
+
+#define AP_ASSOC_MACHINE_BASE           0
+#define APMT2_MLME_DISASSOC_REQ         0
+#define APMT2_PEER_DISASSOC_REQ         1
+#define APMT2_PEER_ASSOC_REQ            2
+#define APMT2_PEER_REASSOC_REQ          3
+#define APMT2_CLS3ERR                   4
+#define AP_MAX_ASSOC_MSG                5
+
+#define AP_ASSOC_FUNC_SIZE              (AP_MAX_ASSOC_STATE * AP_MAX_ASSOC_MSG)
+
+//
+// AP's AUTHENTICATION state machine: states, events, total function #
+//
+#define AP_AUTH_REQ_IDLE                0
+#define AP_MAX_AUTH_STATE               1
+
+#define AP_AUTH_MACHINE_BASE            0
+#define APMT2_MLME_DEAUTH_REQ           0
+#define APMT2_CLS2ERR                   1
+#define AP_MAX_AUTH_MSG                 2
+
+#define AP_AUTH_FUNC_SIZE               (AP_MAX_AUTH_STATE * AP_MAX_AUTH_MSG)
+
+//
+// AP's AUTH-RSP state machine: states, events, total function #
+//
+#define AP_AUTH_RSP_IDLE                0
+#define AP_MAX_AUTH_RSP_STATE           1
+
+#define AP_AUTH_RSP_MACHINE_BASE        0
+#define APMT2_AUTH_CHALLENGE_TIMEOUT    0
+#define APMT2_PEER_AUTH_ODD             1
+#define APMT2_PEER_DEAUTH               2
+#define AP_MAX_AUTH_RSP_MSG             3
+
+#define AP_AUTH_RSP_FUNC_SIZE           (AP_MAX_AUTH_RSP_STATE * AP_MAX_AUTH_RSP_MSG)
+
+//
+// AP's SYNC state machine: states, events, total function #
+//
+#define AP_SYNC_IDLE                    0
+#define AP_SCAN_LISTEN                                 1
+#define AP_MAX_SYNC_STATE               2
+
+#define AP_SYNC_MACHINE_BASE            0
+#define APMT2_PEER_PROBE_REQ            0
+#define APMT2_PEER_BEACON               1
+#define APMT2_MLME_SCAN_REQ                            2
+#define APMT2_PEER_PROBE_RSP                   3
+#define APMT2_SCAN_TIMEOUT                             4
+#define APMT2_MLME_SCAN_CNCL                   5
+#define AP_MAX_SYNC_MSG                 6
+
+#define AP_SYNC_FUNC_SIZE               (AP_MAX_SYNC_STATE * AP_MAX_SYNC_MSG)
+
+//
+// AP's WPA state machine: states, events, total function #
+//
+#define AP_WPA_PTK                      0
+#define AP_MAX_WPA_PTK_STATE            1
+
+#define AP_WPA_MACHINE_BASE             0
+#define APMT2_EAPPacket                 0
+#define APMT2_EAPOLStart                1
+#define APMT2_EAPOLLogoff               2
+#define APMT2_EAPOLKey                  3
+#define APMT2_EAPOLASFAlert             4
+#define AP_MAX_WPA_MSG                  5
+
+#define AP_WPA_FUNC_SIZE                (AP_MAX_WPA_PTK_STATE * AP_MAX_WPA_MSG)
+
+#ifdef APCLI_SUPPORT
+//ApCli authentication state machine
+#define APCLI_AUTH_REQ_IDLE                0
+#define APCLI_AUTH_WAIT_SEQ2               1
+#define APCLI_AUTH_WAIT_SEQ4               2
+#define APCLI_MAX_AUTH_STATE               3
+
+#define APCLI_AUTH_MACHINE_BASE            0
+#define APCLI_MT2_MLME_AUTH_REQ            0
+#define APCLI_MT2_MLME_DEAUTH_REQ          1
+#define APCLI_MT2_PEER_AUTH_EVEN           2
+#define APCLI_MT2_PEER_DEAUTH              3
+#define APCLI_MT2_AUTH_TIMEOUT             4
+#define APCLI_MAX_AUTH_MSG                 5
+
+#define APCLI_AUTH_FUNC_SIZE               (APCLI_MAX_AUTH_STATE * APCLI_MAX_AUTH_MSG)
+
+//ApCli association state machine
+#define APCLI_ASSOC_IDLE                   0
+#define APCLI_ASSOC_WAIT_RSP               1
+#define APCLI_MAX_ASSOC_STATE              2
+
+#define APCLI_ASSOC_MACHINE_BASE           0
+#define APCLI_MT2_MLME_ASSOC_REQ           0
+#define APCLI_MT2_MLME_DISASSOC_REQ        1
+#define APCLI_MT2_PEER_DISASSOC_REQ        2
+#define APCLI_MT2_PEER_ASSOC_RSP           3
+#define APCLI_MT2_ASSOC_TIMEOUT            4
+#define APCLI_MAX_ASSOC_MSG                5
+
+#define APCLI_ASSOC_FUNC_SIZE              (APCLI_MAX_ASSOC_STATE * APCLI_MAX_ASSOC_MSG)
+
+//ApCli sync state machine
+#define APCLI_SYNC_IDLE                   0  // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state
+#define APCLI_JOIN_WAIT_PROBE_RSP         1
+#define APCLI_MAX_SYNC_STATE              2
+
+#define APCLI_SYNC_MACHINE_BASE           0
+#define APCLI_MT2_MLME_PROBE_REQ          0
+#define APCLI_MT2_PEER_PROBE_RSP          1
+#define APCLI_MT2_PROBE_TIMEOUT           2
+#define APCLI_MAX_SYNC_MSG                3
+
+#define APCLI_SYNC_FUNC_SIZE              (APCLI_MAX_SYNC_STATE * APCLI_MAX_SYNC_MSG)
+
+//ApCli ctrl state machine
+#define APCLI_CTRL_DISCONNECTED           0  // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state
+#define APCLI_CTRL_PROBE                  1
+#define APCLI_CTRL_AUTH                   2
+#define APCLI_CTRL_AUTH_2                 3
+#define APCLI_CTRL_ASSOC                  4
+#define APCLI_CTRL_DEASSOC                5
+#define APCLI_CTRL_CONNECTED              6
+#define APCLI_MAX_CTRL_STATE              7
+
+#define APCLI_CTRL_MACHINE_BASE           0
+#define APCLI_CTRL_JOIN_REQ               0
+#define APCLI_CTRL_PROBE_RSP              1
+#define APCLI_CTRL_AUTH_RSP               2
+#define APCLI_CTRL_DISCONNECT_REQ         3
+#define APCLI_CTRL_PEER_DISCONNECT_REQ    4
+#define APCLI_CTRL_ASSOC_RSP              5
+#define APCLI_CTRL_DEASSOC_RSP            6
+#define APCLI_CTRL_JOIN_REQ_TIMEOUT       7
+#define APCLI_CTRL_AUTH_REQ_TIMEOUT       8
+#define APCLI_CTRL_ASSOC_REQ_TIMEOUT      9
+#define APCLI_MAX_CTRL_MSG                10
+
+#define APCLI_CTRL_FUNC_SIZE              (APCLI_MAX_CTRL_STATE * APCLI_MAX_CTRL_MSG)
+
+#if 0  // remove those variables by AlbertY
+// ApCli WPA state machine
+#define APCLI_WPA_PSK_IDLE                             0
+#define APCLI_MAX_WPA_PSK_STATE                        1
+
+// ApCli WPA MSG Type
+#define APCLI_WPA_MACHINE_BASE                 0
+#define APCLI_MT2_EAPPacket                            0
+#define APCLI_MT2_EAPOLStart                   1
+#define APCLI_MT2_EAPOLLogoff                  2
+#define APCLI_MT2_EAPOLKey                             3
+#define APCLI_MT2_EAPOLASFAlert                        4
+#define APCLI_MAX_WPA_PSK_MSG                  5
+
+#define        APCLI_WPA_PSK_FUNC_SIZE                 (APCLI_MAX_WPA_PSK_STATE * APCLI_MAX_WPA_PSK_MSG)
+#endif // end - 0 //
+
+#endif // APCLI_SUPPORT //
+
+
+// =============================================================================
+
+// value domain of 802.11 header FC.Tyte, which is b3..b2 of the 1st-byte of MAC header
+#define BTYPE_MGMT                  0
+#define BTYPE_CNTL                  1
+#define BTYPE_DATA                  2
+
+// value domain of 802.11 MGMT frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header
+#define SUBTYPE_ASSOC_REQ           0
+#define SUBTYPE_ASSOC_RSP           1
+#define SUBTYPE_REASSOC_REQ         2
+#define SUBTYPE_REASSOC_RSP         3
+#define SUBTYPE_PROBE_REQ           4
+#define SUBTYPE_PROBE_RSP           5
+#define SUBTYPE_BEACON              8
+#define SUBTYPE_ATIM                9
+#define SUBTYPE_DISASSOC            10
+#define SUBTYPE_AUTH                11
+#define SUBTYPE_DEAUTH              12
+#define SUBTYPE_ACTION              13
+#define SUBTYPE_ACTION_NO_ACK              14
+
+// value domain of 802.11 CNTL frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header
+#define SUBTYPE_WRAPPER        7
+#define SUBTYPE_BLOCK_ACK_REQ       8
+#define SUBTYPE_BLOCK_ACK           9
+#define SUBTYPE_PS_POLL             10
+#define SUBTYPE_RTS                 11
+#define SUBTYPE_CTS                 12
+#define SUBTYPE_ACK                 13
+#define SUBTYPE_CFEND               14
+#define SUBTYPE_CFEND_CFACK         15
+
+// value domain of 802.11 DATA frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header
+#define SUBTYPE_DATA                0
+#define SUBTYPE_DATA_CFACK          1
+#define SUBTYPE_DATA_CFPOLL         2
+#define SUBTYPE_DATA_CFACK_CFPOLL   3
+#define SUBTYPE_NULL_FUNC           4
+#define SUBTYPE_CFACK               5
+#define SUBTYPE_CFPOLL              6
+#define SUBTYPE_CFACK_CFPOLL        7
+#define SUBTYPE_QDATA               8
+#define SUBTYPE_QDATA_CFACK         9
+#define SUBTYPE_QDATA_CFPOLL        10
+#define SUBTYPE_QDATA_CFACK_CFPOLL  11
+#define SUBTYPE_QOS_NULL            12
+#define SUBTYPE_QOS_CFACK           13
+#define SUBTYPE_QOS_CFPOLL          14
+#define SUBTYPE_QOS_CFACK_CFPOLL    15
+
+// ACK policy of QOS Control field bit 6:5
+#define NORMAL_ACK                  0x00  // b6:5 = 00
+#define NO_ACK                      0x20  // b6:5 = 01
+#define NO_EXPLICIT_ACK             0x40  // b6:5 = 10
+#define BLOCK_ACK                   0x60  // b6:5 = 11
+
+//
+// rtmp_data.c use these definition
+//
+#define LENGTH_802_11               24
+#define LENGTH_802_11_AND_H         30
+#define LENGTH_802_11_CRC_H         34
+#define LENGTH_802_11_CRC           28
+#define LENGTH_802_11_WITH_ADDR4    30
+#define LENGTH_802_3                14
+#define LENGTH_802_3_TYPE           2
+#define LENGTH_802_1_H              8
+#define LENGTH_EAPOL_H              4
+#define LENGTH_WMMQOS_H                                2
+#define LENGTH_CRC                  4
+#define MAX_SEQ_NUMBER              0x0fff
+#define LENGTH_802_3_NO_TYPE           12
+#define LENGTH_802_1Q                          4 /* VLAN related */
+
+// STA_CSR4.field.TxResult
+#define TX_RESULT_SUCCESS           0
+#define TX_RESULT_ZERO_LENGTH       1
+#define TX_RESULT_UNDER_RUN         2
+#define TX_RESULT_OHY_ERROR         4
+#define TX_RESULT_RETRY_FAIL        6
+
+// All PHY rate summary in TXD
+// Preamble MODE in TxD
+#define MODE_CCK       0
+#define MODE_OFDM   1
+#ifdef DOT11_N_SUPPORT
+#define MODE_HTMIX     2
+#define MODE_HTGREENFIELD      3
+#endif // DOT11_N_SUPPORT //
+// MCS for CCK.  BW.SGI.STBC are reserved
+#define MCS_LONGP_RATE_1                      0         // long preamble CCK 1Mbps
+#define MCS_LONGP_RATE_2                      1        // long preamble CCK 1Mbps
+#define MCS_LONGP_RATE_5_5                    2
+#define MCS_LONGP_RATE_11                     3
+#define MCS_SHORTP_RATE_1                      4        // long preamble CCK 1Mbps. short is forbidden in 1Mbps
+#define MCS_SHORTP_RATE_2                      5       // short preamble CCK 2Mbps
+#define MCS_SHORTP_RATE_5_5                    6
+#define MCS_SHORTP_RATE_11                     7
+// To send duplicate legacy OFDM. set BW=BW_40.  SGI.STBC are reserved
+#define MCS_RATE_6                      0   // legacy OFDM
+#define MCS_RATE_9                      1   // OFDM
+#define MCS_RATE_12                     2   // OFDM
+#define MCS_RATE_18                     3   // OFDM
+#define MCS_RATE_24                     4  // OFDM
+#define MCS_RATE_36                     5   // OFDM
+#define MCS_RATE_48                     6  // OFDM
+#define MCS_RATE_54                     7 // OFDM
+// HT
+#define MCS_0          0       // 1S
+#define MCS_1          1
+#define MCS_2          2
+#define MCS_3          3
+#define MCS_4          4
+#define MCS_5          5
+#define MCS_6          6
+#define MCS_7          7
+#define MCS_8          8       // 2S
+#define MCS_9          9
+#define MCS_10         10
+#define MCS_11         11
+#define MCS_12         12
+#define MCS_13         13
+#define MCS_14         14
+#define MCS_15         15
+#define MCS_16         16      // 3*3
+#define MCS_17         17
+#define MCS_18         18
+#define MCS_19         19
+#define MCS_20         20
+#define MCS_21         21
+#define MCS_22         22
+#define MCS_23         23
+#define MCS_32         32
+#define MCS_AUTO               33
+
+#ifdef DOT11_N_SUPPORT
+// OID_HTPHYMODE
+// MODE
+#define HTMODE_MM      0
+#define HTMODE_GF      1
+#endif // DOT11_N_SUPPORT //
+
+// Fixed Tx MODE - HT, CCK or OFDM
+#define FIXED_TXMODE_HT                0
+#define FIXED_TXMODE_CCK       1
+#define FIXED_TXMODE_OFDM      2
+// BW
+#define BW_20          BAND_WIDTH_20
+#define BW_40          BAND_WIDTH_40
+#define BW_BOTH                BAND_WIDTH_BOTH
+#define BW_10          BAND_WIDTH_10   // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field.
+
+#ifdef DOT11_N_SUPPORT
+// SHORTGI
+#define GI_400         GAP_INTERVAL_400        // only support in HT mode
+#define GI_BOTH                GAP_INTERVAL_BOTH
+#endif // DOT11_N_SUPPORT //
+#define GI_800         GAP_INTERVAL_800
+// STBC
+#define STBC_NONE      0
+#ifdef DOT11_N_SUPPORT
+#define STBC_USE       1       // limited use in rt2860b phy
+#define RXSTBC_ONE     1       // rx support of one spatial stream
+#define RXSTBC_TWO     2       // rx support of 1 and 2 spatial stream
+#define RXSTBC_THR     3       // rx support of 1~3 spatial stream
+// MCS FEEDBACK
+#define MCSFBK_NONE    0  // not support mcs feedback /
+#define MCSFBK_RSV     1       // reserved
+#define MCSFBK_UNSOLICIT       2       // only support unsolict mcs feedback
+#define MCSFBK_MRQ     3       // response to both MRQ and unsolict mcs feedback
+
+// MIMO power safe
+#define        MMPS_STATIC     0
+#define        MMPS_DYNAMIC            1
+#define   MMPS_RSV             2
+#define MMPS_ENABLE            3
+
+
+// A-MSDU size
+#define        AMSDU_0 0
+#define        AMSDU_1         1
+
+#endif // DOT11_N_SUPPORT //
+
+// MCS use 7 bits
+#define TXRATEMIMO             0x80
+#define TXRATEMCS              0x7F
+#define TXRATEOFDM             0x7F
+#define RATE_1                      0
+#define RATE_2                      1
+#define RATE_5_5                    2
+#define RATE_11                     3
+#define RATE_6                      4   // OFDM
+#define RATE_9                      5   // OFDM
+#define RATE_12                     6   // OFDM
+#define RATE_18                     7   // OFDM
+#define RATE_24                     8   // OFDM
+#define RATE_36                     9   // OFDM
+#define RATE_48                     10  // OFDM
+#define RATE_54                     11  // OFDM
+#define RATE_FIRST_OFDM_RATE        RATE_6
+#define RATE_LAST_OFDM_RATE            RATE_54
+#define RATE_6_5                    12  // HT mix
+#define RATE_13                     13  // HT mix
+#define RATE_19_5                   14  // HT mix
+#define RATE_26                     15  // HT mix
+#define RATE_39                     16  // HT mix
+#define RATE_52                     17  // HT mix
+#define RATE_58_5                   18  // HT mix
+#define RATE_65                     19  // HT mix
+#define RATE_78                     20  // HT mix
+#define RATE_104                    21  // HT mix
+#define RATE_117                    22  // HT mix
+#define RATE_130                    23  // HT mix
+//#define RATE_AUTO_SWITCH            255 // for StaCfg.FixedTxRate only
+#define HTRATE_0                      12
+#define RATE_FIRST_MM_RATE        HTRATE_0
+#define RATE_FIRST_HT_RATE        HTRATE_0
+#define RATE_LAST_HT_RATE        HTRATE_0
+
+// pTxWI->txop
+#define IFS_HTTXOP                 0   // The txop will be handles by ASIC.
+#define IFS_PIFS                    1
+#define IFS_SIFS                    2
+#define IFS_BACKOFF                 3
+
+// pTxD->RetryMode
+#define LONG_RETRY                  1
+#define SHORT_RETRY                 0
+
+// Country Region definition
+#define REGION_MINIMUM_BG_BAND            0
+#define REGION_0_BG_BAND                  0       // 1-11
+#define REGION_1_BG_BAND                  1       // 1-13
+#define REGION_2_BG_BAND                  2       // 10-11
+#define REGION_3_BG_BAND                  3       // 10-13
+#define REGION_4_BG_BAND                  4       // 14
+#define REGION_5_BG_BAND                  5       // 1-14
+#define REGION_6_BG_BAND                  6       // 3-9
+#define REGION_7_BG_BAND                  7       // 5-13
+#define REGION_31_BG_BAND                 31       // 5-13
+#define REGION_MAXIMUM_BG_BAND            7
+
+#define REGION_MINIMUM_A_BAND             0
+#define REGION_0_A_BAND                   0       // 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165
+#define REGION_1_A_BAND                   1       // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+#define REGION_2_A_BAND                   2       // 36, 40, 44, 48, 52, 56, 60, 64
+#define REGION_3_A_BAND                   3       // 52, 56, 60, 64, 149, 153, 157, 161
+#define REGION_4_A_BAND                   4       // 149, 153, 157, 161, 165
+#define REGION_5_A_BAND                   5       // 149, 153, 157, 161
+#define REGION_6_A_BAND                   6       // 36, 40, 44, 48
+#define REGION_7_A_BAND                   7       // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165
+#define REGION_8_A_BAND                   8       // 52, 56, 60, 64
+#define REGION_9_A_BAND                   9       // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165
+#define REGION_10_A_BAND                  10     // 36, 40, 44, 48, 149, 153, 157, 161, 165
+#define REGION_11_A_BAND                  11     // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161
+#define REGION_MAXIMUM_A_BAND             11
+
+// pTxD->CipherAlg
+#define CIPHER_NONE                 0
+#define CIPHER_WEP64                1
+#define CIPHER_WEP128               2
+#define CIPHER_TKIP                 3
+#define CIPHER_AES                  4
+#define CIPHER_CKIP64               5
+#define CIPHER_CKIP128              6
+#define CIPHER_TKIP_NO_MIC          7       // MIC appended by driver: not a valid value in hardware key table
+#define CIPHER_SMS4                                    8
+
+// value domain of pAd->RfIcType
+#define RFIC_2820                   1       // 2.4G 2T3R
+#define RFIC_2850                   2       // 2.4G/5G 2T3R
+#define RFIC_2720                   3       // 2.4G 1T2R
+#define RFIC_2750                   4       // 2.4G/5G 1T2R
+#define RFIC_3020                   5       // 2.4G 1T1R
+#define RFIC_2020                   6       // 2.4G B/G
+
+// LED Status.
+#define LED_LINK_DOWN               0
+#define LED_LINK_UP                 1
+#define LED_RADIO_OFF               2
+#define LED_RADIO_ON                3
+#define LED_HALT                    4
+#define LED_WPS                     5
+#define LED_ON_SITE_SURVEY          6
+#define LED_POWER_UP                7
+
+// value domain of pAd->LedCntl.LedMode and E2PROM
+#define LED_MODE_DEFAULT            0
+#define LED_MODE_TWO_LED                       1
+#define LED_MODE_SIGNAL_STREGTH                8  // EEPROM define =8
+
+// RC4 init value, used fro WEP & TKIP
+#define PPPINITFCS32                0xffffffff   /* Initial FCS value */
+
+// value domain of pAd->StaCfg.PortSecured. 802.1X controlled port definition
+#define WPA_802_1X_PORT_SECURED     1
+#define WPA_802_1X_PORT_NOT_SECURED 2
+
+#define PAIRWISE_KEY                1
+#define GROUP_KEY                   2
+
+//definition of DRS
+#define MAX_STEP_OF_TX_RATE_SWITCH     32
+
+
+// pre-allocated free NDIS PACKET/BUFFER poll for internal usage
+#define MAX_NUM_OF_FREE_NDIS_PACKET 128
+
+//Block ACK
+#define MAX_TX_REORDERBUF   64
+#define MAX_RX_REORDERBUF   64
+#define DEFAULT_TX_TIMEOUT   30
+#define DEFAULT_RX_TIMEOUT   30
+
+// definition of Recipient or Originator
+#define I_RECIPIENT                  TRUE
+#define I_ORIGINATOR                   FALSE
+
+#define DEFAULT_BBP_TX_POWER        0
+#define DEFAULT_RF_TX_POWER         5
+
+#define MAX_INI_BUFFER_SIZE                    4096
+#define MAX_PARAM_BUFFER_SIZE          (2048) // enough for ACL (18*64)
+                                                                                       //18 : the length of Mac address acceptable format "01:02:03:04:05:06;")
+                                                                                       //64 : MAX_NUM_OF_ACL_LIST
+// definition of pAd->OpMode
+#define OPMODE_STA                  0
+#define OPMODE_AP                   1
+//#define OPMODE_L3_BRG               2       // as AP and STA at the same time
+
+#ifdef RT_BIG_ENDIAN
+#define DIR_READ                    0
+#define DIR_WRITE                   1
+#define TYPE_TXD                    0
+#define TYPE_RXD                    1
+#define TYPE_TXINFO                                    0
+#define TYPE_RXINFO                                    1
+#define TYPE_TXWI                                      0
+#define TYPE_RXWI                                      1
+#endif
+
+// ========================= AP rtmp_def.h ===========================
+// value domain for pAd->EventTab.Log[].Event
+#define EVENT_RESET_ACCESS_POINT    0 // Log = "hh:mm:ss   Restart Access Point"
+#define EVENT_ASSOCIATED            1 // Log = "hh:mm:ss   STA 00:01:02:03:04:05 associated"
+#define EVENT_DISASSOCIATED         2 // Log = "hh:mm:ss   STA 00:01:02:03:04:05 left this BSS"
+#define EVENT_AGED_OUT              3 // Log = "hh:mm:ss   STA 00:01:02:03:04:05 was aged-out and removed from this BSS"
+#define EVENT_COUNTER_M             4
+#define EVENT_INVALID_PSK           5
+#define EVENT_MAX_EVENT_TYPE        6
+// ==== end of AP rtmp_def.h ============
+
+// definition RSSI Number
+#define RSSI_0                                 0
+#define RSSI_1                                 1
+#define RSSI_2                                 2
+
+// definition of radar detection
+#define RD_NORMAL_MODE                         0       // Not found radar signal
+#define RD_SWITCHING_MODE                      1       // Found radar signal, and doing channel switch
+#define RD_SILENCE_MODE                                2       // After channel switch, need to be silence a while to ensure radar not found
+
+//Driver defined cid for mapping status and command.
+#define  SLEEPCID      0x11
+#define  WAKECID       0x22
+#define  QUERYPOWERCID 0x33
+#define  OWNERMCU      0x1
+#define  OWNERCPU      0x0
+
+// MBSSID definition
+#define ENTRY_NOT_FOUND             0xFF
+
+
+/* After Linux 2.6.9,
+ * VLAN module use Private (from user) interface flags (netdevice->priv_flags).
+ * #define IFF_802_1Q_VLAN 0x1         --    802.1Q VLAN device.  in if.h
+ * ref to ip_sabotage_out() [ out->priv_flags & IFF_802_1Q_VLAN ] in br_netfilter.c
+ *
+ * For this reason, we MUST use EVEN value in priv_flags
+ */
+#define INT_MAIN                    0x0100
+#define INT_MBSSID                  0x0200
+#define INT_WDS                     0x0300
+#define INT_APCLI                   0x0400
+#define INT_MESH                       0x0500
+
+// Use bitmap to allow coexist of ATE_TXFRAME and ATE_RXFRAME(i.e.,to support LoopBack mode)
+#ifdef RALINK_ATE
+#define        ATE_START                   0x00   // Start ATE
+#define        ATE_STOP                    0x80   // Stop ATE
+#define        ATE_TXCONT                  0x05   // Continuous Transmit
+#define        ATE_TXCARR                  0x09   // Transmit Carrier
+#define        ATE_TXCARRSUPP              0x11   // Transmit Carrier Suppression
+#define        ATE_TXFRAME                 0x01   // Transmit Frames
+#define        ATE_RXFRAME                 0x02   // Receive Frames
+#ifdef RALINK_28xx_QA
+#define ATE_TXSTOP                  0xe2   // Stop Transmition(i.e., TXCONT, TXCARR, TXCARRSUPP, and TXFRAME)
+#define ATE_RXSTOP                                     0xfd   // Stop receiving Frames
+#define        BBP22_TXFRAME                           0x00   // Transmit Frames
+#define        BBP22_TXCONT_OR_CARRSUPP    0x80   // Continuous Transmit or Carrier Suppression
+#define        BBP22_TXCARR                0xc1   // Transmit Carrier
+#define        BBP24_TXCONT                0x00   // Continuous Transmit
+#define        BBP24_CARRSUPP              0x01   // Carrier Suppression
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+// WEP Key TYPE
+#define WEP_HEXADECIMAL_TYPE    0
+#define WEP_ASCII_TYPE          1
+
+
+
+// WIRELESS EVENTS definition
+/* Max number of char in custom event, refer to wireless_tools.28/wireless.20.h */
+#define IW_CUSTOM_MAX_LEN                                                      255     /* In bytes */
+
+// For system event - start
+#define        IW_SYS_EVENT_FLAG_START                     0x0200
+#define        IW_ASSOC_EVENT_FLAG                         0x0200
+#define        IW_DISASSOC_EVENT_FLAG                      0x0201
+#define        IW_DEAUTH_EVENT_FLAG                            0x0202
+#define        IW_AGEOUT_EVENT_FLAG                            0x0203
+#define        IW_COUNTER_MEASURES_EVENT_FLAG              0x0204
+#define        IW_REPLAY_COUNTER_DIFF_EVENT_FLAG           0x0205
+#define        IW_RSNIE_DIFF_EVENT_FLAG                                0x0206
+#define        IW_MIC_DIFF_EVENT_FLAG                                  0x0207
+#define IW_ICV_ERROR_EVENT_FLAG                                                0x0208
+#define IW_MIC_ERROR_EVENT_FLAG                                                0x0209
+#define IW_GROUP_HS_TIMEOUT_EVENT_FLAG                         0x020A
+#define        IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG                       0x020B
+#define IW_RSNIE_SANITY_FAIL_EVENT_FLAG                                0x020C
+#define IW_SET_KEY_DONE_WPA1_EVENT_FLAG                                0x020D
+#define IW_SET_KEY_DONE_WPA2_EVENT_FLAG                                0x020E
+#define IW_STA_LINKUP_EVENT_FLAG                                       0x020F
+#define IW_STA_LINKDOWN_EVENT_FLAG                                     0x0210
+#define IW_SCAN_COMPLETED_EVENT_FLAG                           0x0211
+#define IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG                                0x0212
+// if add new system event flag, please upadte the IW_SYS_EVENT_FLAG_END
+#define        IW_SYS_EVENT_FLAG_END                       0x0212
+#define        IW_SYS_EVENT_TYPE_NUM                                           (IW_SYS_EVENT_FLAG_END - IW_SYS_EVENT_FLAG_START + 1)
+// For system event - end
+
+// For spoof attack event - start
+#define        IW_SPOOF_EVENT_FLAG_START                   0x0300
+#define IW_CONFLICT_SSID_EVENT_FLAG                                    0x0300
+#define IW_SPOOF_ASSOC_RESP_EVENT_FLAG                         0x0301
+#define IW_SPOOF_REASSOC_RESP_EVENT_FLAG                       0x0302
+#define IW_SPOOF_PROBE_RESP_EVENT_FLAG                         0x0303
+#define IW_SPOOF_BEACON_EVENT_FLAG                                     0x0304
+#define IW_SPOOF_DISASSOC_EVENT_FLAG                           0x0305
+#define IW_SPOOF_AUTH_EVENT_FLAG                                       0x0306
+#define IW_SPOOF_DEAUTH_EVENT_FLAG                                     0x0307
+#define IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG                       0x0308
+#define IW_REPLAY_ATTACK_EVENT_FLAG                                    0x0309
+// if add new spoof attack event flag, please upadte the IW_SPOOF_EVENT_FLAG_END
+#define        IW_SPOOF_EVENT_FLAG_END                     0x0309
+#define        IW_SPOOF_EVENT_TYPE_NUM                                         (IW_SPOOF_EVENT_FLAG_END - IW_SPOOF_EVENT_FLAG_START + 1)
+// For spoof attack event - end
+
+// For flooding attack event - start
+#define        IW_FLOOD_EVENT_FLAG_START                   0x0400
+#define IW_FLOOD_AUTH_EVENT_FLAG                                       0x0400
+#define IW_FLOOD_ASSOC_REQ_EVENT_FLAG                          0x0401
+#define IW_FLOOD_REASSOC_REQ_EVENT_FLAG                                0x0402
+#define IW_FLOOD_PROBE_REQ_EVENT_FLAG                          0x0403
+#define IW_FLOOD_DISASSOC_EVENT_FLAG                           0x0404
+#define IW_FLOOD_DEAUTH_EVENT_FLAG                                     0x0405
+#define IW_FLOOD_EAP_REQ_EVENT_FLAG                                    0x0406
+// if add new flooding attack event flag, please upadte the IW_FLOOD_EVENT_FLAG_END
+#define        IW_FLOOD_EVENT_FLAG_END                         0x0406
+#define        IW_FLOOD_EVENT_TYPE_NUM                                         (IW_FLOOD_EVENT_FLAG_END - IW_FLOOD_EVENT_FLAG_START + 1)
+// For flooding attack - end
+
+// End - WIRELESS EVENTS definition
+
+#ifdef CONFIG_STA_SUPPORT
+// definition for DLS, kathy
+#define        MAX_NUM_OF_INIT_DLS_ENTRY   1
+#define        MAX_NUM_OF_DLS_ENTRY        MAX_NUMBER_OF_DLS_ENTRY
+
+//Block ACK , rt2860, kathy
+#define MAX_TX_REORDERBUF              64
+#define MAX_RX_REORDERBUF              64
+#define DEFAULT_TX_TIMEOUT             30
+#define DEFAULT_RX_TIMEOUT             30
+#ifndef CONFIG_AP_SUPPORT
+#define MAX_BARECI_SESSION             8
+#endif
+
+#ifndef IW_ESSID_MAX_SIZE
+/* Maximum size of the ESSID and pAd->nickname strings */
+#define IW_ESSID_MAX_SIZE              32
+#endif
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef MCAST_RATE_SPECIFIC
+#define MCAST_DISABLE  0
+#define MCAST_CCK              1
+#define MCAST_OFDM             2
+#define MCAST_HTMIX            3
+#endif // MCAST_RATE_SPECIFIC //
+
+// For AsicRadioOff/AsicRadioOn function
+#define DOT11POWERSAVE         0
+#define GUIRADIO_OFF           1
+#define RTMP_HALT                  2
+#define GUI_IDLE_POWER_SAVE            3
+// --
+
+
+// definition for WpaSupport flag
+#define WPA_SUPPLICANT_DISABLE                         0
+#define WPA_SUPPLICANT_ENABLE                          1
+#define        WPA_SUPPLICANT_ENABLE_WITH_WEB_UI       2
+
+// Endian byte swapping codes
+#define SWAP16(x) \
+    ((UINT16)( \
+    (((UINT16)(x) & (UINT16) 0x00ffU) << 8) | \
+    (((UINT16)(x) & (UINT16) 0xff00U) >> 8) ))
+
+#define SWAP32(x) \
+    ((UINT32)( \
+    (((UINT32)(x) & (UINT32) 0x000000ffUL) << 24) | \
+    (((UINT32)(x) & (UINT32) 0x0000ff00UL) <<  8) | \
+    (((UINT32)(x) & (UINT32) 0x00ff0000UL) >>  8) | \
+    (((UINT32)(x) & (UINT32) 0xff000000UL) >> 24) ))
+
+#define SWAP64(x) \
+    ((UINT64)( \
+    (UINT64)(((UINT64)(x) & (UINT64) 0x00000000000000ffULL) << 56) | \
+    (UINT64)(((UINT64)(x) & (UINT64) 0x000000000000ff00ULL) << 40) | \
+    (UINT64)(((UINT64)(x) & (UINT64) 0x0000000000ff0000ULL) << 24) | \
+    (UINT64)(((UINT64)(x) & (UINT64) 0x00000000ff000000ULL) <<  8) | \
+    (UINT64)(((UINT64)(x) & (UINT64) 0x000000ff00000000ULL) >>  8) | \
+    (UINT64)(((UINT64)(x) & (UINT64) 0x0000ff0000000000ULL) >> 24) | \
+    (UINT64)(((UINT64)(x) & (UINT64) 0x00ff000000000000ULL) >> 40) | \
+    (UINT64)(((UINT64)(x) & (UINT64) 0xff00000000000000ULL) >> 56) ))
+
+#ifdef RT_BIG_ENDIAN
+
+#define cpu2le64(x) SWAP64((x))
+#define le2cpu64(x) SWAP64((x))
+#define cpu2le32(x) SWAP32((x))
+#define le2cpu32(x) SWAP32((x))
+#define cpu2le16(x) SWAP16((x))
+#define le2cpu16(x) SWAP16((x))
+#define cpu2be64(x) ((UINT64)(x))
+#define be2cpu64(x) ((UINT64)(x))
+#define cpu2be32(x) ((UINT32)(x))
+#define be2cpu32(x) ((UINT32)(x))
+#define cpu2be16(x) ((UINT16)(x))
+#define be2cpu16(x) ((UINT16)(x))
+
+#else   // Little_Endian
+
+#define cpu2le64(x) ((UINT64)(x))
+#define le2cpu64(x) ((UINT64)(x))
+#define cpu2le32(x) ((UINT32)(x))
+#define le2cpu32(x) ((UINT32)(x))
+#define cpu2le16(x) ((UINT16)(x))
+#define le2cpu16(x) ((UINT16)(x))
+#define cpu2be64(x) SWAP64((x))
+#define be2cpu64(x) SWAP64((x))
+#define cpu2be32(x) SWAP32((x))
+#define be2cpu32(x) SWAP32((x))
+#define cpu2be16(x) SWAP16((x))
+#define be2cpu16(x) SWAP16((x))
+
+#endif  // RT_BIG_ENDIAN
+
+#endif  // __RTMP_DEF_H__
+
+
diff --git a/drivers/staging/rt2870/rtmp_type.h b/drivers/staging/rt2870/rtmp_type.h
new file mode 100644 (file)
index 0000000..1fd7df1
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    rtmp_type.h
+
+    Abstract:
+
+    Revision History:
+    Who         When            What
+    --------    ----------      ----------------------------------------------
+    Name        Date            Modification logs
+    Paul Lin    1-2-2004
+*/
+#ifndef __RTMP_TYPE_H__
+#define __RTMP_TYPE_H__
+
+#define PACKED  __attribute__ ((packed))
+
+// Put platform dependent declaration here
+// For example, linux type definition
+typedef unsigned char          UINT8;
+typedef unsigned short         UINT16;
+typedef unsigned int           UINT32;
+typedef unsigned long long     UINT64;
+typedef int                                    INT32;
+typedef long long                      INT64;
+
+typedef unsigned char *                        PUINT8;
+typedef unsigned short *               PUINT16;
+typedef unsigned int *                 PUINT32;
+typedef unsigned long long *   PUINT64;
+typedef int    *                                       PINT32;
+typedef long long *                    PINT64;
+
+typedef signed char                    CHAR;
+typedef signed short           SHORT;
+typedef signed int                     INT;
+typedef signed long                    LONG;
+typedef signed long long       LONGLONG;
+
+
+typedef unsigned char          UCHAR;
+typedef unsigned short         USHORT;
+typedef unsigned int           UINT;
+typedef unsigned long          ULONG;
+typedef unsigned long long     ULONGLONG;
+
+typedef unsigned char          BOOLEAN;
+typedef void                           VOID;
+
+typedef VOID *                         PVOID;
+typedef CHAR *                         PCHAR;
+typedef UCHAR *                        PUCHAR;
+typedef USHORT *                       PUSHORT;
+typedef LONG *                         PLONG;
+typedef ULONG *                                PULONG;
+typedef UINT *                         PUINT;
+
+typedef unsigned int   NDIS_MEDIA_STATE;
+
+typedef union _LARGE_INTEGER {
+    struct {
+        UINT LowPart;
+        INT32 HighPart;
+    } u;
+    INT64 QuadPart;
+} LARGE_INTEGER;
+
+#endif  // __RTMP_TYPE_H__
+
diff --git a/drivers/staging/rt2870/spectrum.h b/drivers/staging/rt2870/spectrum.h
new file mode 100644 (file)
index 0000000..94cfa5b
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#ifndef __SPECTRUM_H__
+#define __SPECTRUM_H__
+
+#include "rtmp_type.h"
+#include "spectrum_def.h"
+
+typedef struct PACKED _TPC_REPORT_INFO
+{
+       UINT8 TxPwr;
+       UINT8 LinkMargin;
+} TPC_REPORT_INFO, *PTPC_REPORT_INFO;
+
+typedef struct PACKED _CH_SW_ANN_INFO
+{
+       UINT8 ChSwMode;
+       UINT8 Channel;
+       UINT8 ChSwCnt;
+} CH_SW_ANN_INFO, *PCH_SW_ANN_INFO;
+
+typedef union PACKED _MEASURE_REQ_MODE
+{
+#ifdef RT_BIG_ENDIAN
+       struct PACKED
+       {
+               UINT8 Rev1:4;
+               UINT8 Report:1;
+               UINT8 Request:1;
+               UINT8 Enable:1;
+               UINT8 Rev0:1;
+       } field;
+#else
+       struct PACKED
+       {
+               UINT8 Rev0:1;
+               UINT8 Enable:1;
+               UINT8 Request:1;
+               UINT8 Report:1;
+               UINT8 Rev1:4;
+       } field;
+#endif // RT_BIG_ENDIAN //
+       UINT8 word;
+} MEASURE_REQ_MODE, *PMEASURE_REQ_MODE;
+
+typedef struct PACKED _MEASURE_REQ
+{
+       UINT8 ChNum;
+       UINT64 MeasureStartTime;
+       UINT16 MeasureDuration;
+} MEASURE_REQ, *PMEASURE_REQ;
+
+typedef struct PACKED _MEASURE_REQ_INFO
+{
+       UINT8 Token;
+       MEASURE_REQ_MODE ReqMode;
+       UINT8 ReqType;
+       MEASURE_REQ MeasureReq;
+} MEASURE_REQ_INFO, *PMEASURE_REQ_INFO;
+
+typedef union PACKED _MEASURE_BASIC_REPORT_MAP
+{
+#ifdef RT_BIG_ENDIAN
+       struct PACKED
+       {
+               UINT8 Rev:3;
+               UINT8 Unmeasure:1;
+               UINT8 Radar:1;
+               UINT8 UnidentifiedSignal:1;
+               UINT8 OfdmPreamble:1;
+               UINT8 BSS:1;
+       } field;
+#else
+       struct PACKED
+       {
+               UINT8 BSS:1;
+               UINT8 OfdmPreamble:1;
+               UINT8 UnidentifiedSignal:1;
+               UINT8 Radar:1;
+               UINT8 Unmeasure:1;
+               UINT8 Rev:3;
+       } field;
+#endif // RT_BIG_ENDIAN //
+       UINT8 word;
+} MEASURE_BASIC_REPORT_MAP, *PMEASURE_BASIC_REPORT_MAP;
+
+typedef struct PACKED _MEASURE_BASIC_REPORT
+{
+       UINT8 ChNum;
+       UINT64 MeasureStartTime;
+       UINT16 MeasureDuration;
+       MEASURE_BASIC_REPORT_MAP Map;
+} MEASURE_BASIC_REPORT, *PMEASURE_BASIC_REPORT;
+
+typedef struct PACKED _MEASURE_CCA_REPORT
+{
+       UINT8 ChNum;
+       UINT64 MeasureStartTime;
+       UINT16 MeasureDuration;
+       UINT8 CCA_Busy_Fraction;
+} MEASURE_CCA_REPORT, *PMEASURE_CCA_REPORT;
+
+typedef struct PACKED _MEASURE_RPI_REPORT
+{
+       UINT8 ChNum;
+       UINT64 MeasureStartTime;
+       UINT16 MeasureDuration;
+       UINT8 RPI_Density[8];
+} MEASURE_RPI_REPORT, *PMEASURE_RPI_REPORT;
+
+typedef union PACKED _MEASURE_REPORT_MODE
+{
+       struct PACKED
+       {
+#ifdef RT_BIG_ENDIAN
+               UINT8 Rev:5;
+               UINT8 Refused:1;
+               UINT8 Incapable:1;
+               UINT8 Late:1;
+#else
+               UINT8 Late:1;
+               UINT8 Incapable:1;
+               UINT8 Refused:1;
+               UINT8 Rev:5;
+#endif // RT_BIG_ENDIAN //
+       } field;
+       UINT8 word;
+} MEASURE_REPORT_MODE, *PMEASURE_REPORT_MODE;
+
+typedef struct PACKED _MEASURE_REPORT_INFO
+{
+       UINT8 Token;
+       MEASURE_REPORT_MODE ReportMode;
+       UINT8 ReportType;
+       UINT8 Octect[0];
+} MEASURE_REPORT_INFO, *PMEASURE_REPORT_INFO;
+
+typedef struct PACKED _QUIET_INFO
+{
+       UINT8 QuietCnt;
+       UINT8 QuietPeriod;
+       UINT8 QuietDuration;
+       UINT8 QuietOffset;
+} QUIET_INFO, *PQUIET_INFO;
+
+/*
+       ==========================================================================
+       Description:
+               Prepare Measurement request action frame and enqueue it into
+               management queue waiting for transmition.
+
+       Parametrs:
+               1. the destination mac address of the frame.
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID EnqueueMeasurementReq(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pDA,
+       IN UINT8 MeasureToken,
+       IN UINT8 MeasureReqMode,
+       IN UINT8 MeasureReqType,
+       IN UINT8 MeasureCh,
+       IN UINT16 MeasureDuration);
+
+/*
+       ==========================================================================
+       Description:
+               Prepare Measurement report action frame and enqueue it into
+               management queue waiting for transmition.
+
+       Parametrs:
+               1. the destination mac address of the frame.
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID EnqueueMeasurementRep(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pDA,
+       IN UINT8 DialogToken,
+       IN UINT8 MeasureToken,
+       IN UINT8 MeasureReqMode,
+       IN UINT8 MeasureReqType,
+       IN UINT8 ReportInfoLen,
+       IN PUINT8 pReportInfo);
+
+/*
+       ==========================================================================
+       Description:
+               Prepare TPC Request action frame and enqueue it into
+               management queue waiting for transmition.
+
+       Parametrs:
+               1. the destination mac address of the frame.
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID EnqueueTPCReq(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pDA,
+       IN UCHAR DialogToken);
+
+/*
+       ==========================================================================
+       Description:
+               Prepare TPC Report action frame and enqueue it into
+               management queue waiting for transmition.
+
+       Parametrs:
+               1. the destination mac address of the frame.
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID EnqueueTPCRep(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pDA,
+       IN UINT8 DialogToken,
+       IN UINT8 TxPwr,
+       IN UINT8 LinkMargin);
+
+/*
+       ==========================================================================
+       Description:
+               Prepare Channel Switch Announcement action frame and enqueue it into
+               management queue waiting for transmition.
+
+       Parametrs:
+               1. the destination mac address of the frame.
+               2. Channel switch announcement mode.
+               2. a New selected channel.
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID EnqueueChSwAnn(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pDA,
+       IN UINT8 ChSwMode,
+       IN UINT8 NewCh);
+
+/*
+       ==========================================================================
+       Description:
+               Spectrun action frames Handler such as channel switch annoucement,
+               measurement report, measurement request actions frames.
+
+       Parametrs:
+               Elme - MLME message containing the received frame
+
+       Return  : None.
+       ==========================================================================
+ */
+VOID PeerSpectrumAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem);
+
+/*
+       ==========================================================================
+       Description:
+
+       Parametrs:
+
+       Return  : None.
+       ==========================================================================
+ */
+INT Set_MeasureReq_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+INT Set_TpcReq_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+
+VOID MeasureReqTabInit(
+       IN PRTMP_ADAPTER pAd);
+
+VOID MeasureReqTabExit(
+       IN PRTMP_ADAPTER pAd);
+
+VOID TpcReqTabInit(
+       IN PRTMP_ADAPTER pAd);
+
+VOID TpcReqTabExit(
+       IN PRTMP_ADAPTER pAd);
+
+VOID NotifyChSwAnnToPeerAPs(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pRA,
+       IN PUCHAR pTA,
+       IN UINT8 ChSwMode,
+       IN UINT8 Channel);
+#endif // __SPECTRUM_H__ //
+
diff --git a/drivers/staging/rt2870/spectrum_def.h b/drivers/staging/rt2870/spectrum_def.h
new file mode 100644 (file)
index 0000000..4ca4817
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+       spectrum_def.h
+
+    Abstract:
+    Handle association related requests either from WSTA or from local MLME
+
+    Revision History:
+    Who          When          What
+    ---------    ----------    ----------------------------------------------
+       Fonchi Wu    2008                  created for 802.11h
+ */
+
+#ifndef __SPECTRUM_DEF_H__
+#define __SPECTRUM_DEF_H__
+
+#define MAX_MEASURE_REQ_TAB_SIZE               3
+#define MAX_HASH_MEASURE_REQ_TAB_SIZE  MAX_MEASURE_REQ_TAB_SIZE
+
+#define MAX_TPC_REQ_TAB_SIZE                   3
+#define MAX_HASH_TPC_REQ_TAB_SIZE              MAX_TPC_REQ_TAB_SIZE
+
+#define MIN_RCV_PWR                            100             /* Negative value ((dBm) */
+
+#define RM_TPC_REQ                             0
+#define RM_MEASURE_REQ                 1
+
+#define RM_BASIC                               0
+#define RM_CCA                                 1
+#define RM_RPI_HISTOGRAM               2
+
+#define TPC_REQ_AGE_OUT                        500             /* ms */
+#define MQ_REQ_AGE_OUT                 500             /* ms */
+
+#define TPC_DIALOGTOKEN_HASH_INDEX(_DialogToken)       ((_DialogToken) % MAX_HASH_TPC_REQ_TAB_SIZE)
+#define MQ_DIALOGTOKEN_HASH_INDEX(_DialogToken)                ((_DialogToken) % MAX_MEASURE_REQ_TAB_SIZE)
+
+typedef struct _MEASURE_REQ_ENTRY
+{
+       struct _MEASURE_REQ_ENTRY *pNext;
+       ULONG lastTime;
+       BOOLEAN Valid;
+       UINT8 DialogToken;
+       UINT8 MeasureDialogToken[3];    // 0:basic measure, 1: CCA measure, 2: RPI_Histogram measure.
+} MEASURE_REQ_ENTRY, *PMEASURE_REQ_ENTRY;
+
+typedef struct _MEASURE_REQ_TAB
+{
+       UCHAR Size;
+       PMEASURE_REQ_ENTRY Hash[MAX_HASH_MEASURE_REQ_TAB_SIZE];
+       MEASURE_REQ_ENTRY Content[MAX_MEASURE_REQ_TAB_SIZE];
+} MEASURE_REQ_TAB, *PMEASURE_REQ_TAB;
+
+typedef struct _TPC_REQ_ENTRY
+{
+       struct _TPC_REQ_ENTRY *pNext;
+       ULONG lastTime;
+       BOOLEAN Valid;
+       UINT8 DialogToken;
+} TPC_REQ_ENTRY, *PTPC_REQ_ENTRY;
+
+typedef struct _TPC_REQ_TAB
+{
+       UCHAR Size;
+       PTPC_REQ_ENTRY Hash[MAX_HASH_TPC_REQ_TAB_SIZE];
+       TPC_REQ_ENTRY Content[MAX_TPC_REQ_TAB_SIZE];
+} TPC_REQ_TAB, *PTPC_REQ_TAB;
+
+#endif // __SPECTRUM_DEF_H__ //
+
diff --git a/drivers/staging/rt2870/sta/aironet.c b/drivers/staging/rt2870/sta/aironet.c
new file mode 100644 (file)
index 0000000..4af4a19
--- /dev/null
@@ -0,0 +1,1312 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       aironet.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Paul Lin        04-06-15                Initial
+*/
+#include "../rt_config.h"
+
+/*
+       ==========================================================================
+       Description:
+               association     state machine init,     including state transition and timer init
+       Parameters:
+               S -     pointer to the association state machine
+       ==========================================================================
+ */
+VOID   AironetStateMachineInit(
+       IN      PRTMP_ADAPTER           pAd,
+       IN      STATE_MACHINE           *S,
+       OUT     STATE_MACHINE_FUNC      Trans[])
+{
+       StateMachineInit(S,     Trans, MAX_AIRONET_STATE, MAX_AIRONET_MSG, (STATE_MACHINE_FUNC)Drop, AIRONET_IDLE, AIRONET_MACHINE_BASE);
+       StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_MSG, (STATE_MACHINE_FUNC)AironetMsgAction);
+       StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_SCAN_REQ, (STATE_MACHINE_FUNC)AironetRequestAction);
+       StateMachineSetAction(S, AIRONET_SCANNING, MT2_AIRONET_SCAN_DONE, (STATE_MACHINE_FUNC)AironetReportAction);
+}
+
+/*
+       ==========================================================================
+       Description:
+               This is state machine function.
+               When receiving EAPOL packets which is  for 802.1x key management.
+               Use     both in WPA, and WPAPSK case.
+               In this function, further dispatch to different functions according     to the received packet.  3 categories are :
+                 1.  normal 4-way pairwisekey and 2-way groupkey handshake
+                 2.  MIC error (Countermeasures attack)  report packet from STA.
+                 3.  Request for pairwise/group key update     from STA
+       Return:
+       ==========================================================================
+*/
+VOID   AironetMsgAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MLME_QUEUE_ELEM *Elem)
+{
+       USHORT                                                  Length;
+       UCHAR                                                   Index, i;
+       PUCHAR                                                  pData;
+       PAIRONET_RM_REQUEST_FRAME               pRMReq;
+       PRM_REQUEST_ACTION                              pReqElem;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("-----> AironetMsgAction\n"));
+
+       // 0. Get Aironet IAPP header first
+       pRMReq = (PAIRONET_RM_REQUEST_FRAME) &Elem->Msg[LENGTH_802_11];
+       pData  = (PUCHAR) &Elem->Msg[LENGTH_802_11];
+
+       // 1. Change endian format form network to little endian
+       Length = be2cpu16(pRMReq->IAPP.Length);
+
+       // 2.0 Sanity check, this should only happen when CCX 2.0 support is enabled
+       if (pAd->StaCfg.CCXEnable != TRUE)
+               return;
+
+       // 2.1 Radio measurement must be on
+       if (pAd->StaCfg.CCXControl.field.RMEnable != 1)
+               return;
+
+       // 2.2. Debug print all bit information
+       DBGPRINT(RT_DEBUG_TRACE, ("IAPP ID & Length %d\n", Length));
+       DBGPRINT(RT_DEBUG_TRACE, ("IAPP Type %x\n", pRMReq->IAPP.Type));
+       DBGPRINT(RT_DEBUG_TRACE, ("IAPP SubType %x\n", pRMReq->IAPP.SubType));
+       DBGPRINT(RT_DEBUG_TRACE, ("IAPP Dialog Token %x\n", pRMReq->IAPP.Token));
+       DBGPRINT(RT_DEBUG_TRACE, ("IAPP Activation Delay %x\n", pRMReq->Delay));
+       DBGPRINT(RT_DEBUG_TRACE, ("IAPP Measurement Offset %x\n", pRMReq->Offset));
+
+       // 3. Check IAPP frame type, it must be 0x32 for Cisco Aironet extension
+       if (pRMReq->IAPP.Type != AIRONET_IAPP_TYPE)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP type for Cisco Aironet extension\n"));
+               return;
+       }
+
+       // 4. Check IAPP frame subtype, it must be 0x01 for Cisco Aironet extension request.
+       //    Since we are acting as client only, we will disregards reply subtype.
+       if (pRMReq->IAPP.SubType != AIRONET_IAPP_SUBTYPE_REQUEST)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP subtype for Cisco Aironet extension\n"));
+               return;
+       }
+
+       // 5. Verify Destination MAC and Source MAC, both should be all zeros.
+       if (! MAC_ADDR_EQUAL(pRMReq->IAPP.DA, ZERO_MAC_ADDR))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP DA for Cisco Aironet extension, it's not Zero\n"));
+               return;
+       }
+
+       if (! MAC_ADDR_EQUAL(pRMReq->IAPP.SA, ZERO_MAC_ADDR))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP SA for Cisco Aironet extension, it's not Zero\n"));
+               return;
+       }
+
+       // 6. Reinit all report related fields
+       NdisZeroMemory(pAd->StaCfg.FrameReportBuf, 2048);
+       NdisZeroMemory(pAd->StaCfg.BssReportOffset, sizeof(USHORT) * MAX_LEN_OF_BSS_TABLE);
+       NdisZeroMemory(pAd->StaCfg.MeasurementRequest, sizeof(RM_REQUEST_ACTION) * 4);
+
+       // 7. Point to the start of first element report element
+       pAd->StaCfg.FrameReportLen   = LENGTH_802_11 + sizeof(AIRONET_IAPP_HEADER);
+       DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen));
+       pAd->StaCfg.LastBssIndex     = 0xff;
+       pAd->StaCfg.RMReqCnt         = 0;
+       pAd->StaCfg.ParallelReq      = FALSE;
+       pAd->StaCfg.ParallelDuration = 0;
+       pAd->StaCfg.ParallelChannel  = 0;
+       pAd->StaCfg.IAPPToken        = pRMReq->IAPP.Token;
+       pAd->StaCfg.CurrentRMReqIdx  = 0;
+       pAd->StaCfg.CLBusyBytes      = 0;
+       // Reset the statistics
+       for (i = 0; i < 8; i++)
+               pAd->StaCfg.RPIDensity[i] = 0;
+
+       Index = 0;
+
+       // 8. Save dialog token for report
+       pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token;
+
+       // Save Activation delay & measurement offset, Not really needed
+
+       // 9. Point to the first request element
+       pData += sizeof(AIRONET_RM_REQUEST_FRAME);
+       //    Length should exclude the CISCO Aironet SNAP header
+       Length -= (sizeof(AIRONET_RM_REQUEST_FRAME) - LENGTH_802_1_H);
+
+       // 10. Start Parsing the Measurement elements.
+       //    Be careful about multiple MR elements within one frames.
+       while (Length > 0)
+       {
+               pReqElem = (PRM_REQUEST_ACTION) pData;
+               switch (pReqElem->ReqElem.Eid)
+               {
+                       case IE_MEASUREMENT_REQUEST:
+                               // From the example, it seems we only need to support one request in one frame
+                               // There is no multiple request in one frame.
+                               // Besides, looks like we need to take care the measurement request only.
+                               // The measurement request is always 4 bytes.
+
+                               // Start parsing this type of request.
+                               // 0. Eid is IE_MEASUREMENT_REQUEST
+                               // 1. Length didn't include Eid and Length field, it always be 8.
+                               // 2. Measurement Token, we nned to save it for the corresponding report.
+                               // 3. Measurement Mode, Although there are definitions, but we din't see value other than
+                               //    0 from test specs examples.
+                               // 4. Measurement Type, this is what we need to do.
+                               switch (pReqElem->ReqElem.Type)
+                               {
+                                       case MSRN_TYPE_CHANNEL_LOAD_REQ:
+                                       case MSRN_TYPE_NOISE_HIST_REQ:
+                                       case MSRN_TYPE_BEACON_REQ:
+                                               // Check the Enable non-serving channel measurement control
+                                               if (pAd->StaCfg.CCXControl.field.DCRMEnable == 0)
+                                               {
+                                                       // Check channel before enqueue the action
+                                                       if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel)
+                                                               break;
+                                               }
+                                               else
+                                               {
+                                                       // If off channel measurement, check the TU duration limit
+                                                       if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel)
+                                                               if (pReqElem->Measurement.Duration > pAd->StaCfg.CCXControl.field.TuLimit)
+                                                                       break;
+                                               }
+
+                                               // Save requests and execute actions later
+                                               NdisMoveMemory(&pAd->StaCfg.MeasurementRequest[Index], pReqElem, sizeof(RM_REQUEST_ACTION));
+                                               Index += 1;
+                                               break;
+
+                                       case MSRN_TYPE_FRAME_REQ:
+                                               // Since it's option, we will support later
+                                               // FrameRequestAction(pAd, pData);
+                                               break;
+
+                                       default:
+                                               break;
+                               }
+
+                               // Point to next Measurement request
+                               pData  += sizeof(RM_REQUEST_ACTION);
+                               Length -= sizeof(RM_REQUEST_ACTION);
+                               break;
+
+                       // We accept request only, all others are dropped
+                       case IE_MEASUREMENT_REPORT:
+                       case IE_AP_TX_POWER:
+                       case IE_MEASUREMENT_CAPABILITY:
+                       default:
+                               return;
+               }
+       }
+
+       // 11. Update some flags and index
+       pAd->StaCfg.RMReqCnt = Index;
+
+       if (Index)
+       {
+               MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL);
+               RT28XX_MLME_HANDLER(pAd);
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<----- AironetMsgAction\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   AironetRequestAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MLME_QUEUE_ELEM *Elem)
+{
+       PRM_REQUEST_ACTION      pReq;
+
+       // 1. Point to next request element
+       pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
+
+       // 2. Parse measurement type and call appropriate functions
+       if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
+               // Channel Load measurement request
+               ChannelLoadRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+       else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
+               // Noise Histogram measurement request
+               NoiseHistRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+       else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ)
+               // Beacon measurement request
+               BeaconRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+       else
+               // Unknown. Do nothing and return, this should never happen
+               return;
+
+       // 3. Peek into the next request, if it's parallel, we will update the scan time to the largest one
+       if ((pAd->StaCfg.CurrentRMReqIdx + 1) < pAd->StaCfg.RMReqCnt)
+       {
+               pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx + 1];
+               // Check for parallel bit
+               if ((pReq->ReqElem.Mode & 0x01) && (pReq->Measurement.Channel == pAd->StaCfg.CCXScanChannel))
+               {
+                       // Update parallel mode request information
+                       pAd->StaCfg.ParallelReq = TRUE;
+                       pAd->StaCfg.CCXScanTime = ((pReq->Measurement.Duration > pAd->StaCfg.CCXScanTime) ?
+                       (pReq->Measurement.Duration) : (pAd->StaCfg.CCXScanTime));
+               }
+       }
+
+       // 4. Call RT28XX_MLME_HANDLER to execute the request mlme commands, Scan request is the only one used
+       RT28XX_MLME_HANDLER(pAd);
+
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Prepare channel load report action, special scan operation added
+               to support
+
+       Arguments:
+               pAd     Pointer to our adapter
+               pData           Start from element ID
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   ChannelLoadRequestAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Index)
+{
+       PRM_REQUEST_ACTION                              pReq;
+       MLME_SCAN_REQ_STRUCT                    ScanReq;
+       UCHAR                                                   ZeroSsid[32];
+       NDIS_STATUS                                             NStatus;
+       PUCHAR                                                  pOutBuffer = NULL;
+       PHEADER_802_11                                  pNullFrame;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction ----->\n"));
+
+       pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
+       NdisZeroMemory(ZeroSsid, 32);
+
+       // Prepare for special scan request
+       // The scan definition is different with our Active, Passive scan definition.
+       // For CCX2, Active means send out probe request with broadcast BSSID.
+       // Passive means no probe request sent, only listen to the beacons.
+       // The channel scanned is fixed as specified, no need to scan all channels.
+       // The scan wait time is specified in the request too.
+       // Passive scan Mode
+
+       // Control state machine is not idle, reject the request
+       if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
+               return;
+
+       // Fill out stuff for scan request
+       ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_CHANNEL_LOAD);
+       MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+
+       // Reset some internal control flags to make sure this scan works.
+       BssTableInit(&pAd->StaCfg.CCXBssTab);
+       pAd->StaCfg.ScanCnt        = 0;
+       pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
+       pAd->StaCfg.CCXScanTime    = pReq->Measurement.Duration;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel));
+
+       // If it's non serving channel scan, send out a null frame with PSM bit on.
+       if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
+       {
+               // Use MLME enqueue method
+               NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
+               if (NStatus     != NDIS_STATUS_SUCCESS)
+                       return;
+
+               pNullFrame = (PHEADER_802_11) pOutBuffer;;
+               // Make the power save Null frame with PSM bit on
+               MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
+               pNullFrame->Duration    = 0;
+               pNullFrame->FC.Type     = BTYPE_DATA;
+               pNullFrame->FC.PwrMgmt  = PWR_SAVE;
+
+               // Send using priority queue
+               MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
+               MlmeFreeMemory(pAd, pOutBuffer);
+               DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
+               RTMPusecDelay(5000);
+       }
+
+       pAd->StaCfg.CCXReqType     = MSRN_TYPE_CHANNEL_LOAD_REQ;
+       pAd->StaCfg.CLBusyBytes    = 0;
+       // Enable Rx with promiscuous reception
+       RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010);
+
+       // Set channel load measurement flag
+       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
+
+       pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction <-----\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Prepare noise histogram report action, special scan operation added
+               to support
+
+       Arguments:
+               pAd     Pointer to our adapter
+               pData           Start from element ID
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   NoiseHistRequestAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Index)
+{
+       PRM_REQUEST_ACTION                              pReq;
+       MLME_SCAN_REQ_STRUCT                    ScanReq;
+       UCHAR                                                   ZeroSsid[32], i;
+       NDIS_STATUS                                             NStatus;
+       PUCHAR                                                  pOutBuffer = NULL;
+       PHEADER_802_11                                  pNullFrame;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction ----->\n"));
+
+       pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
+       NdisZeroMemory(ZeroSsid, 32);
+
+       // Prepare for special scan request
+       // The scan definition is different with our Active, Passive scan definition.
+       // For CCX2, Active means send out probe request with broadcast BSSID.
+       // Passive means no probe request sent, only listen to the beacons.
+       // The channel scanned is fixed as specified, no need to scan all channels.
+       // The scan wait time is specified in the request too.
+       // Passive scan Mode
+
+       // Control state machine is not idle, reject the request
+       if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
+               return;
+
+       // Fill out stuff for scan request
+       ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_NOISE);
+       MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+
+       // Reset some internal control flags to make sure this scan works.
+       BssTableInit(&pAd->StaCfg.CCXBssTab);
+       pAd->StaCfg.ScanCnt        = 0;
+       pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
+       pAd->StaCfg.CCXScanTime    = pReq->Measurement.Duration;
+       pAd->StaCfg.CCXReqType     = MSRN_TYPE_NOISE_HIST_REQ;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel));
+
+       // If it's non serving channel scan, send out a null frame with PSM bit on.
+       if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
+       {
+               // Use MLME enqueue method
+               NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
+               if (NStatus     != NDIS_STATUS_SUCCESS)
+                       return;
+
+               pNullFrame = (PHEADER_802_11) pOutBuffer;
+               // Make the power save Null frame with PSM bit on
+               MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
+               pNullFrame->Duration    = 0;
+               pNullFrame->FC.Type     = BTYPE_DATA;
+               pNullFrame->FC.PwrMgmt  = PWR_SAVE;
+
+               // Send using priority queue
+               MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
+               MlmeFreeMemory(pAd, pOutBuffer);
+               DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
+               RTMPusecDelay(5000);
+       }
+
+       // Reset the statistics
+       for (i = 0; i < 8; i++)
+               pAd->StaCfg.RPIDensity[i] = 0;
+
+       // Enable Rx with promiscuous reception
+       RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010);
+
+       // Set channel load measurement flag
+       RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
+
+       pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction <-----\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Prepare Beacon report action, special scan operation added
+               to support
+
+       Arguments:
+               pAd     Pointer to our adapter
+               pData           Start from element ID
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   BeaconRequestAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Index)
+{
+       PRM_REQUEST_ACTION                              pReq;
+       NDIS_STATUS                                             NStatus;
+       PUCHAR                                                  pOutBuffer = NULL;
+       PHEADER_802_11                                  pNullFrame;
+       MLME_SCAN_REQ_STRUCT                    ScanReq;
+       UCHAR                                                   ZeroSsid[32];
+
+       DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction ----->\n"));
+
+       pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
+       NdisZeroMemory(ZeroSsid, 32);
+
+       // Prepare for special scan request
+       // The scan definition is different with our Active, Passive scan definition.
+       // For CCX2, Active means send out probe request with broadcast BSSID.
+       // Passive means no probe request sent, only listen to the beacons.
+       // The channel scanned is fixed as specified, no need to scan all channels.
+       // The scan wait time is specified in the request too.
+       if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_PASSIVE)
+       {
+               // Passive scan Mode
+               DBGPRINT(RT_DEBUG_TRACE, ("Passive Scan Mode!\n"));
+
+               // Control state machine is not idle, reject the request
+               if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
+                       return;
+
+               // Fill out stuff for scan request
+               ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_PASSIVE);
+               MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+               pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+
+               // Reset some internal control flags to make sure this scan works.
+               BssTableInit(&pAd->StaCfg.CCXBssTab);
+               pAd->StaCfg.ScanCnt        = 0;
+               pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
+               pAd->StaCfg.CCXScanTime    = pReq->Measurement.Duration;
+               pAd->StaCfg.CCXReqType     = MSRN_TYPE_BEACON_REQ;
+               DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration));
+
+               // If it's non serving channel scan, send out a null frame with PSM bit on.
+               if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
+               {
+                       // Use MLME enqueue method
+                       NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
+                       if (NStatus     != NDIS_STATUS_SUCCESS)
+                               return;
+
+                       pNullFrame = (PHEADER_802_11) pOutBuffer;
+                       // Make the power save Null frame with PSM bit on
+                       MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
+                       pNullFrame->Duration    = 0;
+                       pNullFrame->FC.Type     = BTYPE_DATA;
+                       pNullFrame->FC.PwrMgmt  = PWR_SAVE;
+
+                       // Send using priority queue
+                       MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
+                       MlmeFreeMemory(pAd, pOutBuffer);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
+                       RTMPusecDelay(5000);
+               }
+
+               pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
+       }
+       else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_ACTIVE)
+       {
+               // Active scan Mode
+               DBGPRINT(RT_DEBUG_TRACE, ("Active Scan Mode!\n"));
+
+               // Control state machine is not idle, reject the request
+               if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+                       return;
+
+               // Fill out stuff for scan request
+               ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_ACTIVE);
+               MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+               pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+
+               // Reset some internal control flags to make sure this scan works.
+               BssTableInit(&pAd->StaCfg.CCXBssTab);
+               pAd->StaCfg.ScanCnt        = 0;
+               pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
+               pAd->StaCfg.CCXScanTime    = pReq->Measurement.Duration;
+               pAd->StaCfg.CCXReqType     = MSRN_TYPE_BEACON_REQ;
+               DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration));
+
+               // If it's non serving channel scan, send out a null frame with PSM bit on.
+               if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
+               {
+                       // Use MLME enqueue method
+                       NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
+                       if (NStatus     != NDIS_STATUS_SUCCESS)
+                               return;
+
+                       pNullFrame = (PHEADER_802_11) pOutBuffer;
+                       // Make the power save Null frame with PSM bit on
+                       MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
+                       pNullFrame->Duration    = 0;
+                       pNullFrame->FC.Type     = BTYPE_DATA;
+                       pNullFrame->FC.PwrMgmt  = PWR_SAVE;
+
+                       // Send using priority queue
+                       MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
+                       MlmeFreeMemory(pAd, pOutBuffer);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
+                       RTMPusecDelay(5000);
+               }
+
+               pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
+       }
+       else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_BEACON_TABLE)
+       {
+               // Beacon report Mode, report all the APS in current bss table
+               DBGPRINT(RT_DEBUG_TRACE, ("Beacon Report Mode!\n"));
+
+               // Copy current BSS table to CCX table, we can omit this step later on.
+               NdisMoveMemory(&pAd->StaCfg.CCXBssTab, &pAd->ScanTab, sizeof(BSS_TABLE));
+
+               // Create beacon report from Bss table
+               AironetCreateBeaconReportFromBssTable(pAd);
+
+               // Set state to scanning
+               pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
+
+               // Enqueue report request
+               // Cisco scan request is finished, prepare beacon report
+               MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL);
+       }
+       else
+       {
+               // Wrong scan Mode
+               DBGPRINT(RT_DEBUG_TRACE, ("Wrong Scan Mode!\n"));
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction <-----\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   AironetReportAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MLME_QUEUE_ELEM *Elem)
+{
+       PRM_REQUEST_ACTION      pReq;
+       ULONG                           Now32;
+
+    NdisGetSystemUpTime(&Now32);
+       pAd->StaCfg.LastBeaconRxTime = Now32;
+
+       pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
+
+       DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction ----->\n"));
+
+       // 1. Parse measurement type and call appropriate functions
+       if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
+               // Channel Load measurement request
+               ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+       else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
+               // Noise Histogram measurement request
+               NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+       else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ)
+               // Beacon measurement request
+               BeaconReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+       else
+               // Unknown. Do nothing and return
+               ;
+
+       // 2. Point to the correct index of action element, start from 0
+       pAd->StaCfg.CurrentRMReqIdx++;
+
+       // 3. Check for parallel actions
+       if (pAd->StaCfg.ParallelReq == TRUE)
+       {
+               pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
+
+               // Process next action right away
+               if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
+                       // Channel Load measurement request
+                       ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+               else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
+                       // Noise Histogram measurement request
+                       NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+
+               pAd->StaCfg.ParallelReq = FALSE;
+               pAd->StaCfg.CurrentRMReqIdx++;
+       }
+
+       if (pAd->StaCfg.CurrentRMReqIdx >= pAd->StaCfg.RMReqCnt)
+       {
+               // 4. There is no more unprocessed measurement request, go for transmit this report
+               AironetFinalReportAction(pAd);
+               pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
+       }
+       else
+       {
+               pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
+
+               if (pReq->Measurement.Channel != pAd->CommonCfg.Channel)
+               {
+                       RTMPusecDelay(100000);
+               }
+
+               // 5. There are more requests to be measure
+               MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL);
+               RT28XX_MLME_HANDLER(pAd);
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction <-----\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   AironetFinalReportAction(
+       IN      PRTMP_ADAPTER   pAd)
+{
+       PUCHAR                                  pDest;
+       PAIRONET_IAPP_HEADER    pIAPP;
+       PHEADER_802_11                  pHeader;
+       UCHAR                                   AckRate = RATE_2;
+       USHORT                                  AckDuration = 0;
+       NDIS_STATUS                             NStatus;
+       PUCHAR                                  pOutBuffer = NULL;
+       ULONG                                   FrameLen = 0;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction ----->\n"));
+
+       // 0. Set up the frame pointer, Frame was inited at the end of message action
+       pDest = &pAd->StaCfg.FrameReportBuf[LENGTH_802_11];
+
+       // 1. Update report IAPP fields
+       pIAPP = (PAIRONET_IAPP_HEADER) pDest;
+
+       // 2. Copy Cisco SNAP header
+       NdisMoveMemory(pIAPP->CiscoSnapHeader, SNAP_AIRONET, LENGTH_802_1_H);
+
+       // 3. network order for this 16bit length
+       pIAPP->Length  = cpu2be16(pAd->StaCfg.FrameReportLen - LENGTH_802_11 - LENGTH_802_1_H);
+
+       // 3.1 sanity check the report length, ignore it if there is nothing to report
+       if (be2cpu16(pIAPP->Length) <= 18)
+               return;
+
+       // 4. Type must be 0x32
+       pIAPP->Type    = AIRONET_IAPP_TYPE;
+
+       // 5. SubType for report must be 0x81
+       pIAPP->SubType = AIRONET_IAPP_SUBTYPE_REPORT;
+
+       // 6. DA is not used and must be zero, although the whole frame was cleared at the start of function
+       //    We will do it again here. We can use BSSID instead
+       COPY_MAC_ADDR(pIAPP->DA, pAd->CommonCfg.Bssid);
+
+       // 7. SA is the client reporting which must be our MAC
+       COPY_MAC_ADDR(pIAPP->SA, pAd->CurrentAddress);
+
+       // 8. Copy the saved dialog token
+       pIAPP->Token = pAd->StaCfg.IAPPToken;
+
+       // 9. Make the Report frame 802.11 header
+       //    Reuse function in wpa.c
+       pHeader = (PHEADER_802_11) pAd->StaCfg.FrameReportBuf;
+       pAd->Sequence ++;
+       WpaMacHeaderInit(pAd, pHeader, 0, pAd->CommonCfg.Bssid);
+
+       // ACK size     is 14 include CRC, and its rate is based on real time information
+       AckRate     = pAd->CommonCfg.ExpectedACKRate[pAd->CommonCfg.MlmeRate];
+       AckDuration = RTMPCalcDuration(pAd, AckRate, 14);
+       pHeader->Duration = pAd->CommonCfg.Dsifs + AckDuration;
+
+       // Use MLME enqueue method
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if (NStatus     != NDIS_STATUS_SUCCESS)
+               return;
+
+       // 10. Prepare report frame with dynamic outbuffer. Just simply copy everything.
+       MakeOutgoingFrame(pOutBuffer,                       &FrameLen,
+                         pAd->StaCfg.FrameReportLen, pAd->StaCfg.FrameReportBuf,
+                             END_OF_ARGS);
+
+       // 11. Send using priority queue
+       MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction <-----\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   ChannelLoadReportAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Index)
+{
+       PMEASUREMENT_REPORT_ELEMENT     pReport;
+       PCHANNEL_LOAD_REPORT            pLoad;
+       PUCHAR                                          pDest;
+       UCHAR                                           CCABusyFraction;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction ----->\n"));
+
+       // Disable Rx with promiscuous reception, make it back to normal
+       RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification.
+
+       // 0. Setup pointer for processing beacon & probe response
+       pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
+       pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
+
+       // 1. Fill Measurement report element field.
+       pReport->Eid    = IE_MEASUREMENT_REPORT;
+       // Fixed Length at 9, not include Eid and length fields
+       pReport->Length = 9;
+       pReport->Token  = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token;
+       pReport->Mode   = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode;
+       pReport->Type   = MSRN_TYPE_CHANNEL_LOAD_REQ;
+
+       // 2. Fill channel report measurement data
+       pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
+       pLoad  = (PCHANNEL_LOAD_REPORT) pDest;
+       pLoad->Channel  = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel;
+       pLoad->Spare    = 0;
+       pLoad->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration;
+
+       // 3. Calculate the CCA Busy Fraction
+       //    (Bytes + ACK size) * 8 / Tx speed * 255 / 1000 / measurement duration, use 24 us Tx speed
+       //     =  (Bytes + ACK) / 12 / duration
+       //     9 is the good value for pAd->StaCfg.CLFactor
+       // CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 9 / pLoad->Duration);
+       CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / pAd->StaCfg.CLFactor / pLoad->Duration);
+       if (CCABusyFraction < 10)
+                       CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 3 / pLoad->Duration) + 1;
+
+       pLoad->CCABusy = CCABusyFraction;
+       DBGPRINT(RT_DEBUG_TRACE, ("CLBusyByte %ld, Duration %d, Result, %d\n", pAd->StaCfg.CLBusyBytes, pLoad->Duration, CCABusyFraction));
+
+       DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen));
+       pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(CHANNEL_LOAD_REPORT));
+       DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen));
+
+       // 4. Clear channel load measurement flag
+       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
+
+       // 5. reset to idle state
+       pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction <-----\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   NoiseHistReportAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Index)
+{
+       PMEASUREMENT_REPORT_ELEMENT     pReport;
+       PNOISE_HIST_REPORT                      pNoise;
+       PUCHAR                                          pDest;
+       UCHAR                                           i,NoiseCnt;
+       USHORT                                          TotalRPICnt, TotalRPISum;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction ----->\n"));
+
+       // 0. Disable Rx with promiscuous reception, make it back to normal
+       RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification.
+       // 1. Setup pointer for processing beacon & probe response
+       pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
+       pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
+
+       // 2. Fill Measurement report element field.
+       pReport->Eid    = IE_MEASUREMENT_REPORT;
+       // Fixed Length at 16, not include Eid and length fields
+       pReport->Length = 16;
+       pReport->Token  = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token;
+       pReport->Mode   = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode;
+       pReport->Type   = MSRN_TYPE_NOISE_HIST_REQ;
+
+       // 3. Fill noise histogram report measurement data
+       pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
+       pNoise  = (PNOISE_HIST_REPORT) pDest;
+       pNoise->Channel  = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel;
+       pNoise->Spare    = 0;
+       pNoise->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration;
+       // 4. Fill Noise histogram, the total RPI counts should be 0.4 * TU
+       //    We estimate 4000 normal packets received durning 10 seconds test.
+       //    Adjust it if required.
+       // 3 is a good value for pAd->StaCfg.NHFactor
+       // TotalRPICnt = pNoise->Duration * 3 / 10;
+       TotalRPICnt = pNoise->Duration * pAd->StaCfg.NHFactor / 10;
+       TotalRPISum = 0;
+
+       for (i = 0; i < 8; i++)
+       {
+               TotalRPISum += pAd->StaCfg.RPIDensity[i];
+               DBGPRINT(RT_DEBUG_TRACE, ("RPI %d Conuts %d\n", i, pAd->StaCfg.RPIDensity[i]));
+       }
+
+       // Double check if the counter is larger than our expectation.
+       // We will replace it with the total number plus a fraction.
+       if (TotalRPISum > TotalRPICnt)
+               TotalRPICnt = TotalRPISum + pNoise->Duration / 20;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Total RPI Conuts %d\n", TotalRPICnt));
+
+       // 5. Initialize noise count for the total summation of 0xff
+       NoiseCnt = 0;
+       for (i = 1; i < 8; i++)
+       {
+               pNoise->Density[i] = (UCHAR) (pAd->StaCfg.RPIDensity[i] * 255 / TotalRPICnt);
+               if ((pNoise->Density[i] == 0) && (pAd->StaCfg.RPIDensity[i] != 0))
+                       pNoise->Density[i]++;
+               NoiseCnt += pNoise->Density[i];
+               DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[%d]  = 0x%02x\n", i, pNoise->Density[i]));
+       }
+
+       // 6. RPI[0] represents the rest of counts
+       pNoise->Density[0] = 0xff - NoiseCnt;
+       DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[0]  = 0x%02x\n", pNoise->Density[0]));
+
+       pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(NOISE_HIST_REPORT));
+
+       // 7. Clear channel load measurement flag
+       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
+
+       // 8. reset to idle state
+       pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction <-----\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Prepare Beacon report action,
+
+       Arguments:
+               pAd     Pointer to our adapter
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   BeaconReportAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   Index)
+{
+       DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction ----->\n"));
+
+       // Looks like we don't have anything thing need to do here.
+       // All measurement report already finished in AddBeaconReport
+       // The length is in the FrameReportLen
+
+       // reset Beacon index for next beacon request
+       pAd->StaCfg.LastBssIndex = 0xff;
+
+       // reset to idle state
+       pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction <-----\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+               Index           Current BSSID in CCXBsstab entry index
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID   AironetAddBeaconReport(
+       IN      PRTMP_ADAPTER           pAd,
+       IN      ULONG                           Index,
+       IN      PMLME_QUEUE_ELEM        pElem)
+{
+       PVOID                                           pMsg;
+       PUCHAR                                          pSrc, pDest;
+       UCHAR                                           ReqIdx;
+       ULONG                                           MsgLen;
+       USHORT                                          Length;
+       PFRAME_802_11                           pFrame;
+       PMEASUREMENT_REPORT_ELEMENT     pReport;
+       PEID_STRUCT                             pEid;
+       PBEACON_REPORT                          pBeaconReport;
+       PBSS_ENTRY                                      pBss;
+
+       // 0. Setup pointer for processing beacon & probe response
+       pMsg   = pElem->Msg;
+       MsgLen = pElem->MsgLen;
+       pFrame = (PFRAME_802_11) pMsg;
+       pSrc   = pFrame->Octet;                         // Start from AP TSF
+       pBss   = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index];
+       ReqIdx = pAd->StaCfg.CurrentRMReqIdx;
+
+       // 1 Check the Index, if we already create this entry, only update the average RSSI
+       if ((Index <= pAd->StaCfg.LastBssIndex) && (pAd->StaCfg.LastBssIndex != 0xff))
+       {
+               pDest  = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.BssReportOffset[Index]];
+               // Point to bss report information
+               pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
+               pBeaconReport = (PBEACON_REPORT) pDest;
+
+               // Update Rx power, in dBm
+               // Get the original RSSI readback from BBP
+               pBeaconReport->RxPower += pAd->BbpRssiToDbmDelta;
+               // Average the Rssi reading
+               pBeaconReport->RxPower  = (pBeaconReport->RxPower + pBss->Rssi) / 2;
+               // Get to dBm format
+               pBeaconReport->RxPower -= pAd->BbpRssiToDbmDelta;
+
+               DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ",
+                       pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2],
+                       pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
+               DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld] Rssi %d, Avg Rssi %d\n", Index, (pBss->Rssi - pAd->BbpRssiToDbmDelta), pBeaconReport->RxPower - 256));
+               DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.BssReportOffset[Index]));
+
+               // Update other information here
+
+               // Done
+               return;
+       }
+
+       // 2. Update reported Index
+       pAd->StaCfg.LastBssIndex = Index;
+
+       // 3. Setup the buffer address for copying this BSSID into reporting frame
+       //    The offset should start after 802.11 header and report frame header.
+       pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
+
+       // 4. Save the start offset of each Bss in report frame
+       pAd->StaCfg.BssReportOffset[Index] = pAd->StaCfg.FrameReportLen;
+
+       // 5. Fill Measurement report fields
+       pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
+       pReport->Eid = IE_MEASUREMENT_REPORT;
+       pReport->Length = 0;
+       pReport->Token  = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token;
+       pReport->Mode   = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode;
+       pReport->Type   = MSRN_TYPE_BEACON_REQ;
+       Length          = sizeof(MEASUREMENT_REPORT_ELEMENT);
+       pDest          += sizeof(MEASUREMENT_REPORT_ELEMENT);
+
+       // 6. Start thebeacon report format
+       pBeaconReport = (PBEACON_REPORT) pDest;
+       pDest        += sizeof(BEACON_REPORT);
+       Length       += sizeof(BEACON_REPORT);
+
+       // 7. Copy Channel number
+       pBeaconReport->Channel        = pBss->Channel;
+       pBeaconReport->Spare          = 0;
+       pBeaconReport->Duration       = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration;
+       pBeaconReport->PhyType        = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS);
+       // 8. Rx power, in dBm
+       pBeaconReport->RxPower        = pBss->Rssi - pAd->BbpRssiToDbmDelta;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ",
+               pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2],
+               pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
+       DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld], Rssi %d\n", Index, pBeaconReport->RxPower - 256));
+       DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.FrameReportLen));
+
+       pBeaconReport->BeaconInterval = pBss->BeaconPeriod;
+       COPY_MAC_ADDR(pBeaconReport->BSSID, pFrame->Hdr.Addr3);
+       NdisMoveMemory(pBeaconReport->ParentTSF, pSrc, 4);
+       NdisMoveMemory(pBeaconReport->TargetTSF, &pElem->TimeStamp.u.LowPart, 4);
+       NdisMoveMemory(&pBeaconReport->TargetTSF[4], &pElem->TimeStamp.u.HighPart, 4);
+
+       // 9. Skip the beacon frame and offset to start of capabilityinfo since we already processed capabilityinfo
+       pSrc += (TIMESTAMP_LEN + 2);
+       pBeaconReport->CapabilityInfo = *(USHORT *)pSrc;
+
+       // 10. Point to start of element ID
+       pSrc += 2;
+       pEid = (PEID_STRUCT) pSrc;
+
+       // 11. Start process all variable Eid oayload and add the appropriate to the frame report
+       while (((PUCHAR) pEid + pEid->Len + 1) < ((PUCHAR) pFrame + MsgLen))
+       {
+               // Only limited EID are required to report for CCX 2. It includes SSID, Supported rate,
+               // FH paramenter set, DS parameter set, CF parameter set, IBSS parameter set,
+               // TIM (report first 4 bytes only, radio measurement capability
+               switch (pEid->Eid)
+               {
+                       case IE_SSID:
+                       case IE_SUPP_RATES:
+                       case IE_FH_PARM:
+                       case IE_DS_PARM:
+                       case IE_CF_PARM:
+                       case IE_IBSS_PARM:
+                               NdisMoveMemory(pDest, pEid, pEid->Len + 2);
+                               pDest  += (pEid->Len + 2);
+                               Length += (pEid->Len + 2);
+                               break;
+
+                       case IE_MEASUREMENT_CAPABILITY:
+                               // Since this IE is duplicated with WPA security IE, we has to do sanity check before
+                               // recognize it.
+                               // 1. It also has fixed 6 bytes IE length.
+                               if (pEid->Len != 6)
+                                       break;
+                               // 2. Check the Cisco Aironet OUI
+                               if (NdisEqualMemory(CISCO_OUI, (pSrc + 2), 3))
+                               {
+                                       // Matched, this is what we want
+                                       NdisMoveMemory(pDest, pEid, pEid->Len + 2);
+                                       pDest  += (pEid->Len + 2);
+                                       Length += (pEid->Len + 2);
+                               }
+                               break;
+
+                       case IE_TIM:
+                               if (pEid->Len > 4)
+                               {
+                                       // May truncate and report the first 4 bytes only, with the eid & len, total should be 6
+                                       NdisMoveMemory(pDest, pEid, 6);
+                                       pDest  += 6;
+                                       Length += 6;
+                               }
+                               else
+                               {
+                                       NdisMoveMemory(pDest, pEid, pEid->Len + 2);
+                                       pDest  += (pEid->Len + 2);
+                                       Length += (pEid->Len + 2);
+                               }
+                               break;
+
+                       default:
+                               break;
+               }
+               // 12. Move to next element ID
+               pSrc += (2 + pEid->Len);
+               pEid = (PEID_STRUCT) pSrc;
+       }
+
+       // 13. Update the length in the header, not include EID and length
+       pReport->Length = Length - 4;
+
+       // 14. Update the frame report buffer data length
+       pAd->StaCfg.FrameReportLen += Length;
+       DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+
+       Arguments:
+               Index           Current BSSID in CCXBsstab entry index
+
+       Return Value:
+
+       Note:
+
+       ========================================================================
+*/
+VOID   AironetCreateBeaconReportFromBssTable(
+       IN      PRTMP_ADAPTER           pAd)
+{
+       PMEASUREMENT_REPORT_ELEMENT     pReport;
+       PBEACON_REPORT                          pBeaconReport;
+       UCHAR                                           Index, ReqIdx;
+       USHORT                                          Length;
+       PUCHAR                                          pDest;
+       PBSS_ENTRY                                      pBss;
+
+       // 0. setup base pointer
+       ReqIdx = pAd->StaCfg.CurrentRMReqIdx;
+
+       for (Index = 0; Index < pAd->StaCfg.CCXBssTab.BssNr; Index++)
+       {
+               // 1. Setup the buffer address for copying this BSSID into reporting frame
+               //    The offset should start after 802.11 header and report frame header.
+               pDest  = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
+               pBss   = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index];
+               Length = 0;
+
+               // 2. Fill Measurement report fields
+               pReport         = (PMEASUREMENT_REPORT_ELEMENT) pDest;
+               pReport->Eid    = IE_MEASUREMENT_REPORT;
+               pReport->Length = 0;
+               pReport->Token  = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token;
+               pReport->Mode   = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode;
+               pReport->Type   = MSRN_TYPE_BEACON_REQ;
+               Length          = sizeof(MEASUREMENT_REPORT_ELEMENT);
+               pDest          += sizeof(MEASUREMENT_REPORT_ELEMENT);
+
+               // 3. Start the beacon report format
+               pBeaconReport = (PBEACON_REPORT) pDest;
+               pDest        += sizeof(BEACON_REPORT);
+               Length       += sizeof(BEACON_REPORT);
+
+               // 4. Copy Channel number
+               pBeaconReport->Channel        = pBss->Channel;
+               pBeaconReport->Spare          = 0;
+               pBeaconReport->Duration       = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration;
+               pBeaconReport->PhyType        = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS);
+               pBeaconReport->RxPower        = pBss->Rssi - pAd->BbpRssiToDbmDelta;
+               pBeaconReport->BeaconInterval = pBss->BeaconPeriod;
+               pBeaconReport->CapabilityInfo = pBss->CapabilityInfo;
+               COPY_MAC_ADDR(pBeaconReport->BSSID, pBss->Bssid);
+               NdisMoveMemory(pBeaconReport->ParentTSF, pBss->PTSF, 4);
+               NdisMoveMemory(pBeaconReport->TargetTSF, pBss->TTSF, 8);
+
+               // 5. Create SSID
+               *pDest++ = 0x00;
+               *pDest++ = pBss->SsidLen;
+               NdisMoveMemory(pDest, pBss->Ssid, pBss->SsidLen);
+               pDest  += pBss->SsidLen;
+               Length += (2 + pBss->SsidLen);
+
+               // 6. Create SupportRates
+               *pDest++ = 0x01;
+               *pDest++ = pBss->SupRateLen;
+               NdisMoveMemory(pDest, pBss->SupRate, pBss->SupRateLen);
+               pDest  += pBss->SupRateLen;
+               Length += (2 + pBss->SupRateLen);
+
+               // 7. DS Parameter
+               *pDest++ = 0x03;
+               *pDest++ = 1;
+               *pDest++ = pBss->Channel;
+               Length  += 3;
+
+               // 8. IBSS parameter if presents
+               if (pBss->BssType == BSS_ADHOC)
+               {
+                       *pDest++ = 0x06;
+                       *pDest++ = 2;
+                       *(PUSHORT) pDest = pBss->AtimWin;
+                       pDest   += 2;
+                       Length  += 4;
+               }
+
+               // 9. Update length field, not include EID and length
+               pReport->Length = Length - 4;
+
+               // 10. Update total frame size
+               pAd->StaCfg.FrameReportLen += Length;
+       }
+}
diff --git a/drivers/staging/rt2870/sta/assoc.c b/drivers/staging/rt2870/sta/assoc.c
new file mode 100644 (file)
index 0000000..a76dab5
--- /dev/null
@@ -0,0 +1,2039 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       assoc.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       John            2004-9-3                porting from RT2500
+*/
+#include "../rt_config.h"
+
+UCHAR  CipherWpaTemplate[] = {
+               0xdd,                                   // WPA IE
+               0x16,                                   // Length
+               0x00, 0x50, 0xf2, 0x01, // oui
+               0x01, 0x00,                             // Version
+               0x00, 0x50, 0xf2, 0x02, // Multicast
+               0x01, 0x00,                             // Number of unicast
+               0x00, 0x50, 0xf2, 0x02, // unicast
+               0x01, 0x00,                             // number of authentication method
+               0x00, 0x50, 0xf2, 0x01  // authentication
+               };
+
+UCHAR  CipherWpa2Template[] = {
+               0x30,                                   // RSN IE
+               0x14,                                   // Length
+               0x01, 0x00,                             // Version
+               0x00, 0x0f, 0xac, 0x02, // group cipher, TKIP
+               0x01, 0x00,                             // number of pairwise
+               0x00, 0x0f, 0xac, 0x02, // unicast
+               0x01, 0x00,                             // number of authentication method
+               0x00, 0x0f, 0xac, 0x02, // authentication
+               0x00, 0x00,                             // RSN capability
+               };
+
+UCHAR  Ccx2IeInfo[] = { 0x00, 0x40, 0x96, 0x03, 0x02};
+
+/*
+       ==========================================================================
+       Description:
+               association state machine init, including state transition and timer init
+       Parameters:
+               S - pointer to the association state machine
+
+       IRQL = PASSIVE_LEVEL
+
+       ==========================================================================
+ */
+VOID AssocStateMachineInit(
+       IN      PRTMP_ADAPTER   pAd,
+       IN  STATE_MACHINE *S,
+       OUT STATE_MACHINE_FUNC Trans[])
+{
+       StateMachineInit(S, Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG, (STATE_MACHINE_FUNC)Drop, ASSOC_IDLE, ASSOC_MACHINE_BASE);
+
+       // first column
+       StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)MlmeAssocReqAction);
+       StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)MlmeReassocReqAction);
+       StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)MlmeDisassocReqAction);
+       StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
+
+       // second column
+       StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
+       StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
+       StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
+       StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
+       StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction);
+       //
+       // Patch 3Com AP MOde:3CRWE454G72
+       // We send Assoc request frame to this AP, it always send Reassoc Rsp not Associate Rsp.
+       //
+       StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction);
+       StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_ASSOC_TIMEOUT, (STATE_MACHINE_FUNC)AssocTimeoutAction);
+
+       // third column
+       StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
+       StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
+       StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
+       StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
+       StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction);
+       //
+       // Patch, AP doesn't send Reassociate Rsp frame to Station.
+       //
+       StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction);
+       StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_REASSOC_TIMEOUT, (STATE_MACHINE_FUNC)ReassocTimeoutAction);
+
+       // fourth column
+       StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
+       StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
+       StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
+       StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
+       StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_DISASSOC_TIMEOUT, (STATE_MACHINE_FUNC)DisassocTimeoutAction);
+
+       // initialize the timer
+       RTMPInitTimer(pAd, &pAd->MlmeAux.AssocTimer, GET_TIMER_FUNCTION(AssocTimeout), pAd, FALSE);
+       RTMPInitTimer(pAd, &pAd->MlmeAux.ReassocTimer, GET_TIMER_FUNCTION(ReassocTimeout), pAd, FALSE);
+       RTMPInitTimer(pAd, &pAd->MlmeAux.DisassocTimer, GET_TIMER_FUNCTION(DisassocTimeout), pAd, FALSE);
+}
+
+/*
+       ==========================================================================
+       Description:
+               Association timeout procedure. After association timeout, this function
+               will be called and it will put a message into the MLME queue
+       Parameters:
+               Standard timer parameters
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AssocTimeout(IN PVOID SystemSpecific1,
+                                IN PVOID FunctionContext,
+                                IN PVOID SystemSpecific2,
+                                IN PVOID SystemSpecific3)
+{
+       RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+       // Do nothing if the driver is starting halt state.
+       // This might happen when timer already been fired before cancel timer with mlmehalt
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+               return;
+
+       MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_ASSOC_TIMEOUT, 0, NULL);
+       RT28XX_MLME_HANDLER(pAd);
+}
+
+/*
+       ==========================================================================
+       Description:
+               Reassociation timeout procedure. After reassociation timeout, this
+               function will be called and put a message into the MLME queue
+       Parameters:
+               Standard timer parameters
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID ReassocTimeout(IN PVOID SystemSpecific1,
+                                       IN PVOID FunctionContext,
+                                       IN PVOID SystemSpecific2,
+                                       IN PVOID SystemSpecific3)
+{
+       RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+       // Do nothing if the driver is starting halt state.
+       // This might happen when timer already been fired before cancel timer with mlmehalt
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+               return;
+
+       MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_REASSOC_TIMEOUT, 0, NULL);
+       RT28XX_MLME_HANDLER(pAd);
+}
+
+/*
+       ==========================================================================
+       Description:
+               Disassociation timeout procedure. After disassociation timeout, this
+               function will be called and put a message into the MLME queue
+       Parameters:
+               Standard timer parameters
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID DisassocTimeout(IN PVOID SystemSpecific1,
+                                       IN PVOID FunctionContext,
+                                       IN PVOID SystemSpecific2,
+                                       IN PVOID SystemSpecific3)
+{
+       RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+       // Do nothing if the driver is starting halt state.
+       // This might happen when timer already been fired before cancel timer with mlmehalt
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+               return;
+
+       MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_DISASSOC_TIMEOUT, 0, NULL);
+       RT28XX_MLME_HANDLER(pAd);
+}
+
+/*
+       ==========================================================================
+       Description:
+               mlme assoc req handling procedure
+       Parameters:
+               Adapter - Adapter pointer
+               Elem - MLME Queue Element
+       Pre:
+               the station has been authenticated and the following information is stored in the config
+                       -# SSID
+                       -# supported rates and their length
+                       -# listen interval (Adapter->StaCfg.default_listen_count)
+                       -# Transmit power  (Adapter->StaCfg.tx_power)
+       Post  :
+               -# An association request frame is generated and sent to the air
+               -# Association timer starts
+               -# Association state -> ASSOC_WAIT_RSP
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID MlmeAssocReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR                   ApAddr[6];
+       HEADER_802_11   AssocHdr;
+       UCHAR                   Ccx2Len = 5;
+       UCHAR                   WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
+       USHORT                  ListenIntv;
+       ULONG                   Timeout;
+       USHORT                  CapabilityInfo;
+       BOOLEAN                 TimerCancelled;
+       PUCHAR                  pOutBuffer = NULL;
+       NDIS_STATUS             NStatus;
+       ULONG                   FrameLen = 0;
+       ULONG                   tmp;
+       USHORT                  VarIesOffset;
+       UCHAR                   CkipFlag;
+       UCHAR                   CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH];
+       UCHAR                   AironetCkipIe = IE_AIRONET_CKIP;
+       UCHAR                   AironetCkipLen = CKIP_NEGOTIATION_LENGTH;
+       UCHAR                   AironetIPAddressIE = IE_AIRONET_IPADDRESS;
+       UCHAR                   AironetIPAddressLen = AIRONET_IPADDRESS_LENGTH;
+       UCHAR                   AironetIPAddressBuffer[AIRONET_IPADDRESS_LENGTH] = {0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00};
+       USHORT                  Status;
+
+       // Block all authentication request durning WPA block period
+       if (pAd->StaCfg.bBlockAssoc == TRUE)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block Assoc request durning WPA block period!\n"));
+               pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+               Status = MLME_STATE_MACHINE_REJECT;
+               MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+       }
+       // check sanity first
+       else if (MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv))
+       {
+               RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled);
+               COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr);
+
+               // Get an unused nonpaged memory
+               NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+               if (NStatus != NDIS_STATUS_SUCCESS)
+               {
+                       DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() allocate memory failed \n"));
+                       pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+                       Status = MLME_FAIL_NO_RESOURCE;
+                       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+                       return;
+               }
+
+               // Add by James 03/06/27
+               pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+               // Association don't need to report MAC address
+               pAd->StaCfg.AssocInfo.AvailableRequestFixedIEs =
+                       NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL;
+               pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities = CapabilityInfo;
+               pAd->StaCfg.AssocInfo.RequestFixedIEs.ListenInterval = ListenIntv;
+               // Only reassociate need this
+               //COPY_MAC_ADDR(pAd->StaCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr);
+               pAd->StaCfg.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+
+        NdisZeroMemory(pAd->StaCfg.ReqVarIEs, MAX_VIE_LEN);
+               // First add SSID
+               VarIesOffset = 0;
+               NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SsidIe, 1);
+               VarIesOffset += 1;
+               NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SsidLen, 1);
+               VarIesOffset += 1;
+               NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+               VarIesOffset += pAd->MlmeAux.SsidLen;
+
+               // Second add Supported rates
+               NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SupRateIe, 1);
+               VarIesOffset += 1;
+               NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SupRateLen, 1);
+               VarIesOffset += 1;
+               NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen);
+               VarIesOffset += pAd->MlmeAux.SupRateLen;
+               // End Add by James
+
+        if ((pAd->CommonCfg.Channel > 14) &&
+            (pAd->CommonCfg.bIEEE80211H == TRUE))
+            CapabilityInfo |= 0x0100;
+
+               DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send ASSOC request...\n"));
+               MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr);
+
+               // Build basic frame first
+               MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
+                                                 sizeof(HEADER_802_11),        &AssocHdr,
+                                                 2,                                            &CapabilityInfo,
+                                                 2,                                            &ListenIntv,
+                                                 1,                                            &SsidIe,
+                                                 1,                                            &pAd->MlmeAux.SsidLen,
+                                                 pAd->MlmeAux.SsidLen,         pAd->MlmeAux.Ssid,
+                                                 1,                                            &SupRateIe,
+                                                 1,                                            &pAd->MlmeAux.SupRateLen,
+                                                 pAd->MlmeAux.SupRateLen,  pAd->MlmeAux.SupRate,
+                                                 END_OF_ARGS);
+
+               if (pAd->MlmeAux.ExtRateLen != 0)
+               {
+                       MakeOutgoingFrame(pOutBuffer + FrameLen,    &tmp,
+                                                         1,                        &ExtRateIe,
+                                                         1,                        &pAd->MlmeAux.ExtRateLen,
+                                                         pAd->MlmeAux.ExtRateLen,  pAd->MlmeAux.ExtRate,
+                                                         END_OF_ARGS);
+                       FrameLen += tmp;
+               }
+
+#ifdef DOT11_N_SUPPORT
+               // HT
+               if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+               {
+                       ULONG TmpLen;
+                       UCHAR HtLen;
+                       UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
+                       if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE)
+                       {
+                               HtLen = SIZE_HT_CAP_IE + 4;
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
+                                                         1,                                &WpaIe,
+                                                         1,                                &HtLen,
+                                                         4,                                &BROADCOM[0],
+                                                        pAd->MlmeAux.HtCapabilityLen,          &pAd->MlmeAux.HtCapability,
+                                                         END_OF_ARGS);
+                       }
+                       else
+                       {
+#ifdef RT_BIG_ENDIAN
+                       HT_CAPABILITY_IE HtCapabilityTmp;
+#endif
+
+#ifndef RT_BIG_ENDIAN
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
+                                                         1,                                &HtCapIe,
+                                                         1,                                &pAd->MlmeAux.HtCapabilityLen,
+                                                        pAd->MlmeAux.HtCapabilityLen,          &pAd->MlmeAux.HtCapability,
+                                                         END_OF_ARGS);
+#else
+                NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE));
+                NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, pAd->MlmeAux.HtCapabilityLen);
+                       *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+                       *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+                       MakeOutgoingFrame(pOutBuffer + FrameLen,         &TmpLen,
+                                                               1,                           &HtCapIe,
+                                                               1,                           &pAd->MlmeAux.HtCapabilityLen,
+                                                               pAd->MlmeAux.HtCapabilityLen,&HtCapabilityTmp,
+                                                               END_OF_ARGS);
+#endif
+                       }
+                       FrameLen += TmpLen;
+               }
+#endif // DOT11_N_SUPPORT //
+
+               // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION
+               // Case I: (Aggregation + Piggy-Back)
+               // 1. user enable aggregation, AND
+               // 2. Mac support piggy-back
+               // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON
+               // Case II: (Aggregation)
+               // 1. user enable aggregation, AND
+               // 2. AP annouces it's AGGREGATION-capable in BEACON
+               if (pAd->CommonCfg.bAggregationCapable)
+               {
+                       if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3))
+                       {
+                               ULONG TmpLen;
+                               UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00};
+                               MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
+                                                                 9,                             RalinkIe,
+                                                                 END_OF_ARGS);
+                               FrameLen += TmpLen;
+                       }
+                       else if (pAd->MlmeAux.APRalinkIe & 0x00000001)
+                       {
+                               ULONG TmpLen;
+                               UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00};
+                               MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
+                                                                 9,                             RalinkIe,
+                                                                 END_OF_ARGS);
+                               FrameLen += TmpLen;
+                       }
+               }
+               else
+               {
+                       ULONG TmpLen;
+                       UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00};
+                       MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
+                                                         9,                                             RalinkIe,
+                                                         END_OF_ARGS);
+                       FrameLen += TmpLen;
+               }
+
+               if (pAd->MlmeAux.APEdcaParm.bValid)
+               {
+                       if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable)
+                       {
+                               QBSS_STA_INFO_PARM QosInfo;
+
+                               NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM));
+                               QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE;
+                               QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK;
+                               QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI;
+                               QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO;
+                               QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength;
+                               WmeIe[8] |= *(PUCHAR)&QosInfo;
+                       }
+                       else
+                       {
+                // The Parameter Set Count is set to Â¡Â§0¡¨ in the association request frames
+                // WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f);
+                       }
+
+                       MakeOutgoingFrame(pOutBuffer + FrameLen,    &tmp,
+                                                         9,                        &WmeIe[0],
+                                                         END_OF_ARGS);
+                       FrameLen += tmp;
+               }
+
+               //
+               // Let WPA(#221) Element ID on the end of this association frame.
+               // Otherwise some AP will fail on parsing Element ID and set status fail on Assoc Rsp.
+               // For example: Put Vendor Specific IE on the front of WPA IE.
+               // This happens on AP (Model No:Linksys WRK54G)
+               //
+               if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+            (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
+            (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+            (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)
+                       )
+            )
+               {
+                       UCHAR RSNIe = IE_WPA;
+
+                       if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
+                (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2))
+                       {
+                               RSNIe = IE_WPA2;
+                       }
+
+               RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0);
+
+            // Check for WPA PMK cache list
+                       if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)
+                       {
+                           INT     idx;
+                BOOLEAN FoundPMK = FALSE;
+                               // Search chched PMKID, append it if existed
+                               for (idx = 0; idx < PMKID_NO; idx++)
+                               {
+                                       if (NdisEqualMemory(ApAddr, &pAd->StaCfg.SavedPMK[idx].BSSID, 6))
+                                       {
+                                               FoundPMK = TRUE;
+                                               break;
+                                       }
+                               }
+
+                               if (FoundPMK)
+                               {
+                                       // Set PMK number
+                                       *(PUSHORT) &pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len] = 1;
+                                       NdisMoveMemory(&pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len + 2], &pAd->StaCfg.SavedPMK[idx].PMKID, 16);
+                    pAd->StaCfg.RSNIE_Len += 18;
+                               }
+                       }
+
+                       {
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,                &tmp,
+                                                       1,                              &RSNIe,
+                                               1,                              &pAd->StaCfg.RSNIE_Len,
+                                               pAd->StaCfg.RSNIE_Len,                  pAd->StaCfg.RSN_IE,
+                                               END_OF_ARGS);
+                       }
+
+                       FrameLen += tmp;
+
+                       {
+                   // Append Variable IE
+                   NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &RSNIe, 1);
+                   VarIesOffset += 1;
+                   NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->StaCfg.RSNIE_Len, 1);
+                   VarIesOffset += 1;
+                       }
+                       NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len);
+                       VarIesOffset += pAd->StaCfg.RSNIE_Len;
+
+                       // Set Variable IEs Length
+                       pAd->StaCfg.ReqVarIELen = VarIesOffset;
+               }
+
+               // We have update that at PeerBeaconAtJoinRequest()
+               CkipFlag = pAd->StaCfg.CkipFlag;
+               if (CkipFlag != 0)
+               {
+                       NdisZeroMemory(CkipNegotiationBuffer, CKIP_NEGOTIATION_LENGTH);
+                       CkipNegotiationBuffer[2] = 0x66;
+                       // Make it try KP & MIC, since we have to follow the result from AssocRsp
+                       CkipNegotiationBuffer[8] = 0x18;
+                       CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH - 1] = 0x22;
+                       CkipFlag = 0x18;
+
+                       MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
+                                               1,                                                              &AironetCkipIe,
+                                               1,                                                              &AironetCkipLen,
+                                               AironetCkipLen,                                 CkipNegotiationBuffer,
+                                               END_OF_ARGS);
+                       FrameLen += tmp;
+               }
+
+               // Add CCX v2 request if CCX2 admin state is on
+               if (pAd->StaCfg.CCXControl.field.Enable == 1)
+               {
+
+                       //
+                       // Add AironetIPAddressIE for Cisco CCX 2.X
+                       // Add CCX Version
+                       //
+                       MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+                                               1,                                                      &AironetIPAddressIE,
+                                               1,                                                      &AironetIPAddressLen,
+                                               AironetIPAddressLen,            AironetIPAddressBuffer,
+                                               1,                                                      &Ccx2Ie,
+                                               1,                                                      &Ccx2Len,
+                                               Ccx2Len,                                    Ccx2IeInfo,
+                                               END_OF_ARGS);
+                       FrameLen += tmp;
+
+                       //
+                       // Add CipherSuite CCKM or LeapTkip if setting.
+                       //
+#ifdef LEAP_SUPPORT
+                       if (LEAP_CCKM_ON(pAd))
+                       {
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
+                                               CipherSuiteCiscoCCKMLen,                CipherSuiteCiscoCCKM,
+                                               END_OF_ARGS);
+                               FrameLen += tmp;
+
+                               // Third add RSN
+                               NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, CipherSuiteCiscoCCKM, CipherSuiteCiscoCCKMLen); //Save CipherSuite
+                               VarIesOffset += CipherSuiteCiscoCCKMLen;
+                       }
+                       else if ((pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) && (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled))
+                       {
+                               MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+                                               CipherSuiteCCXTkipLen,      CipherSuiteCCXTkip,
+                                               END_OF_ARGS);
+                               FrameLen += tmp;
+
+                               // Third add RSN
+                               NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, CipherSuiteCCXTkip, CipherSuiteCCXTkipLen);
+                               VarIesOffset += CipherSuiteCCXTkipLen;
+                       }
+#endif // LEAP_SUPPORT //
+
+                       // Add by James 03/06/27
+                       // Set Variable IEs Length
+                       pAd->StaCfg.ReqVarIELen = VarIesOffset;
+                       pAd->StaCfg.AssocInfo.RequestIELength = VarIesOffset;
+
+                       // OffsetResponseIEs follow ReqVarIE
+                       pAd->StaCfg.AssocInfo.OffsetResponseIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + pAd->StaCfg.ReqVarIELen;
+                       // End Add by James
+               }
+
+
+               MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+               MlmeFreeMemory(pAd, pOutBuffer);
+
+               RTMPSetTimer(&pAd->MlmeAux.AssocTimer, Timeout);
+               pAd->Mlme.AssocMachine.CurrState = ASSOC_WAIT_RSP;
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() sanity check failed. BUG!!!!!! \n"));
+               pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+               Status = MLME_INVALID_FORMAT;
+               MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+       }
+
+}
+
+/*
+       ==========================================================================
+       Description:
+               mlme reassoc req handling procedure
+       Parameters:
+               Elem -
+       Pre:
+               -# SSID  (Adapter->StaCfg.ssid[])
+               -# BSSID (AP address, Adapter->StaCfg.bssid)
+               -# Supported rates (Adapter->StaCfg.supported_rates[])
+               -# Supported rates length (Adapter->StaCfg.supported_rates_len)
+               -# Tx power (Adapter->StaCfg.tx_power)
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID MlmeReassocReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR                   ApAddr[6];
+       HEADER_802_11   ReassocHdr;
+       UCHAR                   Ccx2Len = 5;
+       UCHAR                   WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
+       USHORT                  CapabilityInfo, ListenIntv;
+       ULONG                   Timeout;
+       ULONG                   FrameLen = 0;
+       BOOLEAN                 TimerCancelled;
+       NDIS_STATUS             NStatus;
+       ULONG                   tmp;
+       PUCHAR                  pOutBuffer = NULL;
+//CCX 2.X
+#ifdef LEAP_SUPPORT
+       UCHAR                   CkipFlag;
+       UCHAR                   CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH];
+       UCHAR                   AironetCkipIe = IE_AIRONET_CKIP;
+       UCHAR                   AironetCkipLen = CKIP_NEGOTIATION_LENGTH;
+       UCHAR                   AironetIPAddressIE = IE_AIRONET_IPADDRESS;
+       UCHAR                   AironetIPAddressLen = AIRONET_IPADDRESS_LENGTH;
+       UCHAR                   AironetIPAddressBuffer[AIRONET_IPADDRESS_LENGTH] = {0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00};
+       UCHAR                   AironetCCKMReassocIE = IE_AIRONET_CCKMREASSOC;
+       UCHAR                   AironetCCKMReassocLen = AIRONET_CCKMREASSOC_LENGTH;
+       UCHAR                   AironetCCKMReassocBuffer[AIRONET_CCKMREASSOC_LENGTH];
+       UCHAR                   AironetOUI[] = {0x00, 0x40, 0x96, 0x00};
+       UCHAR                   MICMN[16];
+       UCHAR                   CalcMicBuffer[80];
+       ULONG                   CalcMicBufferLen = 0;
+#endif // LEAP_SUPPORT //
+       USHORT                  Status;
+
+       // Block all authentication request durning WPA block period
+       if (pAd->StaCfg.bBlockAssoc == TRUE)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block ReAssoc request durning WPA block period!\n"));
+               pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+               Status = MLME_STATE_MACHINE_REJECT;
+               MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+       }
+       // the parameters are the same as the association
+       else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv))
+       {
+               RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled);
+
+               NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+               if(NStatus != NDIS_STATUS_SUCCESS)
+               {
+                       DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() allocate memory failed \n"));
+                       pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+                       Status = MLME_FAIL_NO_RESOURCE;
+                       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+                       return;
+               }
+
+               COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr);
+
+               // make frame, use bssid as the AP address??
+               DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send RE-ASSOC request...\n"));
+               MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0, ApAddr, ApAddr);
+               MakeOutgoingFrame(pOutBuffer,               &FrameLen,
+                                                 sizeof(HEADER_802_11),    &ReassocHdr,
+                                                 2,                        &CapabilityInfo,
+                                                 2,                        &ListenIntv,
+                                                 MAC_ADDR_LEN,             ApAddr,
+                                                 1,                        &SsidIe,
+                                                 1,                        &pAd->MlmeAux.SsidLen,
+                                                 pAd->MlmeAux.SsidLen,     pAd->MlmeAux.Ssid,
+                                                 1,                        &SupRateIe,
+                                                 1,                                            &pAd->MlmeAux.SupRateLen,
+                                                 pAd->MlmeAux.SupRateLen,  pAd->MlmeAux.SupRate,
+                                                 END_OF_ARGS);
+
+               if (pAd->MlmeAux.ExtRateLen != 0)
+               {
+                       MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
+                                                         1,                            &ExtRateIe,
+                                                         1,                            &pAd->MlmeAux.ExtRateLen,
+                                                         pAd->MlmeAux.ExtRateLen,          pAd->MlmeAux.ExtRate,
+                                                         END_OF_ARGS);
+                       FrameLen += tmp;
+               }
+
+               if (pAd->MlmeAux.APEdcaParm.bValid)
+               {
+                       if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable)
+                       {
+                               QBSS_STA_INFO_PARM QosInfo;
+
+                               NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM));
+                               QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE;
+                               QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK;
+                               QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI;
+                               QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO;
+                               QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength;
+                               WmeIe[8] |= *(PUCHAR)&QosInfo;
+                       }
+
+                       MakeOutgoingFrame(pOutBuffer + FrameLen,    &tmp,
+                                                         9,                        &WmeIe[0],
+                                                         END_OF_ARGS);
+                       FrameLen += tmp;
+               }
+
+#ifdef DOT11_N_SUPPORT
+               // HT
+               if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+               {
+                       ULONG TmpLen;
+                       UCHAR HtLen;
+                       UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
+                       if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE)
+                       {
+                               HtLen = SIZE_HT_CAP_IE + 4;
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
+                                                         1,                                &WpaIe,
+                                                         1,                                &HtLen,
+                                                         4,                                &BROADCOM[0],
+                                                        pAd->MlmeAux.HtCapabilityLen,          &pAd->MlmeAux.HtCapability,
+                                                         END_OF_ARGS);
+                       }
+                       else
+                       {
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
+                                                         1,                                &HtCapIe,
+                                                         1,                                &pAd->MlmeAux.HtCapabilityLen,
+                                                        pAd->MlmeAux.HtCapabilityLen,          &pAd->MlmeAux.HtCapability,
+                                                         END_OF_ARGS);
+                       }
+                       FrameLen += TmpLen;
+               }
+#endif // DOT11_N_SUPPORT //
+
+               // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION
+               // Case I: (Aggregation + Piggy-Back)
+               // 1. user enable aggregation, AND
+               // 2. Mac support piggy-back
+               // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON
+               // Case II: (Aggregation)
+               // 1. user enable aggregation, AND
+               // 2. AP annouces it's AGGREGATION-capable in BEACON
+               if (pAd->CommonCfg.bAggregationCapable)
+               {
+                       if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3))
+                       {
+                               ULONG TmpLen;
+                               UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00};
+                               MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
+                                                                 9,                             RalinkIe,
+                                                                 END_OF_ARGS);
+                               FrameLen += TmpLen;
+                       }
+                       else if (pAd->MlmeAux.APRalinkIe & 0x00000001)
+                       {
+                               ULONG TmpLen;
+                               UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00};
+                               MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
+                                                                 9,                             RalinkIe,
+                                                                 END_OF_ARGS);
+                               FrameLen += TmpLen;
+                       }
+               }
+               else
+               {
+                       ULONG TmpLen;
+                       UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x04, 0x00, 0x00, 0x00};
+                       MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
+                                                         9,                                             RalinkIe,
+                                                         END_OF_ARGS);
+                       FrameLen += TmpLen;
+               }
+#ifdef LEAP_SUPPORT
+               if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE))
+               {
+                       CkipFlag = pAd->StaCfg.CkipFlag;        // We have update that at PeerBeaconAtJoinRequest()
+                       if (CkipFlag != 0)
+                       {
+                               NdisZeroMemory(CkipNegotiationBuffer, CKIP_NEGOTIATION_LENGTH);
+                               CkipNegotiationBuffer[2] = 0x66;
+                               // Make it try KP & MIC, since we have to follow the result from AssocRsp
+                               CkipNegotiationBuffer[8] = 0x18;
+                               CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH - 1] = 0x22;
+
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,            &tmp,
+                                                                       1,                              &AironetCkipIe,
+                                                                       1,                              &AironetCkipLen,
+                                                                       AironetCkipLen,                 CkipNegotiationBuffer,
+                                                                       END_OF_ARGS);
+                               FrameLen += tmp;
+                       }
+
+                       MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+                                                       1,                              &AironetIPAddressIE,
+                                                       1,                              &AironetIPAddressLen,
+                                                       AironetIPAddressLen,            AironetIPAddressBuffer,
+                                                       END_OF_ARGS);
+                       FrameLen += tmp;
+
+                       //
+                       // The RN is incremented before each reassociation request.
+                       //
+                       pAd->StaCfg.CCKMRN++;
+                       //
+                       // Calculate MIC = hmac-md5(krk, STA-ID|BSSID|RSNIE|TSF|RN);
+                       //
+                       COPY_MAC_ADDR(CalcMicBuffer, pAd->CurrentAddress);
+                       CalcMicBufferLen = MAC_ADDR_LEN;
+                       COPY_MAC_ADDR(CalcMicBuffer + CalcMicBufferLen, pAd->MlmeAux.Bssid);
+                       CalcMicBufferLen += MAC_ADDR_LEN;
+                       NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, CipherSuiteCiscoCCKM, CipherSuiteCiscoCCKMLen);
+                       CalcMicBufferLen += CipherSuiteCiscoCCKMLen;
+                       NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, (PUCHAR) &pAd->StaCfg.CCKMBeaconAtJoinTimeStamp, sizeof(pAd->StaCfg.CCKMBeaconAtJoinTimeStamp));
+                       CalcMicBufferLen += sizeof(pAd->StaCfg.CCKMBeaconAtJoinTimeStamp);
+                       NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, (PUCHAR)&pAd->StaCfg.CCKMRN, sizeof(pAd->StaCfg.CCKMRN));
+                       CalcMicBufferLen += sizeof(pAd->StaCfg.CCKMRN);
+                       hmac_md5(pAd->StaCfg.KRK, LEN_EAP_MICK, CalcMicBuffer, CalcMicBufferLen, MICMN);
+
+                       //
+                       // fill up CCKM reassociation request element
+                       //
+                       NdisMoveMemory(AironetCCKMReassocBuffer, AironetOUI, 4);
+                       NdisMoveMemory(AironetCCKMReassocBuffer + 4, (PUCHAR)&pAd->StaCfg.CCKMBeaconAtJoinTimeStamp, 8);
+                       NdisMoveMemory(AironetCCKMReassocBuffer + 12, (PUCHAR) &pAd->StaCfg.CCKMRN, 4);
+                       NdisMoveMemory(AironetCCKMReassocBuffer +16, MICMN, 8);
+
+                       MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+                                                       1,                      &AironetCCKMReassocIE,
+                                                       1,                      &AironetCCKMReassocLen,
+                                                       AironetCCKMReassocLen,  AironetCCKMReassocBuffer,
+                                                       END_OF_ARGS);
+                       FrameLen += tmp;
+
+                       MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+                                                       CipherSuiteCiscoCCKMLen,CipherSuiteCiscoCCKM,
+                                                       END_OF_ARGS);
+                       FrameLen += tmp;
+               }
+#endif // LEAP_SUPPORT //
+
+               // Add CCX v2 request if CCX2 admin state is on
+               if (pAd->StaCfg.CCXControl.field.Enable == 1)
+               {
+                       //
+                       // Add CCX Version
+                       //
+                       MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+                                               1,                                                      &Ccx2Ie,
+                                               1,                                                      &Ccx2Len,
+                                               Ccx2Len,                                    Ccx2IeInfo,
+                                               END_OF_ARGS);
+                       FrameLen += tmp;
+               }
+
+               MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+               MlmeFreeMemory(pAd, pOutBuffer);
+
+               RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout); /* in mSec */
+               pAd->Mlme.AssocMachine.CurrState = REASSOC_WAIT_RSP;
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() sanity check failed. BUG!!!! \n"));
+               pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+               Status = MLME_INVALID_FORMAT;
+               MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+               Upper layer issues disassoc request
+       Parameters:
+               Elem -
+
+       IRQL = PASSIVE_LEVEL
+
+       ==========================================================================
+ */
+VOID MlmeDisassocReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       PMLME_DISASSOC_REQ_STRUCT pDisassocReq;
+       HEADER_802_11         DisassocHdr;
+       PHEADER_802_11        pDisassocHdr;
+       PUCHAR                pOutBuffer = NULL;
+       ULONG                 FrameLen = 0;
+       NDIS_STATUS           NStatus;
+       BOOLEAN               TimerCancelled;
+       ULONG                 Timeout = 0;
+       USHORT                Status;
+
+#ifdef QOS_DLS_SUPPORT
+       // send DLS-TEAR_DOWN message,
+       if (pAd->CommonCfg.bDLSCapable)
+       {
+               UCHAR i;
+
+               // tear down local dls table entry
+               for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+               {
+                       if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+                       {
+                               RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+                               pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
+                               pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                       }
+               }
+
+               // tear down peer dls table entry
+               for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+               {
+                       if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+                       {
+                               RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+                               pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+                               pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                       }
+               }
+       }
+#endif // QOS_DLS_SUPPORT //
+
+       // skip sanity check
+       pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT)(Elem->Msg);
+
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if (NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - MlmeDisassocReqAction() allocate memory failed\n"));
+               pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+               Status = MLME_FAIL_NO_RESOURCE;
+               MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
+               return;
+       }
+
+
+
+       RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &TimerCancelled);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send DISASSOC request[BSSID::%02x:%02x:%02x:%02x:%02x:%02x (Reason=%d)\n",
+                               pDisassocReq->Addr[0], pDisassocReq->Addr[1], pDisassocReq->Addr[2],
+                               pDisassocReq->Addr[3], pDisassocReq->Addr[4], pDisassocReq->Addr[5], pDisassocReq->Reason));
+       MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr);       // patch peap ttls switching issue
+       MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+                                         sizeof(HEADER_802_11),&DisassocHdr,
+                                         2,                    &pDisassocReq->Reason,
+                                         END_OF_ARGS);
+       MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+
+       // To patch Instance and Buffalo(N) AP
+       // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine
+       // Therefore, we send both of them.
+       pDisassocHdr = (PHEADER_802_11)pOutBuffer;
+       pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH;
+       MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       pAd->StaCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING;
+       COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pDisassocReq->Addr);
+
+       RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); /* in mSec */
+       pAd->Mlme.AssocMachine.CurrState = DISASSOC_WAIT_RSP;
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+    if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+       {
+        union iwreq_data    wrqu;
+        //send disassociate event to wpa_supplicant
+        memset(&wrqu, 0, sizeof(wrqu));
+        wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
+        wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+    }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+    {
+        union iwreq_data    wrqu;
+        memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+        wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+    }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+}
+
+/*
+       ==========================================================================
+       Description:
+               peer sends assoc rsp back
+       Parameters:
+               Elme - MLME message containing the received frame
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID PeerAssocRspAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT        CapabilityInfo, Status, Aid;
+       UCHAR         SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen;
+       UCHAR         ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen;
+       UCHAR         Addr2[MAC_ADDR_LEN];
+       BOOLEAN       TimerCancelled;
+       UCHAR         CkipFlag;
+       EDCA_PARM     EdcaParm;
+       HT_CAPABILITY_IE                HtCapability;
+       ADD_HT_INFO_IE          AddHtInfo;      // AP might use this additional ht info IE
+       UCHAR                   HtCapabilityLen;
+       UCHAR                   AddHtInfoLen;
+       UCHAR                   NewExtChannelOffset = 0xff;
+
+       if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen,
+               &HtCapability,&AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag))
+       {
+               // The frame is for me ?
+               if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status));
+#ifdef DOT11_N_SUPPORT
+                       DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n",Elem->Wcid, pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
+#endif // DOT11_N_SUPPORT //
+                       RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled);
+                       if(Status == MLME_SUCCESS)
+                       {
+                               UCHAR                   MaxSupportedRateIn500Kbps = 0;
+                               UCHAR                   idx;
+
+                               // supported rates array may not be sorted. sort it and find the maximum rate
+                           for (idx=0; idx<SupRateLen; idx++)
+                           {
+                               if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f))
+                                   MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f;
+                           }
+
+                               for (idx=0; idx<ExtRateLen; idx++)
+                           {
+                               if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f))
+                                   MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f;
+                           }
+                               // go to procedure listed on page 376
+                               AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen,
+                                       &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo);
+
+                               StaAddMacTableEntry(pAd, &pAd->MacTab.Content[BSSID_WCID], MaxSupportedRateIn500Kbps, &HtCapability, HtCapabilityLen, CapabilityInfo);
+
+                               pAd->StaCfg.CkipFlag = CkipFlag;
+                               if (CkipFlag & 0x18)
+                               {
+                                       NdisZeroMemory(pAd->StaCfg.TxSEQ, 4);
+                                       NdisZeroMemory(pAd->StaCfg.RxSEQ, 4);
+                                       NdisZeroMemory(pAd->StaCfg.CKIPMIC, 4);
+                                       pAd->StaCfg.GIV[0] = RandomByte(pAd);
+                                       pAd->StaCfg.GIV[1] = RandomByte(pAd);
+                                       pAd->StaCfg.GIV[2] = RandomByte(pAd);
+                                       pAd->StaCfg.bCkipOn = TRUE;
+                                       DBGPRINT(RT_DEBUG_TRACE, ("<CCX> pAd->StaCfg.CkipFlag = 0x%02x\n", pAd->StaCfg.CkipFlag));
+                               }
+                       }
+                       else
+                       {
+                               // Faile on Association, we need to check the status code
+                               // Is that a Rogue AP?
+#ifdef LEAP_SUPPORT
+                               if ((pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) && (Status == MLME_ALG_NOT_SUPPORT))
+                               { //Possibly Rogue AP
+                                       RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, pAd->MlmeAux.Bssid, LEAP_REASON_INVALID_AUTH);
+                               }
+#endif // LEAP_SUPPORT //
+                       }
+                       pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+                       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+               }
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerAssocRspAction() sanity check fail\n"));
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+               peer sends reassoc rsp
+       Parametrs:
+               Elem - MLME message cntaining the received frame
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID PeerReassocRspAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT      CapabilityInfo;
+       USHORT      Status;
+       USHORT      Aid;
+       UCHAR       SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen;
+       UCHAR       ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen;
+       UCHAR       Addr2[MAC_ADDR_LEN];
+       UCHAR       CkipFlag;
+       BOOLEAN     TimerCancelled;
+       EDCA_PARM   EdcaParm;
+       HT_CAPABILITY_IE                HtCapability;
+       ADD_HT_INFO_IE          AddHtInfo;      // AP might use this additional ht info IE
+       UCHAR                   HtCapabilityLen;
+       UCHAR                   AddHtInfoLen;
+       UCHAR                   NewExtChannelOffset = 0xff;
+
+       if(PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen,
+                                                               &HtCapability,  &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag))
+       {
+               if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) // The frame is for me ?
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - receive REASSOC_RSP to me (status=%d)\n", Status));
+                       RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled);
+
+                       if(Status == MLME_SUCCESS)
+                       {
+                               // go to procedure listed on page 376
+                               AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen,
+                                        &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+                if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+                {
+                    union iwreq_data    wrqu;
+
+                    SendAssocIEsToWpaSupplicant(pAd);
+                    memset(&wrqu, 0, sizeof(wrqu));
+                    wrqu.data.flags = RT_ASSOC_EVENT_FLAG;
+                    wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+                }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+                {
+                    union iwreq_data    wrqu;
+                    wext_notify_event_assoc(pAd);
+
+                    memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+                    memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
+                    wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+                }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+                       }
+
+                       //
+                       // Cisco Leap CCKM supported Re-association.
+                       //
+#ifdef LEAP_SUPPORT
+                       if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE))
+                       {
+                               if (CCKMAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen) == TRUE)
+                               {
+                                       pAd->StaCfg.CkipFlag = CkipFlag;
+                                       if (CkipFlag & 0x18)
+                                       {
+                                               NdisZeroMemory(pAd->StaCfg.TxSEQ, 4);
+                                               NdisZeroMemory(pAd->StaCfg.RxSEQ, 4);
+                                               NdisZeroMemory(pAd->StaCfg.CKIPMIC, 4);
+                                               pAd->StaCfg.GIV[0] = RandomByte(pAd);
+                                               pAd->StaCfg.GIV[1] = RandomByte(pAd);
+                                               pAd->StaCfg.GIV[2] = RandomByte(pAd);
+                                               pAd->StaCfg.bCkipOn = TRUE;
+                                               DBGPRINT(RT_DEBUG_TRACE, ("<CCX> pAd->StaCfg.CkipFlag = 0x%02x\n", pAd->StaCfg.CkipFlag));
+                                       }
+
+                                       pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+                                       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+                               }
+                               else
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - CCKMAssocRspSanity() sanity check fail\n"));
+                               }
+                       }
+                       else
+#endif // LEAP_SUPPORT //
+                       {
+                               // CkipFlag is no use for reassociate
+                               pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+                               MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+                       }
+               }
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerReassocRspAction() sanity check fail\n"));
+       }
+
+}
+
+/*
+       ==========================================================================
+       Description:
+               procedures on IEEE 802.11/1999 p.376
+       Parametrs:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AssocPostProc(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR pAddr2,
+       IN USHORT CapabilityInfo,
+       IN USHORT Aid,
+       IN UCHAR SupRate[],
+       IN UCHAR SupRateLen,
+       IN UCHAR ExtRate[],
+       IN UCHAR ExtRateLen,
+       IN PEDCA_PARM pEdcaParm,
+       IN HT_CAPABILITY_IE             *pHtCapability,
+       IN UCHAR HtCapabilityLen,
+       IN ADD_HT_INFO_IE               *pAddHtInfo)    // AP might use this additional ht info IE
+{
+       ULONG Idx;
+
+       pAd->MlmeAux.BssType = BSS_INFRA;
+       COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pAddr2);
+       pAd->MlmeAux.Aid = Aid;
+       pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
+#ifdef DOT11_N_SUPPORT
+       // Some HT AP might lost WMM IE. We add WMM ourselves. beacuase HT requires QoS on.
+       if ((HtCapabilityLen > 0) && (pEdcaParm->bValid == FALSE))
+       {
+               pEdcaParm->bValid = TRUE;
+               pEdcaParm->Aifsn[0] = 3;
+               pEdcaParm->Aifsn[1] = 7;
+               pEdcaParm->Aifsn[2] = 2;
+               pEdcaParm->Aifsn[3] = 2;
+
+               pEdcaParm->Cwmin[0] = 4;
+               pEdcaParm->Cwmin[1] = 4;
+               pEdcaParm->Cwmin[2] = 3;
+               pEdcaParm->Cwmin[3] = 2;
+
+               pEdcaParm->Cwmax[0] = 10;
+               pEdcaParm->Cwmax[1] = 10;
+               pEdcaParm->Cwmax[2] = 4;
+               pEdcaParm->Cwmax[3] = 3;
+
+               pEdcaParm->Txop[0]  = 0;
+               pEdcaParm->Txop[1]  = 0;
+               pEdcaParm->Txop[2]  = 96;
+               pEdcaParm->Txop[3]  = 48;
+
+       }
+#endif // DOT11_N_SUPPORT //
+
+       NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
+
+       // filter out un-supported rates
+       pAd->MlmeAux.SupRateLen = SupRateLen;
+       NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
+       RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
+
+       // filter out un-supported rates
+       pAd->MlmeAux.ExtRateLen = ExtRateLen;
+       NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
+       RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
+
+#ifdef DOT11_N_SUPPORT
+       if (HtCapabilityLen > 0)
+       {
+               RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo);
+       }
+       DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===>  AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n", pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
+
+       DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===>    (Mmps=%d, AmsduSize=%d, )\n",
+               pAd->MacTab.Content[BSSID_WCID].MmpsMode, pAd->MacTab.Content[BSSID_WCID].AMsduSize));
+#endif // DOT11_N_SUPPORT //
+
+       // Set New WPA information
+       Idx = BssTableSearch(&pAd->ScanTab, pAddr2, pAd->MlmeAux.Channel);
+       if (Idx == BSS_NOT_FOUND)
+       {
+               DBGPRINT_ERR(("ASSOC - Can't find BSS after receiving Assoc response\n"));
+       }
+       else
+       {
+               // Init variable
+               pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = 0;
+               NdisZeroMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, MAX_LEN_OF_RSNIE);
+
+               // Store appropriate RSN_IE for WPA SM negotiation later
+               if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAd->ScanTab.BssEntry[Idx].VarIELen != 0))
+               {
+                       PUCHAR              pVIE;
+                       USHORT              len;
+                       PEID_STRUCT         pEid;
+
+                       pVIE = pAd->ScanTab.BssEntry[Idx].VarIEs;
+                       len      = pAd->ScanTab.BssEntry[Idx].VarIELen;
+
+                       while (len > 0)
+                       {
+                               pEid = (PEID_STRUCT) pVIE;
+                               // For WPA/WPAPSK
+                               if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
+                                       && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+                               {
+                                       NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2));
+                                       pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA SM negotiation \n"));
+                               }
+                               // For WPA2/WPA2PSK
+                               else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
+                                       && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+                               {
+                                       NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2));
+                                       pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA2 SM negotiation \n"));
+                               }
+
+                               pVIE += (pEid->Len + 2);
+                               len  -= (pEid->Len + 2);
+                       }
+               }
+
+               if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0)
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> no RSN_IE \n"));
+               }
+               else
+               {
+                       hex_dump("RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len);
+               }
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+               left part of IEEE 802.11/1999 p.374
+       Parameters:
+               Elem - MLME message containing the received frame
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID PeerDisassocAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR         Addr2[MAC_ADDR_LEN];
+       USHORT        Reason;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction()\n"));
+       if(PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() Reason = %d\n", Reason));
+               if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, Addr2))
+               {
+
+                       if (pAd->CommonCfg.bWirelessEvent)
+                       {
+                               RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+                       }
+
+
+#ifdef LEAP_SUPPORT
+                       if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+                       {
+                               // Cisco_LEAP has start a timer
+                               // We should cancel it if using LEAP
+                               RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &TimerCancelled);
+                               //Check is it mach the LEAP Authentication failed as possible a Rogue AP
+                               //on it's PortSecured not equal to WPA_802_1X_PORT_SECURED while process the Association.
+                               if ((pAd->Mlme.LeapMachine.CurrState != LEAP_IDLE) && (pAd->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED))
+                               {
+                                       RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_AUTH_TIMEOUT);
+                               }
+                       }
+#endif // LEAP_SUPPORT //
+                       //
+                       // Get Current System time and Turn on AdjacentAPReport
+                       //
+                       NdisGetSystemUpTime(&pAd->StaCfg.CCXAdjacentAPLinkDownTime);
+                       pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
+                       LinkDown(pAd, TRUE);
+                       pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+            if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+                       {
+                union iwreq_data    wrqu;
+                //send disassociate event to wpa_supplicant
+                memset(&wrqu, 0, sizeof(wrqu));
+                wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
+                wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+            }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+            {
+                union iwreq_data    wrqu;
+                memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+                wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+            }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+               }
+       }
+       else
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() sanity check fail\n"));
+       }
+
+}
+
+/*
+       ==========================================================================
+       Description:
+               what the state machine will do after assoc timeout
+       Parameters:
+               Elme -
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID AssocTimeoutAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT  Status;
+       DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - AssocTimeoutAction\n"));
+       pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+       Status = MLME_REJ_TIMEOUT;
+       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+}
+
+/*
+       ==========================================================================
+       Description:
+               what the state machine will do after reassoc timeout
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID ReassocTimeoutAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT  Status;
+       DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - ReassocTimeoutAction\n"));
+       pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+       Status = MLME_REJ_TIMEOUT;
+       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+}
+
+/*
+       ==========================================================================
+       Description:
+               what the state machine will do after disassoc timeout
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID DisassocTimeoutAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT  Status;
+       DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - DisassocTimeoutAction\n"));
+       pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+       Status = MLME_SUCCESS;
+       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
+}
+
+VOID InvalidStateWhenAssoc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT  Status;
+       DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenAssoc(state=%ld), reset ASSOC state machine\n",
+               pAd->Mlme.AssocMachine.CurrState));
+       pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+       Status = MLME_STATE_MACHINE_REJECT;
+       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+}
+
+VOID InvalidStateWhenReassoc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT Status;
+       DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenReassoc(state=%ld), reset ASSOC state machine\n",
+               pAd->Mlme.AssocMachine.CurrState));
+       pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+       Status = MLME_STATE_MACHINE_REJECT;
+       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+}
+
+VOID InvalidStateWhenDisassociate(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT Status;
+       DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenDisassoc(state=%ld), reset ASSOC state machine\n",
+               pAd->Mlme.AssocMachine.CurrState));
+       pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+       Status = MLME_STATE_MACHINE_REJECT;
+       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
+}
+
+/*
+       ==========================================================================
+       Description:
+               right part of IEEE 802.11/1999 page 374
+       Note:
+               This event should never cause ASSOC state machine perform state
+               transition, and has no relationship with CNTL machine. So we separate
+               this routine as a service outside of ASSOC state transition table.
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID Cls3errAction(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR        pAddr)
+{
+       HEADER_802_11         DisassocHdr;
+       PHEADER_802_11        pDisassocHdr;
+       PUCHAR                pOutBuffer = NULL;
+       ULONG                 FrameLen = 0;
+       NDIS_STATUS           NStatus;
+       USHORT                Reason = REASON_CLS3ERR;
+
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if (NStatus != NDIS_STATUS_SUCCESS)
+               return;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Class 3 Error, Send DISASSOC frame\n"));
+       MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAddr, pAd->CommonCfg.Bssid);  // patch peap ttls switching issue
+       MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+                                         sizeof(HEADER_802_11),&DisassocHdr,
+                                         2,                    &Reason,
+                                         END_OF_ARGS);
+       MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+
+       // To patch Instance and Buffalo(N) AP
+       // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine
+       // Therefore, we send both of them.
+       pDisassocHdr = (PHEADER_802_11)pOutBuffer;
+       pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH;
+       MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       pAd->StaCfg.DisassocReason = REASON_CLS3ERR;
+       COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pAddr);
+}
+
+ /*
+        ==========================================================================
+        Description:
+                Switch between WEP and CKIP upon new association up.
+        Parameters:
+
+        IRQL = DISPATCH_LEVEL
+
+        ==========================================================================
+  */
+VOID SwitchBetweenWepAndCkip(
+       IN PRTMP_ADAPTER pAd)
+{
+       int            i;
+       SHAREDKEY_MODE_STRUC  csr1;
+
+       // if KP is required. change the CipherAlg in hardware shard key table from WEP
+       // to CKIP. else remain as WEP
+       if (pAd->StaCfg.bCkipOn && (pAd->StaCfg.CkipFlag & 0x10))
+       {
+               // modify hardware key table so that MAC use correct algorithm to decrypt RX
+               RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word);
+               if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP64)
+                       csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP64;
+               else if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP128)
+                       csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP128;
+
+               if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP64)
+                       csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP64;
+               else if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP128)
+                       csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP128;
+
+               if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP64)
+                       csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP64;
+               else if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP128)
+                       csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP128;
+
+               if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP64)
+                       csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP64;
+               else if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP128)
+                       csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP128;
+               RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word);
+               DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg]));
+
+               // modify software key table so that driver can specify correct algorithm in TXD upon TX
+               for (i=0; i<SHARE_KEY_NUM; i++)
+               {
+                       if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_WEP64)
+                               pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP64;
+                       else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_WEP128)
+                               pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP128;
+               }
+       }
+
+       // else if KP NOT inused. change the CipherAlg in hardware shard key table from CKIP
+       // to WEP.
+       else
+       {
+               // modify hardware key table so that MAC use correct algorithm to decrypt RX
+               RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word);
+               if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP64)
+                       csr1.field.Bss0Key0CipherAlg = CIPHER_WEP64;
+               else if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP128)
+                       csr1.field.Bss0Key0CipherAlg = CIPHER_WEP128;
+
+               if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP64)
+                       csr1.field.Bss0Key1CipherAlg = CIPHER_WEP64;
+               else if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP128)
+                       csr1.field.Bss0Key1CipherAlg = CIPHER_WEP128;
+
+               if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP64)
+                       csr1.field.Bss0Key2CipherAlg = CIPHER_WEP64;
+               else if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP128)
+                       csr1.field.Bss0Key2CipherAlg = CIPHER_WEP128;
+
+               if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP64)
+                       csr1.field.Bss0Key3CipherAlg = CIPHER_WEP64;
+               else if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP128)
+                       csr1.field.Bss0Key3CipherAlg = CIPHER_WEP128;
+
+               // modify software key table so that driver can specify correct algorithm in TXD upon TX
+               for (i=0; i<SHARE_KEY_NUM; i++)
+               {
+                       if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_CKIP64)
+                               pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP64;
+                       else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_CKIP128)
+                               pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP128;
+               }
+
+               //
+               // On WPA-NONE, must update CipherAlg.
+               // Because the OID_802_11_WEP_STATUS was been set after OID_802_11_ADD_KEY
+               // and CipherAlg will be CIPHER_NONE by Windows ZeroConfig.
+               // So we need to update CipherAlg after connect.
+               //
+               if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+               {
+                       for (i = 0; i < SHARE_KEY_NUM; i++)
+                       {
+                               if (pAd->SharedKey[BSS0][i].KeyLen != 0)
+                               {
+                                       if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)
+                                       {
+                                               pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_TKIP;
+                                       }
+                                       else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+                                       {
+                                               pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_AES;
+                                       }
+                               }
+                               else
+                               {
+                                       pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE;
+                               }
+                       }
+
+                       csr1.field.Bss0Key0CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
+                       csr1.field.Bss0Key1CipherAlg = pAd->SharedKey[BSS0][1].CipherAlg;
+                       csr1.field.Bss0Key2CipherAlg = pAd->SharedKey[BSS0][2].CipherAlg;
+                       csr1.field.Bss0Key3CipherAlg = pAd->SharedKey[BSS0][3].CipherAlg;
+               }
+               RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word);
+               DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg]));
+       }
+}
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+VOID    SendAssocIEsToWpaSupplicant(
+    IN  PRTMP_ADAPTER pAd)
+{
+    union iwreq_data    wrqu;
+    unsigned char custom[IW_CUSTOM_MAX] = {0};
+
+    if ((pAd->StaCfg.ReqVarIELen + 17) <= IW_CUSTOM_MAX)
+    {
+        sprintf(custom, "ASSOCINFO_ReqIEs=");
+           NdisMoveMemory(custom+17, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen);
+           memset(&wrqu, 0, sizeof(wrqu));
+        wrqu.data.length = pAd->StaCfg.ReqVarIELen + 17;
+        wrqu.data.flags = RT_REQIE_EVENT_FLAG;
+        wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom);
+
+        memset(&wrqu, 0, sizeof(wrqu));
+        wrqu.data.flags = RT_ASSOCINFO_EVENT_FLAG;
+        wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+    }
+    else
+        DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen + 17 > MAX_CUSTOM_LEN\n"));
+
+    return;
+}
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+int wext_notify_event_assoc(
+       IN  RTMP_ADAPTER *pAd)
+{
+    union iwreq_data    wrqu;
+    char custom[IW_CUSTOM_MAX] = {0};
+
+#if WIRELESS_EXT > 17
+    if (pAd->StaCfg.ReqVarIELen <= IW_CUSTOM_MAX)
+    {
+        wrqu.data.length = pAd->StaCfg.ReqVarIELen;
+        memcpy(custom, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen);
+        wireless_send_event(pAd->net_dev, IWEVASSOCREQIE, &wrqu, custom);
+    }
+    else
+        DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen > MAX_CUSTOM_LEN\n"));
+#else
+    if (((pAd->StaCfg.ReqVarIELen*2) + 17) <= IW_CUSTOM_MAX)
+    {
+        UCHAR   idx;
+        wrqu.data.length = (pAd->StaCfg.ReqVarIELen*2) + 17;
+        sprintf(custom, "ASSOCINFO(ReqIEs=");
+        for (idx=0; idx<pAd->StaCfg.ReqVarIELen; idx++)
+                sprintf(custom, "%s%02x", custom, pAd->StaCfg.ReqVarIEs[idx]);
+        wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom);
+    }
+    else
+        DBGPRINT(RT_DEBUG_TRACE, ("(pAd->StaCfg.ReqVarIELen*2) + 17 > MAX_CUSTOM_LEN\n"));
+#endif
+
+       return 0;
+
+}
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+
+BOOLEAN StaAddMacTableEntry(
+       IN  PRTMP_ADAPTER               pAd,
+       IN  PMAC_TABLE_ENTRY    pEntry,
+       IN  UCHAR                               MaxSupportedRateIn500Kbps,
+       IN  HT_CAPABILITY_IE    *pHtCapability,
+       IN  UCHAR                               HtCapabilityLen,
+       IN  USHORT                      CapabilityInfo)
+{
+       UCHAR            MaxSupportedRate = RATE_11;
+
+       if (ADHOC_ON(pAd))
+               CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
+
+       switch (MaxSupportedRateIn500Kbps)
+    {
+        case 108: MaxSupportedRate = RATE_54;   break;
+        case 96:  MaxSupportedRate = RATE_48;   break;
+        case 72:  MaxSupportedRate = RATE_36;   break;
+        case 48:  MaxSupportedRate = RATE_24;   break;
+        case 36:  MaxSupportedRate = RATE_18;   break;
+        case 24:  MaxSupportedRate = RATE_12;   break;
+        case 18:  MaxSupportedRate = RATE_9;    break;
+        case 12:  MaxSupportedRate = RATE_6;    break;
+        case 22:  MaxSupportedRate = RATE_11;   break;
+        case 11:  MaxSupportedRate = RATE_5_5;  break;
+        case 4:   MaxSupportedRate = RATE_2;    break;
+        case 2:   MaxSupportedRate = RATE_1;    break;
+        default:  MaxSupportedRate = RATE_11;   break;
+    }
+
+    if ((pAd->CommonCfg.PhyMode == PHY_11G) && (MaxSupportedRate < RATE_FIRST_OFDM_RATE))
+        return FALSE;
+
+#ifdef DOT11_N_SUPPORT
+       // 11n only
+       if (((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))&& (HtCapabilityLen == 0))
+               return FALSE;
+#endif // DOT11_N_SUPPORT //
+
+       if (!pEntry)
+        return FALSE;
+
+       NdisAcquireSpinLock(&pAd->MacTabLock);
+       if (pEntry)
+       {
+               pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+               if ((MaxSupportedRate < RATE_FIRST_OFDM_RATE) ||
+                       (pAd->CommonCfg.PhyMode == PHY_11B))
+               {
+                       pEntry->RateLen = 4;
+                       if (MaxSupportedRate >= RATE_FIRST_OFDM_RATE)
+                               MaxSupportedRate = RATE_11;
+               }
+               else
+                       pEntry->RateLen = 12;
+
+               pEntry->MaxHTPhyMode.word = 0;
+               pEntry->MinHTPhyMode.word = 0;
+               pEntry->HTPhyMode.word = 0;
+               pEntry->MaxSupportedRate = MaxSupportedRate;
+               if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
+               {
+                       pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
+                       pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+                       pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
+                       pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+                       pEntry->HTPhyMode.field.MODE = MODE_CCK;
+                       pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+               }
+               else
+               {
+                       pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
+                       pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+                       pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
+                       pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+                       pEntry->HTPhyMode.field.MODE = MODE_OFDM;
+                       pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+               }
+               pEntry->CapabilityInfo = CapabilityInfo;
+               CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE);
+               CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE);
+       }
+
+#ifdef DOT11_N_SUPPORT
+       // If this Entry supports 802.11n, upgrade to HT rate.
+       if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+       {
+               UCHAR   j, bitmask; //k,bitmask;
+               CHAR    i;
+
+               if (ADHOC_ON(pAd))
+                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
+               if ((pHtCapability->HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
+               {
+                       pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
+               }
+               else
+               {
+                       pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+                       pAd->MacTab.fAnyStationNonGF = TRUE;
+                       pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
+               }
+
+               if ((pHtCapability->HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
+               {
+                       pEntry->MaxHTPhyMode.field.BW= BW_40;
+                       pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pHtCapability->HtCapInfo.ShortGIfor40));
+               }
+               else
+               {
+                       pEntry->MaxHTPhyMode.field.BW = BW_20;
+                       pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(pHtCapability->HtCapInfo.ShortGIfor20));
+                       pAd->MacTab.fAnyStation20Only = TRUE;
+               }
+
+               // 3*3
+               if (pAd->MACVersion >= RALINK_2883_VERSION && pAd->MACVersion < RALINK_3070_VERSION)
+                       pEntry->MaxHTPhyMode.field.TxBF = pAd->CommonCfg.RegTransmitSetting.field.TxBF;
+
+               // find max fixed rate
+               for (i=23; i>=0; i--) // 3*3
+               {
+                       j = i/8;
+                       bitmask = (1<<(i-(j*8)));
+                       if ((pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j] & bitmask) && (pHtCapability->MCSSet[j] & bitmask))
+                       {
+                               pEntry->MaxHTPhyMode.field.MCS = i;
+                               break;
+                       }
+                       if (i==0)
+                               break;
+               }
+
+
+               if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
+               {
+                       if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
+                       {
+                               // Fix MCS as HT Duplicated Mode
+                               pEntry->MaxHTPhyMode.field.BW = 1;
+                               pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+                               pEntry->MaxHTPhyMode.field.STBC = 0;
+                               pEntry->MaxHTPhyMode.field.ShortGI = 0;
+                               pEntry->MaxHTPhyMode.field.MCS = 32;
+                       }
+                       else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
+                       {
+                               // STA supports fixed MCS
+                               pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+                       }
+               }
+
+               pEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
+               pEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity;
+               pEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor;
+               pEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs;
+               pEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize;
+               pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+
+               if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE))
+                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED);
+               if (pHtCapability->HtCapInfo.ShortGIfor20)
+                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
+               if (pHtCapability->HtCapInfo.ShortGIfor40)
+                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
+               if (pHtCapability->HtCapInfo.TxSTBC)
+                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
+               if (pHtCapability->HtCapInfo.RxSTBC)
+                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
+               if (pHtCapability->ExtHtCapInfo.PlusHTC)
+                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
+               if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
+                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
+               if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03)
+                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
+       }
+       else
+       {
+               pAd->MacTab.fAnyStationIsLegacy = TRUE;
+       }
+
+       NdisMoveMemory(&pEntry->HTCapability, pHtCapability, sizeof(HT_CAPABILITY_IE));
+#endif // DOT11_N_SUPPORT //
+
+       pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+       pEntry->CurrTxRate = pEntry->MaxSupportedRate;
+
+       // Set asic auto fall back
+       if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
+       {
+               PUCHAR                                  pTable;
+               UCHAR                                   TableSize = 0;
+
+               MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
+               pEntry->bAutoTxRateSwitch = TRUE;
+       }
+       else
+       {
+               pEntry->HTPhyMode.field.MODE    = pAd->StaCfg.HTPhyMode.field.MODE;
+               pEntry->HTPhyMode.field.MCS     = pAd->StaCfg.HTPhyMode.field.MCS;
+               pEntry->bAutoTxRateSwitch = FALSE;
+
+               // If the legacy mode is set, overwrite the transmit setting of this entry.
+               RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
+       }
+
+       pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+       pEntry->Sst = SST_ASSOC;
+       pEntry->AuthState = AS_AUTH_OPEN;
+       pEntry->AuthMode = pAd->StaCfg.AuthMode;
+       pEntry->WepStatus = pAd->StaCfg.WepStatus;
+
+       NdisReleaseSpinLock(&pAd->MacTabLock);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+    if (pAd->StaCfg.WpaSupplicantUP)
+    {
+        union iwreq_data    wrqu;
+
+        SendAssocIEsToWpaSupplicant(pAd);
+        memset(&wrqu, 0, sizeof(wrqu));
+        wrqu.data.flags = RT_ASSOC_EVENT_FLAG;
+        wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+    }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+    {
+        union iwreq_data    wrqu;
+        wext_notify_event_assoc(pAd);
+
+        memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+        memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
+        wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+    }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+       return TRUE;
+}
+
+
diff --git a/drivers/staging/rt2870/sta/auth.c b/drivers/staging/rt2870/sta/auth.c
new file mode 100644 (file)
index 0000000..73fb8d6
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       auth.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       John            2004-9-3                porting from RT2500
+*/
+#include "../rt_config.h"
+
+/*
+    ==========================================================================
+    Description:
+        authenticate state machine init, including state transition and timer init
+    Parameters:
+        Sm - pointer to the auth state machine
+    Note:
+        The state machine looks like this
+
+                        AUTH_REQ_IDLE           AUTH_WAIT_SEQ2                   AUTH_WAIT_SEQ4
+    MT2_MLME_AUTH_REQ   mlme_auth_req_action    invalid_state_when_auth          invalid_state_when_auth
+    MT2_PEER_AUTH_EVEN  drop                    peer_auth_even_at_seq2_action    peer_auth_even_at_seq4_action
+    MT2_AUTH_TIMEOUT    Drop                    auth_timeout_action              auth_timeout_action
+
+       IRQL = PASSIVE_LEVEL
+
+    ==========================================================================
+ */
+
+void AuthStateMachineInit(
+    IN PRTMP_ADAPTER pAd,
+    IN STATE_MACHINE *Sm,
+    OUT STATE_MACHINE_FUNC Trans[])
+{
+    StateMachineInit(Sm, Trans, MAX_AUTH_STATE, MAX_AUTH_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_REQ_IDLE, AUTH_MACHINE_BASE);
+
+    // the first column
+    StateMachineSetAction(Sm, AUTH_REQ_IDLE, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)MlmeAuthReqAction);
+
+    // the second column
+    StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth);
+    StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq2Action);
+    StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction);
+
+    // the third column
+    StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth);
+    StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq4Action);
+    StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction);
+
+       RTMPInitTimer(pAd, &pAd->MlmeAux.AuthTimer, GET_TIMER_FUNCTION(AuthTimeout), pAd, FALSE);
+}
+
+/*
+    ==========================================================================
+    Description:
+        function to be executed at timer thread when auth timer expires
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID AuthTimeout(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3)
+{
+    RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+    DBGPRINT(RT_DEBUG_TRACE,("AUTH - AuthTimeout\n"));
+
+       // Do nothing if the driver is starting halt state.
+       // This might happen when timer already been fired before cancel timer with mlmehalt
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+               return;
+
+       // send a de-auth to reset AP's state machine (Patch AP-Dir635)
+       if (pAd->Mlme.AuthMachine.CurrState == AUTH_WAIT_SEQ2)
+               Cls2errAction(pAd, pAd->MlmeAux.Bssid);
+
+
+    MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_AUTH_TIMEOUT, 0, NULL);
+    RT28XX_MLME_HANDLER(pAd);
+}
+
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID MlmeAuthReqAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+    UCHAR              Addr[6];
+    USHORT             Alg, Seq, Status;
+    ULONG              Timeout;
+    HEADER_802_11      AuthHdr;
+    BOOLEAN            TimerCancelled;
+    NDIS_STATUS        NStatus;
+    PUCHAR             pOutBuffer = NULL;
+    ULONG              FrameLen = 0;
+
+       // Block all authentication request durning WPA block period
+       if (pAd->StaCfg.bBlockAssoc == TRUE)
+       {
+        DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Block Auth request durning WPA block period!\n"));
+        pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+        Status = MLME_STATE_MACHINE_REJECT;
+        MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+       }
+    else if(MlmeAuthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr, &Timeout, &Alg))
+    {
+        // reset timer
+        RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
+        COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr);
+        pAd->MlmeAux.Alg  = Alg;
+        Seq = 1;
+        Status = MLME_SUCCESS;
+
+        NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+        if(NStatus != NDIS_STATUS_SUCCESS)
+        {
+            DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", Alg));
+            pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+            Status = MLME_FAIL_NO_RESOURCE;
+            MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+            return;
+        }
+
+        DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#1 (Alg=%d)...\n", Alg));
+        MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->MlmeAux.Bssid);
+        MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+                          sizeof(HEADER_802_11),&AuthHdr,
+                          2,                    &Alg,
+                          2,                    &Seq,
+                          2,                    &Status,
+                          END_OF_ARGS);
+        MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+        RTMPSetTimer(&pAd->MlmeAux.AuthTimer, Timeout);
+        pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2;
+    }
+    else
+    {
+        DBGPRINT_ERR(("AUTH - MlmeAuthReqAction() sanity check failed\n"));
+        pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+        Status = MLME_INVALID_FORMAT;
+        MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+    }
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID PeerAuthRspAtSeq2Action(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+    UCHAR         Addr2[MAC_ADDR_LEN];
+    USHORT        Seq, Status, RemoteStatus, Alg;
+    UCHAR         ChlgText[CIPHER_TEXT_LEN];
+    UCHAR         CyperChlgText[CIPHER_TEXT_LEN + 8 + 8];
+    UCHAR         Element[2];
+    HEADER_802_11 AuthHdr;
+    BOOLEAN       TimerCancelled;
+    PUCHAR        pOutBuffer = NULL;
+    NDIS_STATUS   NStatus;
+    ULONG         FrameLen = 0;
+    USHORT        Status2;
+
+    if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
+    {
+        if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2)
+        {
+            DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status));
+            RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
+
+            if (Status == MLME_SUCCESS)
+            {
+                // Authentication Mode "LEAP" has allow for CCX 1.X
+                if ((pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen)
+#ifdef LEAP_SUPPORT
+                                       || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+#endif // LEAP_SUPPORT //
+                               )
+                {
+                    pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+#ifdef LEAP_SUPPORT
+                    pAd->Mlme.LeapMachine.CurrState = LEAP_IDLE;
+#endif // LEAP_SUPPORT //
+                    MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+                }
+                else
+                {
+                    // 2. shared key, need to be challenged
+                    Seq++;
+                    RemoteStatus = MLME_SUCCESS;
+
+                                       // Get an unused nonpaged memory
+                    NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+                    if(NStatus != NDIS_STATUS_SUCCESS)
+                    {
+                        DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n"));
+                        pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+                        Status2 = MLME_FAIL_NO_RESOURCE;
+                        MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2);
+                        return;
+                    }
+
+                    DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n"));
+                    MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid);
+                    AuthHdr.FC.Wep = 1;
+                    // Encrypt challenge text & auth information
+                    RTMPInitWepEngine(
+                       pAd,
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
+                       pAd->StaCfg.DefaultKeyId,
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen,
+                       CyperChlgText);
+
+                                       Alg = cpu2le16(*(USHORT *)&Alg);
+                                       Seq = cpu2le16(*(USHORT *)&Seq);
+                                       RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus);
+
+                                       RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2);
+                                       RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2);
+                                       RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2);
+                                       Element[0] = 16;
+                                       Element[1] = 128;
+                                       RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2);
+                                       RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128);
+                                       RTMPSetICV(pAd, CyperChlgText + 140);
+                    MakeOutgoingFrame(pOutBuffer,               &FrameLen,
+                                      sizeof(HEADER_802_11),    &AuthHdr,
+                                      CIPHER_TEXT_LEN + 16,     CyperChlgText,
+                                      END_OF_ARGS);
+                    MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+                       MlmeFreeMemory(pAd, pOutBuffer);
+
+                    RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT);
+                    pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4;
+                }
+            }
+            else
+            {
+#ifdef LEAP_SUPPORT
+                if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+                {
+                    //Invalid Authentication possible rogue AP
+                    //Add this Ap to Rogue AP.
+                    RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_INVALID_AUTH);
+                               }
+#endif // LEAP_SUPPORT //
+                pAd->StaCfg.AuthFailReason = Status;
+                COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
+                pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+                MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+            }
+        }
+    }
+    else
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n"));
+    }
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID PeerAuthRspAtSeq4Action(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+    UCHAR         Addr2[MAC_ADDR_LEN];
+    USHORT        Alg, Seq, Status;
+    CHAR          ChlgText[CIPHER_TEXT_LEN];
+    BOOLEAN       TimerCancelled;
+
+    if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
+    {
+        if(MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4)
+        {
+            DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#4 to me\n"));
+            RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
+
+            if (Status != MLME_SUCCESS)
+            {
+                pAd->StaCfg.AuthFailReason = Status;
+                COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
+            }
+
+            pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+            MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+        }
+    }
+    else
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n"));
+    }
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID MlmeDeauthReqAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+    MLME_DEAUTH_REQ_STRUCT *pInfo;
+    HEADER_802_11 DeauthHdr;
+    PUCHAR        pOutBuffer = NULL;
+    NDIS_STATUS   NStatus;
+    ULONG         FrameLen = 0;
+    USHORT        Status;
+
+    pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg;
+
+    NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+    if (NStatus != NDIS_STATUS_SUCCESS)
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeDeauthReqAction() allocate memory fail\n"));
+        pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+        Status = MLME_FAIL_NO_RESOURCE;
+        MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
+        return;
+    }
+
+    DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pInfo->Reason));
+    MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, pAd->MlmeAux.Bssid);
+    MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+                      sizeof(HEADER_802_11),&DeauthHdr,
+                      2,                    &pInfo->Reason,
+                      END_OF_ARGS);
+    MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+    pAd->StaCfg.DeauthReason = pInfo->Reason;
+    COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr);
+    pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+    Status = MLME_SUCCESS;
+    MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
+
+       // send wireless event - for deauthentication
+       if (pAd->CommonCfg.bWirelessEvent)
+               RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID AuthTimeoutAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+    USHORT Status;
+    DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n"));
+    pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+    Status = MLME_REJ_TIMEOUT;
+    MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID InvalidStateWhenAuth(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+    USHORT Status;
+    DBGPRINT(RT_DEBUG_TRACE, ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", pAd->Mlme.AuthMachine.CurrState));
+    pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+    Status = MLME_STATE_MACHINE_REJECT;
+    MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+}
+
+/*
+    ==========================================================================
+    Description:
+        Some STA/AP
+    Note:
+        This action should never trigger AUTH state transition, therefore we
+        separate it from AUTH state machine, and make it as a standalone service
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID Cls2errAction(
+    IN PRTMP_ADAPTER pAd,
+    IN PUCHAR pAddr)
+{
+    HEADER_802_11 DeauthHdr;
+    PUCHAR        pOutBuffer = NULL;
+    NDIS_STATUS   NStatus;
+    ULONG         FrameLen = 0;
+    USHORT        Reason = REASON_CLS2ERR;
+
+    NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+    if (NStatus != NDIS_STATUS_SUCCESS)
+        return;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Class 2 error, Send DEAUTH frame...\n"));
+    MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, pAd->MlmeAux.Bssid);
+    MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+                      sizeof(HEADER_802_11),&DeauthHdr,
+                      2,                    &Reason,
+                      END_OF_ARGS);
+    MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+    pAd->StaCfg.DeauthReason = Reason;
+    COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr);
+}
+
+
diff --git a/drivers/staging/rt2870/sta/auth_rsp.c b/drivers/staging/rt2870/sta/auth_rsp.c
new file mode 100644 (file)
index 0000000..6e3c2d2
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       auth_rsp.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       John            2004-10-1               copy from RT2560
+*/
+#include "../rt_config.h"
+
+/*
+    ==========================================================================
+    Description:
+        authentication state machine init procedure
+    Parameters:
+        Sm - the state machine
+
+       IRQL = PASSIVE_LEVEL
+
+    ==========================================================================
+ */
+VOID AuthRspStateMachineInit(
+    IN PRTMP_ADAPTER pAd,
+    IN PSTATE_MACHINE Sm,
+    IN STATE_MACHINE_FUNC Trans[])
+{
+    StateMachineInit(Sm, Trans, MAX_AUTH_RSP_STATE, MAX_AUTH_RSP_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_RSP_IDLE, AUTH_RSP_MACHINE_BASE);
+
+    // column 1
+    StateMachineSetAction(Sm, AUTH_RSP_IDLE, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction);
+
+    // column 2
+    StateMachineSetAction(Sm, AUTH_RSP_WAIT_CHAL, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction);
+
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+*/
+VOID PeerAuthSimpleRspGenAndSend(
+    IN PRTMP_ADAPTER pAd,
+    IN PHEADER_802_11 pHdr80211,
+    IN USHORT Alg,
+    IN USHORT Seq,
+    IN USHORT Reason,
+    IN USHORT Status)
+{
+    HEADER_802_11     AuthHdr;
+    ULONG             FrameLen = 0;
+    PUCHAR            pOutBuffer = NULL;
+    NDIS_STATUS       NStatus;
+
+    if (Reason != MLME_SUCCESS)
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("Peer AUTH fail...\n"));
+        return;
+    }
+
+       //Get an unused nonpaged memory
+    NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+    if (NStatus != NDIS_STATUS_SUCCESS)
+        return;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Send AUTH response (seq#2)...\n"));
+    MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, pHdr80211->Addr2, pAd->MlmeAux.Bssid);
+    MakeOutgoingFrame(pOutBuffer,               &FrameLen,
+                      sizeof(HEADER_802_11),    &AuthHdr,
+                      2,                        &Alg,
+                      2,                        &Seq,
+                      2,                        &Reason,
+                      END_OF_ARGS);
+    MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+*/
+VOID PeerDeauthAction(
+    IN PRTMP_ADAPTER pAd,
+    IN PMLME_QUEUE_ELEM Elem)
+{
+    UCHAR       Addr2[MAC_ADDR_LEN];
+    USHORT      Reason;
+
+    if (PeerDeauthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason))
+    {
+        if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(Addr2, pAd->CommonCfg.Bssid))
+        {
+            DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - receive DE-AUTH from our AP (Reason=%d)\n", Reason));
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+            {
+                union iwreq_data    wrqu;
+                memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+                wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+            }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+
+                       // send wireless event - for deauthentication
+                       if (pAd->CommonCfg.bWirelessEvent)
+                               RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+
+            LinkDown(pAd, TRUE);
+
+            // Authentication Mode Cisco_LEAP has start a timer
+            // We should cancel it if using LEAP
+#ifdef LEAP_SUPPORT
+            if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+            {
+                RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &TimerCancelled);
+                //Check is it mach the LEAP Authentication failed as possible a Rogue AP
+                //on it's PortSecured not equal to WPA_802_1X_PORT_SECURED while process the Authenticaton.
+                if ((pAd->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED) && (pAd->Mlme.LeapMachine.CurrState != LEAP_IDLE))
+                {
+                    RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_AUTH_TIMEOUT);
+                }
+            }
+#endif // LEAP_SUPPORT //
+        }
+    }
+    else
+    {
+        DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - PeerDeauthAction() sanity check fail\n"));
+    }
+}
+
diff --git a/drivers/staging/rt2870/sta/connect.c b/drivers/staging/rt2870/sta/connect.c
new file mode 100644 (file)
index 0000000..c93140a
--- /dev/null
@@ -0,0 +1,2822 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       connect.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       John                    2004-08-08                      Major modification from RT2560
+*/
+#include "../rt_config.h"
+
+UCHAR  CipherSuiteWpaNoneTkip[] = {
+               0x00, 0x50, 0xf2, 0x01, // oui
+               0x01, 0x00,                             // Version
+               0x00, 0x50, 0xf2, 0x02, // Multicast
+               0x01, 0x00,                             // Number of unicast
+               0x00, 0x50, 0xf2, 0x02, // unicast
+               0x01, 0x00,                             // number of authentication method
+               0x00, 0x50, 0xf2, 0x00  // authentication
+               };
+UCHAR  CipherSuiteWpaNoneTkipLen = (sizeof(CipherSuiteWpaNoneTkip) / sizeof(UCHAR));
+
+UCHAR  CipherSuiteWpaNoneAes[] = {
+               0x00, 0x50, 0xf2, 0x01, // oui
+               0x01, 0x00,                             // Version
+               0x00, 0x50, 0xf2, 0x04, // Multicast
+               0x01, 0x00,                             // Number of unicast
+               0x00, 0x50, 0xf2, 0x04, // unicast
+               0x01, 0x00,                             // number of authentication method
+               0x00, 0x50, 0xf2, 0x00  // authentication
+               };
+UCHAR  CipherSuiteWpaNoneAesLen = (sizeof(CipherSuiteWpaNoneAes) / sizeof(UCHAR));
+
+// The following MACRO is called after 1. starting an new IBSS, 2. succesfully JOIN an IBSS,
+// or 3. succesfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS
+// All settings successfuly negotiated furing MLME state machines become final settings
+// and are copied to pAd->StaActive
+#define COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd)                                 \
+{                                                                                       \
+       (_pAd)->CommonCfg.SsidLen = (_pAd)->MlmeAux.SsidLen;                                \
+       NdisMoveMemory((_pAd)->CommonCfg.Ssid, (_pAd)->MlmeAux.Ssid, (_pAd)->MlmeAux.SsidLen); \
+       COPY_MAC_ADDR((_pAd)->CommonCfg.Bssid, (_pAd)->MlmeAux.Bssid);                      \
+       (_pAd)->CommonCfg.Channel = (_pAd)->MlmeAux.Channel;                                \
+       (_pAd)->CommonCfg.CentralChannel = (_pAd)->MlmeAux.CentralChannel;                  \
+       (_pAd)->StaActive.Aid = (_pAd)->MlmeAux.Aid;                                        \
+       (_pAd)->StaActive.AtimWin = (_pAd)->MlmeAux.AtimWin;                                \
+       (_pAd)->StaActive.CapabilityInfo = (_pAd)->MlmeAux.CapabilityInfo;                  \
+       (_pAd)->CommonCfg.BeaconPeriod = (_pAd)->MlmeAux.BeaconPeriod;                      \
+       (_pAd)->StaActive.CfpMaxDuration = (_pAd)->MlmeAux.CfpMaxDuration;                  \
+       (_pAd)->StaActive.CfpPeriod = (_pAd)->MlmeAux.CfpPeriod;                            \
+       (_pAd)->StaActive.SupRateLen = (_pAd)->MlmeAux.SupRateLen;                          \
+       NdisMoveMemory((_pAd)->StaActive.SupRate, (_pAd)->MlmeAux.SupRate, (_pAd)->MlmeAux.SupRateLen);\
+       (_pAd)->StaActive.ExtRateLen = (_pAd)->MlmeAux.ExtRateLen;                          \
+       NdisMoveMemory((_pAd)->StaActive.ExtRate, (_pAd)->MlmeAux.ExtRate, (_pAd)->MlmeAux.ExtRateLen);\
+       NdisMoveMemory(&(_pAd)->CommonCfg.APEdcaParm, &(_pAd)->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));\
+       NdisMoveMemory(&(_pAd)->CommonCfg.APQosCapability, &(_pAd)->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));\
+       NdisMoveMemory(&(_pAd)->CommonCfg.APQbssLoad, &(_pAd)->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));\
+       COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].Addr, (_pAd)->MlmeAux.Bssid);      \
+       (_pAd)->MacTab.Content[BSSID_WCID].Aid = (_pAd)->MlmeAux.Aid;                       \
+       (_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = (_pAd)->StaCfg.PairCipher;\
+       COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.BssId, (_pAd)->MlmeAux.Bssid);\
+       (_pAd)->MacTab.Content[BSSID_WCID].RateLen = (_pAd)->StaActive.SupRateLen + (_pAd)->StaActive.ExtRateLen;\
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = PASSIVE_LEVEL
+
+       ==========================================================================
+*/
+VOID MlmeCntlInit(
+       IN PRTMP_ADAPTER pAd,
+       IN STATE_MACHINE *S,
+       OUT STATE_MACHINE_FUNC Trans[])
+{
+       // Control state machine differs from other state machines, the interface
+       // follows the standard interface
+       pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID MlmeCntlMachinePerformAction(
+       IN PRTMP_ADAPTER pAd,
+       IN STATE_MACHINE *S,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       switch(pAd->Mlme.CntlMachine.CurrState)
+       {
+               case CNTL_IDLE:
+                               CntlIdleProc(pAd, Elem);
+                       break;
+               case CNTL_WAIT_DISASSOC:
+                       CntlWaitDisassocProc(pAd, Elem);
+                       break;
+               case CNTL_WAIT_JOIN:
+                       CntlWaitJoinProc(pAd, Elem);
+                       break;
+
+               // CNTL_WAIT_REASSOC is the only state in CNTL machine that does
+               // not triggered directly or indirectly by "RTMPSetInformation(OID_xxx)".
+               // Therefore not protected by NDIS's "only one outstanding OID request"
+               // rule. Which means NDIS may SET OID in the middle of ROAMing attempts.
+               // Current approach is to block new SET request at RTMPSetInformation()
+               // when CntlMachine.CurrState is not CNTL_IDLE
+               case CNTL_WAIT_REASSOC:
+                       CntlWaitReassocProc(pAd, Elem);
+                       break;
+
+               case CNTL_WAIT_START:
+                       CntlWaitStartProc(pAd, Elem);
+                       break;
+               case CNTL_WAIT_AUTH:
+                       CntlWaitAuthProc(pAd, Elem);
+                       break;
+               case CNTL_WAIT_AUTH2:
+                       CntlWaitAuthProc2(pAd, Elem);
+                       break;
+               case CNTL_WAIT_ASSOC:
+                       CntlWaitAssocProc(pAd, Elem);
+                       break;
+
+               case CNTL_WAIT_OID_LIST_SCAN:
+                       if(Elem->MsgType == MT2_SCAN_CONF)
+                       {
+                               // Resume TxRing after SCANING complete. We hope the out-of-service time
+                               // won't be too long to let upper layer time-out the waiting frames
+                               RTMPResumeMsduTransmission(pAd);
+                               if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED)
+                               {
+                                       // Cisco scan request is finished, prepare beacon report
+                                       MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL);
+                               }
+                               pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+
+                //
+                               // Set LED status to previous status.
+                               //
+                               if (pAd->bLedOnScanning)
+                               {
+                                       pAd->bLedOnScanning = FALSE;
+                                       RTMPSetLED(pAd, pAd->LedStatus);
+                               }
+#ifdef DOT11N_DRAFT3
+                               // AP sent a 2040Coexistence mgmt frame, then station perform a scan, and then send back the respone.
+                               if (pAd->CommonCfg.BSSCoexist2040.field.InfoReq == 1)
+                               {
+                                       Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
+                               }
+#endif // DOT11N_DRAFT3 //
+                       }
+                       break;
+
+               case CNTL_WAIT_OID_DISASSOC:
+                       if (Elem->MsgType == MT2_DISASSOC_CONF)
+                       {
+                               LinkDown(pAd, FALSE);
+                               pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+                       }
+                       break;
+#ifdef RT2870
+               //
+               // This state is for that we want to connect to an AP but
+               // it didn't find on BSS List table. So we need to scan the air first,
+               // after that we can try to connect to the desired AP if available.
+               //
+               case CNTL_WAIT_SCAN_FOR_CONNECT:
+                       if(Elem->MsgType == MT2_SCAN_CONF)
+                       {
+                               // Resume TxRing after SCANING complete. We hope the out-of-service time
+                               // won't be too long to let upper layer time-out the waiting frames
+                               RTMPResumeMsduTransmission(pAd);
+#ifdef CCX_SUPPORT
+                               if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED)
+                               {
+                                       // Cisco scan request is finished, prepare beacon report
+                                       MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL);
+                               }
+#endif // CCX_SUPPORT //
+                               pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+
+                               //
+                               // Check if we can connect to.
+                               //
+                               BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
+                               if (pAd->MlmeAux.SsidBssTab.BssNr > 0)
+                               {
+                                       MlmeAutoReconnectLastSSID(pAd);
+                               }
+                       }
+                       break;
+#endif // RT2870 //
+               default:
+                       DBGPRINT_ERR(("!ERROR! CNTL - Illegal message type(=%ld)", Elem->MsgType));
+                       break;
+       }
+}
+
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID CntlIdleProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       MLME_DISASSOC_REQ_STRUCT   DisassocReq;
+
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
+               return;
+
+       switch(Elem->MsgType)
+       {
+               case OID_802_11_SSID:
+                       CntlOidSsidProc(pAd, Elem);
+                       break;
+
+               case OID_802_11_BSSID:
+                       CntlOidRTBssidProc(pAd,Elem);
+                       break;
+
+               case OID_802_11_BSSID_LIST_SCAN:
+                       CntlOidScanProc(pAd,Elem);
+                       break;
+
+               case OID_802_11_DISASSOCIATE:
+#ifdef RALINK_ATE
+                       if(ATE_ON(pAd))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               break;
+                       }
+#endif // RALINK_ATE //
+                       DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
+                       MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC;
+#ifdef WPA_SUPPLICANT_SUPPORT
+            if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE_WITH_WEB_UI)
+#endif // WPA_SUPPLICANT_SUPPORT //
+            {
+                       // Set the AutoReconnectSsid to prevent it reconnect to old SSID
+                       // Since calling this indicate user don't want to connect to that SSID anymore.
+                       pAd->MlmeAux.AutoReconnectSsidLen= 32;
+                       NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
+            }
+                       break;
+
+               case MT2_MLME_ROAMING_REQ:
+                       CntlMlmeRoamingProc(pAd, Elem);
+                       break;
+
+        case OID_802_11_MIC_FAILURE_REPORT_FRAME:
+            WpaMicFailureReportFrame(pAd, Elem);
+            break;
+
+#ifdef QOS_DLS_SUPPORT
+               case RT_OID_802_11_SET_DLS_PARAM:
+                       CntlOidDLSSetupProc(pAd, Elem);
+                       break;
+#endif // QOS_DLS_SUPPORT //
+
+               default:
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Illegal message in CntlIdleProc(MsgType=%ld)\n",Elem->MsgType));
+                       break;
+       }
+}
+
+VOID CntlOidScanProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       MLME_SCAN_REQ_STRUCT       ScanReq;
+       ULONG                      BssIdx = BSS_NOT_FOUND;
+       BSS_ENTRY                  CurrBss;
+
+#ifdef RALINK_ATE
+/* Disable scanning when ATE is running. */
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+
+       // record current BSS if network is connected.
+       // 2003-2-13 do not include current IBSS if this is the only STA in this IBSS.
+       if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+       {
+               BssIdx = BssSsidTableSearch(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->CommonCfg.Channel);
+               if (BssIdx != BSS_NOT_FOUND)
+               {
+                       NdisMoveMemory(&CurrBss, &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY));
+               }
+       }
+
+       // clean up previous SCAN result, add current BSS back to table if any
+       BssTableInit(&pAd->ScanTab);
+       if (BssIdx != BSS_NOT_FOUND)
+       {
+               // DDK Note: If the NIC is associated with a particular BSSID and SSID
+               //    that are not contained in the list of BSSIDs generated by this scan, the
+               //    BSSID description of the currently associated BSSID and SSID should be
+               //    appended to the list of BSSIDs in the NIC's database.
+               // To ensure this, we append this BSS as the first entry in SCAN result
+               NdisMoveMemory(&pAd->ScanTab.BssEntry[0], &CurrBss, sizeof(BSS_ENTRY));
+               pAd->ScanTab.BssNr = 1;
+       }
+
+       ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_ACTIVE);
+       MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ,
+               sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+}
+
+/*
+       ==========================================================================
+       Description:
+               Before calling this routine, user desired SSID should already been
+               recorded in CommonCfg.Ssid[]
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID CntlOidSsidProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM * Elem)
+{
+       PNDIS_802_11_SSID          pOidSsid = (NDIS_802_11_SSID *)Elem->Msg;
+       MLME_DISASSOC_REQ_STRUCT   DisassocReq;
+       ULONG                                      Now;
+
+       // Step 1. record the desired user settings to MlmeAux
+       NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
+       NdisMoveMemory(pAd->MlmeAux.Ssid, pOidSsid->Ssid, pOidSsid->SsidLength);
+       pAd->MlmeAux.SsidLen = (UCHAR)pOidSsid->SsidLength;
+       NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
+       pAd->MlmeAux.BssType = pAd->StaCfg.BssType;
+
+
+       //
+       // Update Reconnect Ssid, that user desired to connect.
+       //
+       NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID);
+       NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+       pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen;
+
+       // step 2. find all matching BSS in the lastest SCAN result (inBssTab)
+       //    & log them into MlmeAux.SsidBssTab for later-on iteration. Sort by RSSI order
+       BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - %d BSS of %d BSS match the desire (%d)SSID - %s\n",
+                       pAd->MlmeAux.SsidBssTab.BssNr, pAd->ScanTab.BssNr, pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid));
+       NdisGetSystemUpTime(&Now);
+
+       if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
+               (pAd->CommonCfg.SsidLen == pAd->MlmeAux.SsidBssTab.BssEntry[0].SsidLen) &&
+               NdisEqualMemory(pAd->CommonCfg.Ssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Ssid, pAd->CommonCfg.SsidLen) &&
+               MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Bssid))
+       {
+               // Case 1. already connected with an AP who has the desired SSID
+               //         with highest RSSI
+
+               // Add checking Mode "LEAP" for CCX 1.0
+               if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+                        (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+                        (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
+                        (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+#ifdef LEAP_SUPPORT
+                        || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+#endif // LEAP_SUPPORT //
+                        ) &&
+                       (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+               {
+                       // case 1.1 For WPA, WPA-PSK, if the 1x port is not secured, we have to redo
+                       //          connection process
+                       DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n"));
+                       DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
+                       MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
+                                               sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
+               }
+               else if (pAd->bConfigChanged == TRUE)
+               {
+                       // case 1.2 Important Config has changed, we have to reconnect to the same AP
+                       DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP Because config changed...\n"));
+                       DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
+                       MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
+                                               sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
+               }
+               else
+               {
+                       // case 1.3. already connected to the SSID with highest RSSI.
+                       DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - already with this BSSID. ignore this SET_SSID request\n"));
+                       //
+                       // (HCT 12.1) 1c_wlan_mediaevents required
+                       // media connect events are indicated when associating with the same AP
+                       //
+                       if (INFRA_ON(pAd))
+                       {
+                               //
+                               // Since MediaState already is NdisMediaStateConnected
+                               // We just indicate the connect event again to meet the WHQL required.
+                               //
+                               pAd->IndicateMediaState = NdisMediaStateConnected;
+                               RTMP_IndicateMediaState(pAd);
+                pAd->ExtraInfo = GENERAL_LINK_UP;   // Update extra information to link is up
+                       }
+
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+            {
+                union iwreq_data    wrqu;
+
+                memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+                memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
+                wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+            }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+               }
+       }
+       else if (INFRA_ON(pAd))
+       {
+               //
+               // For RT61
+               // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: )
+               // RT61 may lost SSID, and not connect to NDTEST_WEP_AP2 and will connect to NDTEST_WEP_AP2 by Autoreconnect
+               // But media status is connected, so the SSID not report correctly.
+               //
+               if (!SSID_EQUAL(pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen))
+               {
+                       //
+                       // Different SSID means not Roaming case, so we let LinkDown() to Indicate a disconnect event.
+                       //
+                       pAd->MlmeAux.CurrReqIsFromNdis = TRUE;
+               }
+               // case 2. active INFRA association existent
+               //    roaming is done within miniport driver, nothing to do with configuration
+               //    utility. so upon a new SET(OID_802_11_SSID) is received, we just
+               //    disassociate with the current associated AP,
+               //    then perform a new association with this new SSID, no matter the
+               //    new/old SSID are the same or not.
+               DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n"));
+               DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
+               MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
+                                       sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
+               pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
+       }
+       else
+       {
+               if (ADHOC_ON(pAd))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - drop current ADHOC\n"));
+                       LinkDown(pAd, FALSE);
+                       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+                       pAd->IndicateMediaState = NdisMediaStateDisconnected;
+                       RTMP_IndicateMediaState(pAd);
+            pAd->ExtraInfo = GENERAL_LINK_DOWN;
+                       DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():NDIS_STATUS_MEDIA_DISCONNECT Event C!\n"));
+               }
+
+               if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) &&
+                       (pAd->StaCfg.bAutoReconnect == TRUE) &&
+                       (pAd->MlmeAux.BssType == BSS_INFRA) &&
+                       (MlmeValidateSSID(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen) == TRUE)
+                       )
+               {
+                       MLME_SCAN_REQ_STRUCT       ScanReq;
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - No matching BSS, start a new scan\n"));
+                       ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE);
+                       MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+                       // Reset Missed scan number
+                       pAd->StaCfg.LastScanTime = Now;
+               }
+               else
+               {
+                       pAd->MlmeAux.BssIdx = 0;
+                       IterateOnBssTab(pAd);
+               }
+       }
+}
+
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID CntlOidRTBssidProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM * Elem)
+{
+       ULONG       BssIdx;
+       PUCHAR      pOidBssid = (PUCHAR)Elem->Msg;
+       MLME_DISASSOC_REQ_STRUCT    DisassocReq;
+       MLME_JOIN_REQ_STRUCT        JoinReq;
+
+#ifdef RALINK_ATE
+/* No need to perform this routine when ATE is running. */
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+       // record user desired settings
+       COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pOidBssid);
+       pAd->MlmeAux.BssType = pAd->StaCfg.BssType;
+
+       //
+       // Update Reconnect Ssid, that user desired to connect.
+       //
+       NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID);
+       pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen;
+       NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+
+       // find the desired BSS in the latest SCAN result table
+       BssIdx = BssTableSearch(&pAd->ScanTab, pOidBssid, pAd->MlmeAux.Channel);
+       if (BssIdx == BSS_NOT_FOUND)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n"));
+               pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+               return;
+       }
+
+       // copy the matched BSS entry from ScanTab to MlmeAux.SsidBssTab. Why?
+       // Because we need this entry to become the JOIN target in later on SYNC state machine
+       pAd->MlmeAux.BssIdx = 0;
+       pAd->MlmeAux.SsidBssTab.BssNr = 1;
+       NdisMoveMemory(&pAd->MlmeAux.SsidBssTab.BssEntry[0], &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY));
+
+       //pAd->MlmeAux.AutoReconnectSsidLen = pAd->ScanTab.BssEntry[BssIdx].SsidLen;
+       //NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->ScanTab.BssEntry[BssIdx].Ssid, pAd->ScanTab.BssEntry[BssIdx].SsidLen);
+
+       // Add SSID into MlmeAux for site surey joining hidden SSID
+       //pAd->MlmeAux.SsidLen = pAd->ScanTab.BssEntry[BssIdx].SsidLen;
+       //NdisMoveMemory(pAd->MlmeAux.Ssid, pAd->ScanTab.BssEntry[BssIdx].Ssid, pAd->MlmeAux.SsidLen);
+
+       // 2002-11-26 skip the following checking. i.e. if user wants to re-connect to same AP
+       //   we just follow normal procedure. The reason of user doing this may because he/she changed
+       //   AP to another channel, but we still received BEACON from it thus don't claim Link Down.
+       //   Since user knows he's changed AP channel, he'll re-connect again. By skipping the following
+       //   checking, we'll disassociate then re-do normal association with this AP at the new channel.
+       // 2003-1-6 Re-enable this feature based on microsoft requirement which prefer not to re-do
+       //   connection when setting the same BSSID.
+       if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
+               MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pOidBssid))
+       {
+               // already connected to the same BSSID, go back to idle state directly
+               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - already in this BSSID. ignore this SET_BSSID request\n"));
+               pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+            {
+                union iwreq_data    wrqu;
+
+                memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+                memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
+                wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+            }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+       }
+       else
+       {
+               if (INFRA_ON(pAd))
+               {
+                       // disassoc from current AP first
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - disassociate with current AP ...\n"));
+                       DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
+                       MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
+                                               sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
+
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
+               }
+               else
+               {
+                       if (ADHOC_ON(pAd))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - drop current ADHOC\n"));
+                               LinkDown(pAd, FALSE);
+                               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+                               pAd->IndicateMediaState = NdisMediaStateDisconnected;
+                               RTMP_IndicateMediaState(pAd);
+                pAd->ExtraInfo = GENERAL_LINK_DOWN;
+                               DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event C!\n"));
+                       }
+
+                       // Change the wepstatus to original wepstatus
+                       pAd->StaCfg.WepStatus   = pAd->StaCfg.OrigWepStatus;
+                       pAd->StaCfg.PairCipher  = pAd->StaCfg.OrigWepStatus;
+                       pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus;
+
+                       // Check cipher suite, AP must have more secured cipher than station setting
+                       // Set the Pairwise and Group cipher to match the intended AP setting
+                       // We can only connect to AP with less secured cipher setting
+                       if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+                       {
+                               pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.GroupCipher;
+
+                               if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher)
+                                       pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher;
+                               else if (pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled)
+                                       pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux;
+                               else    // There is no PairCipher Aux, downgrade our capability to TKIP
+                                       pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
+                       }
+                       else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+                       {
+                               pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.GroupCipher;
+
+                               if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher)
+                                       pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher;
+                               else if (pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled)
+                                       pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux;
+                               else    // There is no PairCipher Aux, downgrade our capability to TKIP
+                                       pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
+
+                               // RSN capability
+                               pAd->StaCfg.RsnCapability = pAd->ScanTab.BssEntry[BssIdx].WPA2.RsnCapability;
+                       }
+
+                       // Set Mix cipher flag
+                       pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE;
+                       if (pAd->StaCfg.bMixCipher == TRUE)
+                       {
+                               // If mix cipher, re-build RSNIE
+                               RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0);
+                       }
+                       // No active association, join the BSS immediately
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - joining %02x:%02x:%02x:%02x:%02x:%02x ...\n",
+                               pOidBssid[0],pOidBssid[1],pOidBssid[2],pOidBssid[3],pOidBssid[4],pOidBssid[5]));
+
+                       JoinParmFill(pAd, &JoinReq, pAd->MlmeAux.BssIdx);
+                       MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), &JoinReq);
+
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN;
+               }
+       }
+}
+
+// Roaming is the only external request triggering CNTL state machine
+// despite of other "SET OID" operation. All "SET OID" related oerations
+// happen in sequence, because no other SET OID will be sent to this device
+// until the the previous SET operation is complete (successful o failed).
+// So, how do we quarantee this ROAMING request won't corrupt other "SET OID"?
+// or been corrupted by other "SET OID"?
+//
+// IRQL = DISPATCH_LEVEL
+VOID CntlMlmeRoamingProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       // TODO:
+       // AP in different channel may show lower RSSI than actual value??
+       // should we add a weighting factor to compensate it?
+       DBGPRINT(RT_DEBUG_TRACE,("CNTL - Roaming in MlmeAux.RoamTab...\n"));
+
+       NdisMoveMemory(&pAd->MlmeAux.SsidBssTab, &pAd->MlmeAux.RoamTab, sizeof(pAd->MlmeAux.RoamTab));
+       pAd->MlmeAux.SsidBssTab.BssNr = pAd->MlmeAux.RoamTab.BssNr;
+
+       BssTableSortByRssi(&pAd->MlmeAux.SsidBssTab);
+       pAd->MlmeAux.BssIdx = 0;
+       IterateOnBssTab(pAd);
+}
+
+#ifdef QOS_DLS_SUPPORT
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID CntlOidDLSSetupProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       PRT_802_11_DLS          pDLS = (PRT_802_11_DLS)Elem->Msg;
+       MLME_DLS_REQ_STRUCT     MlmeDlsReq;
+       INT                                     i;
+       USHORT                          reason = REASON_UNSPECIFY;
+
+       DBGPRINT(RT_DEBUG_TRACE,("CNTL - (OID set %02x:%02x:%02x:%02x:%02x:%02x with Valid=%d, Status=%d, TimeOut=%d, CountDownTimer=%d)\n",
+               pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5],
+               pDLS->Valid, pDLS->Status, pDLS->TimeOut, pDLS->CountDownTimer));
+
+       if (!pAd->CommonCfg.bDLSCapable)
+               return;
+
+       // DLS will not be supported when Adhoc mode
+       if (INFRA_ON(pAd))
+       {
+               for (i = 0; i < MAX_NUM_OF_DLS_ENTRY; i++)
+               {
+                       if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
+                               (pDLS->TimeOut == pAd->StaCfg.DLSEntry[i].TimeOut) && MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+                       {
+                               // 1. Same setting, just drop it
+                               DBGPRINT(RT_DEBUG_TRACE,("CNTL - setting unchanged\n"));
+                               break;
+                       }
+                       else if (!pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
+                               MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+                       {
+                               // 2. Disable DLS link case, just tear down DLS link
+                               reason = REASON_QOS_UNWANTED_MECHANISM;
+                               pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                               pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
+                               DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+                               MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+                               DBGPRINT(RT_DEBUG_TRACE,("CNTL - start tear down procedure\n"));
+                               break;
+                       }
+                       else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid && !pAd->StaCfg.DLSEntry[i].Valid)
+                       {
+                               // 3. Enable case, start DLS setup procedure
+                               NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, sizeof(RT_802_11_DLS_UI));
+
+                               //Update countdown timer
+                               pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
+                               DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+                               MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+                               DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS setup case\n"));
+                               break;
+                       }
+                       else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid &&
+                               (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && !MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+                       {
+                               // 4. update mac case, tear down old DLS and setup new DLS
+                               reason = REASON_QOS_UNWANTED_MECHANISM;
+                               pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                               pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
+                               DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+                               MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+                               NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, sizeof(RT_802_11_DLS_UI));
+                               DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+                               MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+                               DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS tear down and restart case\n"));
+                               break;
+                       }
+                       else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid &&
+                               MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr) && (pAd->StaCfg.DLSEntry[i].TimeOut != pDLS->TimeOut))
+                       {
+                               // 5. update timeout case, start DLS setup procedure (no tear down)
+                               pAd->StaCfg.DLSEntry[i].TimeOut = pDLS->TimeOut;
+                               //Update countdown timer
+                               pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
+                               DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+                               MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+                               DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS update timeout case\n"));
+                               break;
+                       }
+                       else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid &&
+                               (pAd->StaCfg.DLSEntry[i].Status != DLS_FINISH) && MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+                       {
+                               // 6. re-setup case, start DLS setup procedure (no tear down)
+                               DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+                               MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+                               DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS retry setup procedure\n"));
+                               break;
+                       }
+                       else
+                       {
+                               DBGPRINT(RT_DEBUG_WARN,("CNTL - DLS not changed in entry - %d - Valid=%d, Status=%d, TimeOut=%d\n",
+                                       i, pAd->StaCfg.DLSEntry[i].Valid, pAd->StaCfg.DLSEntry[i].Status, pAd->StaCfg.DLSEntry[i].TimeOut));
+                       }
+               }
+       }
+}
+#endif // QOS_DLS_SUPPORT //
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID CntlWaitDisassocProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       MLME_START_REQ_STRUCT     StartReq;
+
+       if (Elem->MsgType == MT2_DISASSOC_CONF)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Dis-associate successful\n"));
+
+           if (pAd->CommonCfg.bWirelessEvent)
+               {
+                       RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+               }
+
+               LinkDown(pAd, FALSE);
+
+               // case 1. no matching BSS, and user wants ADHOC, so we just start a new one
+               if ((pAd->MlmeAux.SsidBssTab.BssNr==0) && (pAd->StaCfg.BssType == BSS_ADHOC))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - No matching BSS, start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid));
+                       StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+                       MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
+               }
+               // case 2. try each matched BSS
+               else
+               {
+                       pAd->MlmeAux.BssIdx = 0;
+
+                       IterateOnBssTab(pAd);
+               }
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID CntlWaitJoinProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT                      Reason;
+       MLME_AUTH_REQ_STRUCT        AuthReq;
+
+       if (Elem->MsgType == MT2_JOIN_CONF)
+       {
+               NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
+               if (Reason == MLME_SUCCESS)
+               {
+                       // 1. joined an IBSS, we are pretty much done here
+                       if (pAd->MlmeAux.BssType == BSS_ADHOC)
+                       {
+                           //
+                               // 5G bands rules of Japan:
+                               // Ad hoc must be disabled in W53(ch52,56,60,64) channels.
+                               //
+                               if ( (pAd->CommonCfg.bIEEE80211H == 1) &&
+                      RadarChannelCheck(pAd, pAd->CommonCfg.Channel)
+                                  )
+                               {
+                                       pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+                                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Join adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel));
+                                       return;
+                               }
+
+                               LinkUp(pAd, BSS_ADHOC);
+                               pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+                               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - join the IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n",
+                               pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2],
+                               pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5]));
+
+                pAd->IndicateMediaState = NdisMediaStateConnected;
+                pAd->ExtraInfo = GENERAL_LINK_UP;
+                       }
+                       // 2. joined a new INFRA network, start from authentication
+                       else
+                       {
+#ifdef LEAP_SUPPORT
+                               // Add AuthMode "LEAP" for CCX 1.X
+                               if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+                               {
+                                       AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, CISCO_AuthModeLEAP);
+                               }
+                               else
+#endif // LEAP_SUPPORT //
+                               {
+                                       // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first
+                                       if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) ||
+                                               (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch))
+                                       {
+                                               AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared);
+                                       }
+                                       else
+                                       {
+                                               AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen);
+                                       }
+                               }
+                               MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ,
+                                                       sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq);
+
+                               pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH;
+                       }
+               }
+               else
+               {
+                       // 3. failed, try next BSS
+                       pAd->MlmeAux.BssIdx++;
+                       IterateOnBssTab(pAd);
+               }
+       }
+}
+
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID CntlWaitStartProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT      Result;
+
+       if (Elem->MsgType == MT2_START_CONF)
+       {
+               NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT));
+               if (Result == MLME_SUCCESS)
+               {
+                   //
+                       // 5G bands rules of Japan:
+                       // Ad hoc must be disabled in W53(ch52,56,60,64) channels.
+                       //
+                       if ( (pAd->CommonCfg.bIEEE80211H == 1) &&
+                  RadarChannelCheck(pAd, pAd->CommonCfg.Channel)
+                          )
+                       {
+                               pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+                               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Start adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel));
+                               return;
+                       }
+#ifdef DOT11_N_SUPPORT
+                       if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+                       {
+                               N_ChannelCheck(pAd);
+                               SetCommonHT(pAd);
+                               NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &pAd->CommonCfg.AddHTInfo, sizeof(ADD_HT_INFO_IE));
+                               RTMPCheckHt(pAd, BSSID_WCID, &pAd->CommonCfg.HtCapability, &pAd->CommonCfg.AddHTInfo);
+                               pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
+                               NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], 16);
+                               NdisMoveMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], &pAd->CommonCfg.HtCapability.MCSSet[0], 16);
+                               COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
+
+                               if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth  == BW_40) &&
+                                       (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE))
+                               {
+                                       pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel + 2;
+                               }
+                               else if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth  == BW_40) &&
+                                                (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW))
+                               {
+                                       pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel - 2;
+                               }
+                       }
+                       else
+#endif // DOT11_N_SUPPORT //
+                       {
+                               pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
+                       }
+                       LinkUp(pAd, BSS_ADHOC);
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+                       // Before send beacon, driver need do radar detection
+                       if ((pAd->CommonCfg.Channel > 14 )
+                               && (pAd->CommonCfg.bIEEE80211H == 1)
+                               && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
+                       {
+                               pAd->CommonCfg.RadarDetect.RDMode = RD_SILENCE_MODE;
+                               pAd->CommonCfg.RadarDetect.RDCount = 0;
+#ifdef DFS_SUPPORT
+                               BbpRadarDetectionStart(pAd);
+#endif // DFS_SUPPORT //
+                       }
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - start a new IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n",
+                               pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2],
+                               pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5]));
+               }
+               else
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Start IBSS fail. BUG!!!!!\n"));
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+               }
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID CntlWaitAuthProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT                       Reason;
+       MLME_ASSOC_REQ_STRUCT        AssocReq;
+       MLME_AUTH_REQ_STRUCT         AuthReq;
+
+       if (Elem->MsgType == MT2_AUTH_CONF)
+       {
+               NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
+               if (Reason == MLME_SUCCESS)
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n"));
+                       AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo,
+                                                 ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount);
+
+#ifdef LEAP_SUPPORT
+                       //
+                       // Cisco Leap CCKM supported Re-association.
+                       //
+                       if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE))
+                       {
+                               //if CCKM is turn on , that's mean Fast Reauthentication
+                               //Use CCKM Reassociation instead of normal association for Fast Roaming.
+                               MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ,
+                                                       sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq);
+
+                               pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC;
+                       }
+                       else
+#endif // LEAP_SUPPORT //
+                       {
+                               MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ,
+                                                       sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq);
+
+                               pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC;
+                       }
+               }
+               else
+               {
+                       // This fail may because of the AP already keep us in its MAC table without
+                       // ageing-out. The previous authentication attempt must have let it remove us.
+                       // so try Authentication again may help. For D-Link DWL-900AP+ compatibility.
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try again...\n"));
+#ifdef LEAP_SUPPORT
+                       //Add AuthMode "LEAP" for CCX 1.X
+                       if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+                       {
+                               AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, CISCO_AuthModeLEAP);
+                       }
+                       else
+#endif // LEAP_SUPPORT //
+                       {
+                               if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) ||
+                                       (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch))
+                               {
+                                       // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first
+                                       AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared);
+                               }
+                               else
+                               {
+                                       AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen);
+                               }
+                       }
+                       MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ,
+                                               sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq);
+
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2;
+               }
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID CntlWaitAuthProc2(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT                       Reason;
+       MLME_ASSOC_REQ_STRUCT        AssocReq;
+       MLME_AUTH_REQ_STRUCT         AuthReq;
+
+       if (Elem->MsgType == MT2_AUTH_CONF)
+       {
+               NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
+               if (Reason == MLME_SUCCESS)
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n"));
+                       AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo,
+                                                 ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount);
+                       MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ,
+                                               sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq);
+
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC;
+               }
+               else
+               {
+#ifdef LEAP_SUPPORT
+                       // Process LEAP first, since it use different control variable
+                       // We don't want to affect other poven operation
+                       if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+                       {
+                               // LEAP Auth not success, try next BSS
+                               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - *LEAP* AUTH FAIL, give up; try next BSS\n"));
+                               DBGPRINT(RT_DEBUG_TRACE, ("Total match BSSID [=%d]\n", pAd->MlmeAux.SsidBssTab.BssNr));
+                               pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+                               pAd->MlmeAux.BssIdx++;
+                               IterateOnBssTab(pAd);
+                       }
+                       else
+#endif // LEAP_SUPPORT //
+                       if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch) &&
+                                (pAd->MlmeAux.Alg == Ndis802_11AuthModeShared))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try OPEN system...\n"));
+                               AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen);
+                               MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ,
+                                                       sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq);
+
+                               pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2;
+                       }
+                       else
+                       {
+                               // not success, try next BSS
+                               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, give up; try next BSS\n"));
+                               pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; //???????
+                               pAd->MlmeAux.BssIdx++;
+                               IterateOnBssTab(pAd);
+                       }
+               }
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID CntlWaitAssocProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT      Reason;
+
+       if (Elem->MsgType == MT2_ASSOC_CONF)
+       {
+               NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
+               if (Reason == MLME_SUCCESS)
+               {
+                       LinkUp(pAd, BSS_INFRA);
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association successful on BSS #%ld\n",pAd->MlmeAux.BssIdx));
+
+                       if (pAd->CommonCfg.bWirelessEvent)
+                       {
+                               RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+                       }
+               }
+               else
+               {
+                       // not success, try next BSS
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association fails on BSS #%ld\n",pAd->MlmeAux.BssIdx));
+                       pAd->MlmeAux.BssIdx++;
+                       IterateOnBssTab(pAd);
+               }
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID CntlWaitReassocProc(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT      Result;
+
+       if (Elem->MsgType == MT2_REASSOC_CONF)
+       {
+               NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT));
+               if (Result == MLME_SUCCESS)
+               {
+                       //
+                       // NDIS requires a new Link UP indication but no Link Down for RE-ASSOC
+                       //
+                       LinkUp(pAd, BSS_INFRA);
+
+                       // send wireless event - for association
+                       if (pAd->CommonCfg.bWirelessEvent)
+                               RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+
+
+#ifdef LEAP_SUPPORT
+                       if (LEAP_CCKM_ON(pAd))
+                       {
+                               STA_PORT_SECURED(pAd);
+                               pAd->StaCfg.WpaState = SS_FINISH;
+                       }
+#endif // LEAP_SUPPORT //
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition successful on BSS #%ld\n", pAd->MlmeAux.RoamIdx));
+               }
+               else
+               {
+                       // reassoc failed, try to pick next BSS in the BSS Table
+                       DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition fails on BSS #%ld\n", pAd->MlmeAux.RoamIdx));
+                       pAd->MlmeAux.RoamIdx++;
+                       IterateOnBssTab2(pAd);
+               }
+       }
+}
+
+
+VOID   AdhocTurnOnQos(
+       IN  PRTMP_ADAPTER pAd)
+{
+#define AC0_DEF_TXOP           0
+#define AC1_DEF_TXOP           0
+#define AC2_DEF_TXOP           94
+#define AC3_DEF_TXOP           47
+
+       // Turn on QOs if use HT rate.
+       if (pAd->CommonCfg.APEdcaParm.bValid == FALSE)
+       {
+               pAd->CommonCfg.APEdcaParm.bValid = TRUE;
+               pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3;
+               pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7;
+               pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1;
+               pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1;
+
+               pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4;
+               pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4;
+               pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3;
+               pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2;
+
+               pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10;
+               pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6;
+               pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4;
+               pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3;
+
+               pAd->CommonCfg.APEdcaParm.Txop[0]  = 0;
+               pAd->CommonCfg.APEdcaParm.Txop[1]  = 0;
+               pAd->CommonCfg.APEdcaParm.Txop[2]  = AC2_DEF_TXOP;
+               pAd->CommonCfg.APEdcaParm.Txop[3]  = AC3_DEF_TXOP;
+       }
+       AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID LinkUp(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR BssType)
+{
+       ULONG   Now;
+       UINT32  Data;
+       BOOLEAN Cancelled;
+       UCHAR   Value = 0, idx;
+       MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
+
+       pEntry = &pAd->MacTab.Content[BSSID_WCID];
+
+       //
+       // ASSOC - DisassocTimeoutAction
+       // CNTL - Dis-associate successful
+       // !!! LINK DOWN !!!
+       // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: )
+       //
+       // To prevent DisassocTimeoutAction to call Link down after we link up,
+       // cancel the DisassocTimer no matter what it start or not.
+       //
+       RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer,  &Cancelled);
+
+       COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
+
+#ifdef DOT11_N_SUPPORT
+       COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
+#endif // DOT11_N_SUPPORT //
+       // It's quite difficult to tell if a newly added KEY is WEP or CKIP until a new BSS
+       // is formed (either ASSOC/RE-ASSOC done or IBSS started. LinkUP should be a safe place
+       // to examine if cipher algorithm switching is required.
+       //rt2860b. Don't know why need this
+       SwitchBetweenWepAndCkip(pAd);
+
+
+       if (BssType == BSS_ADHOC)
+       {
+               OPSTATUS_SET_FLAG(pAd, fOP_STATUS_ADHOC_ON);
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON);
+
+#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+               // No carrier detection when adhoc
+               // CarrierDetectionStop(pAd);
+               pAd->CommonCfg.CarrierDetect.CD_State = CD_NORMAL;
+#endif // CARRIER_DETECTION_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+               if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+                       AdhocTurnOnQos(pAd);
+#endif // DOT11_N_SUPPORT //
+
+               DBGPRINT(RT_DEBUG_TRACE, ("!!!Adhoc LINK UP !!! \n" ));
+       }
+       else
+       {
+               OPSTATUS_SET_FLAG(pAd, fOP_STATUS_INFRA_ON);
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON);
+
+               DBGPRINT(RT_DEBUG_TRACE, ("!!!Infra LINK UP !!! \n" ));
+       }
+
+       // 3*3
+       // reset Tx beamforming bit
+       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
+       Value &= (~0x01);
+       Value |= pAd->CommonCfg.RegTransmitSetting.field.TxBF;
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
+
+#ifdef DOT11_N_SUPPORT
+       // Change to AP channel
+    if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
+       {
+               // Must using 40MHz.
+               pAd->CommonCfg.BBPCurrentBW = BW_40;
+               AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+               AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
+               Value &= (~0x18);
+               Value |= 0x10;
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
+
+               //  RX : control channel at lower
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
+               Value &= (~0x20);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
+
+               RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
+               Data &= 0xfffffffe;
+               RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
+
+               if (pAd->MACVersion == 0x28600100)
+               {
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16);
+            DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
+               }
+
+               DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel ));
+       }
+       else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
+    {
+           // Must using 40MHz.
+               pAd->CommonCfg.BBPCurrentBW = BW_40;
+               AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+           AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
+               Value &= (~0x18);
+               Value |= 0x10;
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
+
+               RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
+               Data |= 0x1;
+               RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
+
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
+           Value |= (0x20);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
+
+               if (pAd->MACVersion == 0x28600100)
+               {
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16);
+                           DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
+               }
+
+           DBGPRINT(RT_DEBUG_TRACE, ("!!! 40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel ));
+    }
+    else
+#endif // DOT11_N_SUPPORT //
+    {
+           pAd->CommonCfg.BBPCurrentBW = BW_20;
+               pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
+               AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+               AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
+               Value &= (~0x18);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
+
+               RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
+               Data &= 0xfffffffe;
+               RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
+
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
+               Value &= (~0x20);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
+
+               if (pAd->MACVersion == 0x28600100)
+               {
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11);
+            DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
+               }
+
+           DBGPRINT(RT_DEBUG_TRACE, ("!!! 20MHz LINK UP !!! \n" ));
+    }
+
+       RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
+       //
+       // Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission
+       //
+       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (BssType=%d, AID=%d, ssid=%s, Channel=%d, CentralChannel = %d)\n",
+               BssType, pAd->StaActive.Aid, pAd->CommonCfg.Ssid, pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel));
+
+#ifdef DOT11_N_SUPPORT
+       DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (Density =%d, )\n", pAd->MacTab.Content[BSSID_WCID].MpduDensity));
+#endif // DOT11_N_SUPPORT //
+
+               AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
+
+       AsicSetSlotTime(pAd, TRUE);
+       AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
+
+       // Call this for RTS protectionfor legacy rate, we will always enable RTS threshold, but normally it will not hit
+       AsicUpdateProtect(pAd, 0, (OFDMSETPROTECT | CCKSETPROTECT), TRUE, FALSE);
+
+#ifdef DOT11_N_SUPPORT
+       if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
+       {
+               // Update HT protectionfor based on AP's operating mode.
+       if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)
+       {
+               AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode,  ALLN_SETPROTECT, FALSE, TRUE);
+       }
+       else
+                       AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode,  ALLN_SETPROTECT, FALSE, FALSE);
+       }
+#endif // DOT11_N_SUPPORT //
+
+       NdisZeroMemory(&pAd->DrsCounters, sizeof(COUNTER_DRS));
+
+       NdisGetSystemUpTime(&Now);
+       pAd->StaCfg.LastBeaconRxTime = Now;   // last RX timestamp
+
+       if ((pAd->CommonCfg.TxPreamble != Rt802_11PreambleLong) &&
+               CAP_IS_SHORT_PREAMBLE_ON(pAd->StaActive.CapabilityInfo))
+       {
+               MlmeSetTxPreamble(pAd, Rt802_11PreambleShort);
+       }
+
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
+
+       if (pAd->CommonCfg.RadarDetect.RDMode == RD_SILENCE_MODE)
+       {
+#ifdef DFS_SUPPORT
+               RadarDetectionStop(pAd);
+#endif // DFS_SUPPORT //
+       }
+       pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE;
+
+       if (BssType == BSS_ADHOC)
+       {
+               MakeIbssBeacon(pAd);
+               if ((pAd->CommonCfg.Channel > 14)
+                       && (pAd->CommonCfg.bIEEE80211H == 1)
+                       && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
+               {
+                       ; //Do nothing
+               }
+               else
+               {
+                       AsicEnableIbssSync(pAd);
+               }
+
+               // In ad hoc mode, use MAC table from index 1.
+               // p.s ASIC use all 0xff as termination of WCID table search.To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here.
+               RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00);
+               RTMP_IO_WRITE32(pAd, 0x1808, 0x00);
+
+               // If WEP is enabled, add key material and cipherAlg into Asic
+               // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000)
+
+               if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)
+               {
+                       PUCHAR  Key;
+                       UCHAR   CipherAlg;
+
+                       for (idx=0; idx < SHARE_KEY_NUM; idx++)
+               {
+                               CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg;
+                       Key = pAd->SharedKey[BSS0][idx].Key;
+
+                               if (pAd->SharedKey[BSS0][idx].KeyLen > 0)
+                               {
+                                       // Set key material and cipherAlg to Asic
+                               AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
+
+                    if (idx == pAd->StaCfg.DefaultKeyId)
+                                       {
+                                               // Update WCID attribute table and IVEIV table for this group key table
+                                               RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
+                                       }
+                               }
+
+
+                       }
+               }
+               // If WPANone is enabled, add key material and cipherAlg into Asic
+               // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000)
+               else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+               {
+                       pAd->StaCfg.DefaultKeyId = 0;   // always be zero
+
+            NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
+                                                       pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
+                       NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pAd->StaCfg.PMK, LEN_TKIP_EK);
+
+            if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+            {
+                       NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_RXMICK);
+                       NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_TXMICK);
+            }
+
+                       // Decide its ChiperAlg
+                       if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+                               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
+                       else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
+                               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
+                       else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Unknow Cipher (=%d), set Cipher to AES\n", pAd->StaCfg.PairCipher));
+                               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
+            }
+
+                       // Set key material and cipherAlg to Asic
+                       AsicAddSharedKeyEntry(pAd,
+                                                                 BSS0,
+                                                                 0,
+                                                                 pAd->SharedKey[BSS0][0].CipherAlg,
+                                                                 pAd->SharedKey[BSS0][0].Key,
+                                                                 pAd->SharedKey[BSS0][0].TxMic,
+                                                                 pAd->SharedKey[BSS0][0].RxMic);
+
+            // Update WCID attribute table and IVEIV table for this group key table
+                       RTMPAddWcidAttributeEntry(pAd, BSS0, 0, pAd->SharedKey[BSS0][0].CipherAlg, NULL);
+
+               }
+
+       }
+       else // BSS_INFRA
+       {
+               // Check the new SSID with last SSID
+               while (Cancelled == TRUE)
+               {
+                       if (pAd->CommonCfg.LastSsidLen == pAd->CommonCfg.SsidLen)
+                       {
+                               if (RTMPCompareMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen) == 0)
+                               {
+                                       // Link to the old one no linkdown is required.
+                                       break;
+                               }
+                       }
+                       // Send link down event before set to link up
+                       pAd->IndicateMediaState = NdisMediaStateDisconnected;
+                       RTMP_IndicateMediaState(pAd);
+            pAd->ExtraInfo = GENERAL_LINK_DOWN;
+                       DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event AA!\n"));
+                       break;
+               }
+
+               //
+               // On WPA mode, Remove All Keys if not connect to the last BSSID
+               // Key will be set after 4-way handshake.
+               //
+               if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA))
+               {
+                       ULONG           IV;
+
+                       // Remove all WPA keys
+                       RTMPWPARemoveAllKeys(pAd);
+                       pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                       pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
+
+                       // Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP
+                       // If IV related values are too large in GroupMsg2, AP would ignore this message.
+                       IV = 0;
+                       IV |= (pAd->StaCfg.DefaultKeyId << 30);
+                       AsicUpdateWCIDIVEIV(pAd, BSSID_WCID, IV, 0);
+               }
+               // NOTE:
+               // the decision of using "short slot time" or not may change dynamically due to
+               // new STA association to the AP. so we have to decide that upon parsing BEACON, not here
+
+               // NOTE:
+               // the decision to use "RTC/CTS" or "CTS-to-self" protection or not may change dynamically
+               // due to new STA association to the AP. so we have to decide that upon parsing BEACON, not here
+
+               ComposePsPoll(pAd);
+               ComposeNullFrame(pAd);
+
+                       AsicEnableBssSync(pAd);
+
+               // Add BSSID to WCID search table
+               AsicUpdateRxWCIDTable(pAd, BSSID_WCID, pAd->CommonCfg.Bssid);
+
+               NdisAcquireSpinLock(&pAd->MacTabLock);
+               // add this BSSID entry into HASH table
+               {
+                       UCHAR HashIdx;
+
+                       //pEntry = &pAd->MacTab.Content[BSSID_WCID];
+                       HashIdx = MAC_ADDR_HASH_INDEX(pAd->CommonCfg.Bssid);
+                       if (pAd->MacTab.Hash[HashIdx] == NULL)
+                       {
+                               pAd->MacTab.Hash[HashIdx] = pEntry;
+                       }
+                       else
+                       {
+                               pCurrEntry = pAd->MacTab.Hash[HashIdx];
+                               while (pCurrEntry->pNext != NULL)
+                                       pCurrEntry = pCurrEntry->pNext;
+                               pCurrEntry->pNext = pEntry;
+                       }
+               }
+               NdisReleaseSpinLock(&pAd->MacTabLock);
+
+
+               // If WEP is enabled, add paiewise and shared key
+#ifdef WPA_SUPPLICANT_SUPPORT
+        if (((pAd->StaCfg.WpaSupplicantUP)&&
+             (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)&&
+             (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)) ||
+            ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)&&
+              (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)))
+#else
+               if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)
+#endif // WPA_SUPPLICANT_SUPPORT //
+               {
+                       PUCHAR  Key;
+                       UCHAR   CipherAlg;
+
+                       for (idx=0; idx < SHARE_KEY_NUM; idx++)
+               {
+                               CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg;
+                       Key = pAd->SharedKey[BSS0][idx].Key;
+
+                               if (pAd->SharedKey[BSS0][idx].KeyLen > 0)
+                               {
+                                       // Set key material and cipherAlg to Asic
+                               AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
+
+                                       if (idx == pAd->StaCfg.DefaultKeyId)
+                                       {
+                                               // Assign group key info
+                                               RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
+
+                                               // Assign pairwise key info
+                                               RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
+                                       }
+                               }
+                       }
+               }
+
+               // only INFRASTRUCTURE mode need to indicate connectivity immediately; ADHOC mode
+               // should wait until at least 2 active nodes in this BSSID.
+               OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+
+        // For GUI ++
+               if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
+               {
+                       pAd->IndicateMediaState = NdisMediaStateConnected;
+                       pAd->ExtraInfo = GENERAL_LINK_UP;
+                       RTMP_IndicateMediaState(pAd);
+               }
+        // --
+
+               // Add BSSID in my MAC Table.
+        NdisAcquireSpinLock(&pAd->MacTabLock);
+               RTMPMoveMemory(pAd->MacTab.Content[BSSID_WCID].Addr, pAd->CommonCfg.Bssid, MAC_ADDR_LEN);
+               pAd->MacTab.Content[BSSID_WCID].Aid = BSSID_WCID;
+               pAd->MacTab.Content[BSSID_WCID].pAd = pAd;
+               pAd->MacTab.Content[BSSID_WCID].ValidAsCLI = TRUE;      //Although this is bssid..still set ValidAsCl
+               pAd->MacTab.Size = 1;   // infra mode always set MACtab size =1.
+               pAd->MacTab.Content[BSSID_WCID].Sst = SST_ASSOC;
+               pAd->MacTab.Content[BSSID_WCID].AuthState = SST_ASSOC;
+               pAd->MacTab.Content[BSSID_WCID].WepStatus = pAd->StaCfg.WepStatus;
+        NdisReleaseSpinLock(&pAd->MacTabLock);
+
+               DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!!  ClientStatusFlags=%lx)\n",
+                       pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
+
+               MlmeUpdateTxRates(pAd, TRUE, BSS0);
+#ifdef DOT11_N_SUPPORT
+               MlmeUpdateHtTxRates(pAd, BSS0);
+               DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !! (StaActive.bHtEnable =%d, )\n", pAd->StaActive.SupportedPhyInfo.bHtEnable));
+#endif // DOT11_N_SUPPORT //
+
+               //
+               // Report Adjacent AP report.
+               //
+#ifdef LEAP_SUPPORT
+               CCXAdjacentAPReport(pAd);
+#endif // LEAP_SUPPORT //
+
+               if (pAd->CommonCfg.bAggregationCapable)
+               {
+                       if ((pAd->CommonCfg.bPiggyBackCapable) && (pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)
+                       {
+
+                               OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED);
+                               OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
+                RTMPSetPiggyBack(pAd, TRUE);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n"));
+                       }
+                       else if (pAd->MlmeAux.APRalinkIe & 0x00000001)
+                       {
+                               OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
+                       }
+               }
+
+               if (pAd->MlmeAux.APRalinkIe != 0x0)
+               {
+#ifdef DOT11_N_SUPPORT
+                       if (CLIENT_STATUS_TEST_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RDG_CAPABLE))
+                       {
+                               AsicEnableRDG(pAd);
+                       }
+#endif // DOT11_N_SUPPORT //
+                       OPSTATUS_SET_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET);
+                       CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET);
+               }
+               else
+               {
+                       OPSTATUS_CLEAR_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET);
+                       CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET);
+               }
+       }
+
+#ifdef DOT11_N_SUPPORT
+       DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_CONNECT Event B!.BACapability = %x. ClientStatusFlags = %lx\n", pAd->CommonCfg.BACapability.word, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
+#endif // DOT11_N_SUPPORT //
+
+       // Set LED
+       RTMPSetLED(pAd, LED_LINK_UP);
+
+       pAd->Mlme.PeriodicRound = 0;
+       pAd->Mlme.OneSecPeriodicRound = 0;
+       pAd->bConfigChanged = FALSE;        // Reset config flag
+       pAd->ExtraInfo = GENERAL_LINK_UP;   // Update extra information to link is up
+
+       // Set asic auto fall back
+       {
+               PUCHAR                                  pTable;
+               UCHAR                                   TableSize = 0;
+
+               MlmeSelectTxRateTable(pAd, &pAd->MacTab.Content[BSSID_WCID], &pTable, &TableSize, &pAd->CommonCfg.TxRateIndex);
+               AsicUpdateAutoFallBackTable(pAd, pTable);
+       }
+
+       NdisAcquireSpinLock(&pAd->MacTabLock);
+    pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word;
+    pEntry->MaxHTPhyMode.word = pAd->StaCfg.HTPhyMode.word;
+       if (pAd->StaCfg.bAutoTxRateSwitch == FALSE)
+       {
+               pEntry->bAutoTxRateSwitch = FALSE;
+#ifdef DOT11_N_SUPPORT
+               if (pEntry->HTPhyMode.field.MCS == 32)
+                       pEntry->HTPhyMode.field.ShortGI = GI_800;
+
+               if ((pEntry->HTPhyMode.field.MCS > MCS_7) || (pEntry->HTPhyMode.field.MCS == 32))
+                       pEntry->HTPhyMode.field.STBC = STBC_NONE;
+#endif // DOT11_N_SUPPORT //
+               // If the legacy mode is set, overwrite the transmit setting of this entry.
+               if (pEntry->HTPhyMode.field.MODE <= MODE_OFDM)
+                       RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
+       }
+       else
+               pEntry->bAutoTxRateSwitch = TRUE;
+       NdisReleaseSpinLock(&pAd->MacTabLock);
+
+       //  Let Link Status Page display first initial rate.
+       pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
+       // Select DAC according to HT or Legacy
+       if (pAd->StaActive.SupportedPhyInfo.MCSSet[0] != 0x00)
+       {
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value);
+               Value &= (~0x18);
+               if (pAd->Antenna.field.TxPath == 2)
+               {
+                   Value |= 0x10;
+               }
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value);
+       }
+       else
+       {
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value);
+               Value &= (~0x18);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value);
+       }
+
+#ifdef DOT11_N_SUPPORT
+       if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
+       {
+       }
+       else if (pEntry->MaxRAmpduFactor == 0)
+       {
+           // If HT AP doesn't support MaxRAmpduFactor = 1, we need to set max PSDU to 0.
+           // Because our Init value is 1 at MACRegTable.
+               RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x0fff);
+       }
+#endif // DOT11_N_SUPPORT //
+
+       // Patch for Marvel AP to gain high throughput
+       // Need to set as following,
+       // 1. Set txop in register-EDCA_AC0_CFG as 0x60
+       // 2. Set EnTXWriteBackDDONE in register-WPDMA_GLO_CFG as zero
+       // 3. PBF_MAX_PCNT as 0x1F3FBF9F
+       // 4. kick per two packets when dequeue
+       //
+       // Txop can only be modified when RDG is off, WMM is disable and TxBurst is enable
+       //
+       // if 1. Legacy AP WMM on,  or 2. 11n AP, AMPDU disable.  Force turn off burst no matter what bEnableTxBurst is.
+#ifdef DOT11_N_SUPPORT
+       if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
+               || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)))
+       {
+               RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+               Data  &= 0xFFFFFF00;
+               RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+
+               RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F);
+               DBGPRINT(RT_DEBUG_TRACE, ("Txburst 1\n"));
+       }
+       else
+#endif // DOT11_N_SUPPORT //
+       if (pAd->CommonCfg.bEnableTxBurst)
+       {
+               RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+               Data  &= 0xFFFFFF00;
+               Data  |= 0x60;
+               RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+               pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = TRUE;
+
+               RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3FBF9F);
+               DBGPRINT(RT_DEBUG_TRACE, ("Txburst 2\n"));
+       }
+       else
+       {
+               RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+               Data  &= 0xFFFFFF00;
+               RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+
+               RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F);
+               DBGPRINT(RT_DEBUG_TRACE, ("Txburst 3\n"));
+       }
+
+#ifdef DOT11_N_SUPPORT
+       // Re-check to turn on TX burst or not.
+       if ((pAd->CommonCfg.IOTestParm.bLastAtheros == TRUE) && ((STA_WEP_ON(pAd))||(STA_TKIP_ON(pAd))))
+       {
+               pAd->CommonCfg.IOTestParm.bNextDisableRxBA = TRUE;
+               if (pAd->CommonCfg.bEnableTxBurst)
+               {
+                   UINT32 MACValue = 0;
+                       // Force disable  TXOP value in this case. The same action in MLMEUpdateProtect too.
+                       // I didn't change PBF_MAX_PCNT setting.
+                       RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &MACValue);
+                       MACValue  &= 0xFFFFFF00;
+                       RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, MACValue);
+                       pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE;
+               }
+       }
+       else
+       {
+               pAd->CommonCfg.IOTestParm.bNextDisableRxBA = FALSE;
+       }
+#endif // DOT11_N_SUPPORT //
+
+       pAd->CommonCfg.IOTestParm.bLastAtheros = FALSE;
+       COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid);
+       DBGPRINT(RT_DEBUG_TRACE, ("!!!pAd->bNextDisableRxBA= %d \n", pAd->CommonCfg.IOTestParm.bNextDisableRxBA));
+       // BSSID add in one MAC entry too.  Because in Tx, ASIC need to check Cipher and IV/EIV, BAbitmap
+       // Pther information in MACTab.Content[BSSID_WCID] is not necessary for driver.
+       // Note: As STA, The MACTab.Content[BSSID_WCID]. PairwiseKey and Shared Key for BSS0 are the same.
+
+    if (pAd->StaCfg.WepStatus <= Ndis802_11WEPDisabled)
+    {
+        pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+               pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
+       }
+
+       NdisAcquireSpinLock(&pAd->MacTabLock);
+       pEntry->PortSecured = pAd->StaCfg.PortSecured;
+       NdisReleaseSpinLock(&pAd->MacTabLock);
+
+    //
+       // Patch Atheros AP TX will breakdown issue.
+       // AP Model: DLink DWL-8200AP
+       //
+       if (INFRA_ON(pAd) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && STA_TKIP_ON(pAd))
+       {
+               RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x01);
+       }
+       else
+       {
+               RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x00);
+       }
+
+       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+
+
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+       if ((pAd->CommonCfg.BACapability.field.b2040CoexistScanSup) && (pAd->CommonCfg.Channel <= 11))
+       {
+               OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SCAN_2040);
+               BuildEffectedChannelList(pAd);
+       }
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+}
+
+/*
+       ==========================================================================
+
+       Routine Description:
+               Disconnect current BSSID
+
+       Arguments:
+               pAd                             - Pointer to our adapter
+               IsReqFromAP             - Request from AP
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+               We need more information to know it's this requst from AP.
+               If yes! we need to do extra handling, for example, remove the WPA key.
+               Otherwise on 4-way handshaking will faied, since the WPA key didn't be
+               remove while auto reconnect.
+               Disconnect request from AP, it means we will start afresh 4-way handshaking
+               on WPA mode.
+
+       ==========================================================================
+*/
+VOID LinkDown(
+       IN PRTMP_ADAPTER pAd,
+       IN  BOOLEAN      IsReqFromAP)
+{
+       UCHAR                       i, ByteValue = 0;
+
+       // Do nothing if monitor mode is on
+       if (MONITOR_ON(pAd))
+               return;
+
+#ifdef RALINK_ATE
+       // Nothing to do in ATE mode.
+       if (ATE_ON(pAd))
+               return;
+#endif // RALINK_ATE //
+
+    if (pAd->CommonCfg.bWirelessEvent)
+       {
+               RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN !!!\n"));
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
+
+       if (ADHOC_ON(pAd))              // Adhoc mode link down
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 1!!!\n"));
+
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON);
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+               pAd->IndicateMediaState = NdisMediaStateDisconnected;
+               RTMP_IndicateMediaState(pAd);
+        pAd->ExtraInfo = GENERAL_LINK_DOWN;
+               BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel);
+               DBGPRINT(RT_DEBUG_TRACE, ("!!! MacTab.Size=%d !!!\n", pAd->MacTab.Size));
+       }
+       else                                    // Infra structure mode
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 2!!!\n"));
+
+#ifdef QOS_DLS_SUPPORT
+               // DLS tear down frame must be sent before link down
+               // send DLS-TEAR_DOWN message
+               if (pAd->CommonCfg.bDLSCapable)
+               {
+                       // tear down local dls table entry
+                       for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+                       {
+                               if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+                               {
+                                       pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+                                       RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+                               }
+                       }
+
+                       // tear down peer dls table entry
+                       for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+                       {
+                               if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status ==  DLS_FINISH))
+                               {
+                                       pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+                                       RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+                               }
+                       }
+               }
+#endif // QOS_DLS_SUPPORT //
+
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON);
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+
+               // Saved last SSID for linkup comparison
+               pAd->CommonCfg.LastSsidLen = pAd->CommonCfg.SsidLen;
+               NdisMoveMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen);
+               COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid);
+               if (pAd->MlmeAux.CurrReqIsFromNdis == TRUE)
+               {
+                       pAd->IndicateMediaState = NdisMediaStateDisconnected;
+                       RTMP_IndicateMediaState(pAd);
+            pAd->ExtraInfo = GENERAL_LINK_DOWN;
+                       DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event A!\n"));
+                       pAd->MlmeAux.CurrReqIsFromNdis = FALSE;
+               }
+               else
+               {
+            //
+                       // If disassociation request is from NDIS, then we don't need to delete BSSID from entry.
+                       // Otherwise lost beacon or receive De-Authentication from AP,
+                       // then we should delete BSSID from BssTable.
+                       // If we don't delete from entry, roaming will fail.
+                       //
+                       BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel);
+               }
+
+               // restore back to -
+               //      1. long slot (20 us) or short slot (9 us) time
+               //      2. turn on/off RTS/CTS and/or CTS-to-self protection
+               //      3. short preamble
+               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
+
+               if (pAd->StaCfg.CCXAdjacentAPReportFlag == TRUE)
+               {
+                       //
+                       // Record current AP's information.
+                       // for later used reporting Adjacent AP report.
+                       //
+                       pAd->StaCfg.CCXAdjacentAPChannel = pAd->CommonCfg.Channel;
+                       pAd->StaCfg.CCXAdjacentAPSsidLen = pAd->CommonCfg.SsidLen;
+                       NdisMoveMemory(pAd->StaCfg.CCXAdjacentAPSsid, pAd->CommonCfg.Ssid, pAd->StaCfg.CCXAdjacentAPSsidLen);
+                       COPY_MAC_ADDR(pAd->StaCfg.CCXAdjacentAPBssid, pAd->CommonCfg.Bssid);
+               }
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+               // Country IE of the AP will be evaluated and will be used.
+               if (pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None)
+               {
+                       NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pAd->StaCfg.StaOriCountryCode[0], 2);
+                       pAd->CommonCfg.Geography = pAd->StaCfg.StaOriGeography;
+                       BuildChannelListEx(pAd);
+               }
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+       }
+
+       for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
+                       MacTableDeleteEntry(pAd, pAd->MacTab.Content[i].Aid, pAd->MacTab.Content[i].Addr);
+       }
+
+       pAd->StaCfg.CCXQosECWMin        = 4;
+       pAd->StaCfg.CCXQosECWMax        = 10;
+
+       AsicSetSlotTime(pAd, TRUE); //FALSE);
+       AsicSetEdcaParm(pAd, NULL);
+
+       // Set LED
+       RTMPSetLED(pAd, LED_LINK_DOWN);
+    pAd->LedIndicatorStregth = 0xF0;
+    RTMPSetSignalLED(pAd, -100);       // Force signal strength Led to be turned off, firmware is not done it.
+
+               AsicDisableSync(pAd);
+
+       pAd->Mlme.PeriodicRound = 0;
+       pAd->Mlme.OneSecPeriodicRound = 0;
+
+       if (pAd->StaCfg.BssType == BSS_INFRA)
+       {
+               // Remove StaCfg Information after link down
+               NdisZeroMemory(pAd->CommonCfg.Bssid, MAC_ADDR_LEN);
+               NdisZeroMemory(pAd->CommonCfg.Ssid, MAX_LEN_OF_SSID);
+               pAd->CommonCfg.SsidLen = 0;
+       }
+#ifdef DOT11_N_SUPPORT
+       NdisZeroMemory(&pAd->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE));
+       NdisZeroMemory(&pAd->MlmeAux.AddHtInfo, sizeof(ADD_HT_INFO_IE));
+       pAd->MlmeAux.HtCapabilityLen = 0;
+       pAd->MlmeAux.NewExtChannelOffset = 0xff;
+#endif // DOT11_N_SUPPORT //
+
+       // Reset WPA-PSK state. Only reset when supplicant enabled
+       if (pAd->StaCfg.WpaState != SS_NOTUSE)
+       {
+               pAd->StaCfg.WpaState = SS_START;
+               // Clear Replay counter
+               NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8);
+
+#ifdef QOS_DLS_SUPPORT
+               if (pAd->CommonCfg.bDLSCapable)
+                       NdisZeroMemory(pAd->StaCfg.DlsReplayCounter, 8);
+#endif // QOS_DLS_SUPPORT //
+       }
+
+
+       //
+       // if link down come from AP, we need to remove all WPA keys on WPA mode.
+       // otherwise will cause 4-way handshaking failed, since the WPA key not empty.
+       //
+       if ((IsReqFromAP) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA))
+       {
+               // Remove all WPA keys
+               RTMPWPARemoveAllKeys(pAd);
+       }
+
+       // 802.1x port control
+#ifdef WPA_SUPPLICANT_SUPPORT
+       // Prevent clear PortSecured here with static WEP
+       // NetworkManger set security policy first then set SSID to connect AP.
+       if (pAd->StaCfg.WpaSupplicantUP &&
+               (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) &&
+               (pAd->StaCfg.IEEE8021X == FALSE))
+       {
+               pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+       }
+       else
+#endif // WPA_SUPPLICANT_SUPPORT //
+       {
+               pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+               pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
+       }
+
+       NdisAcquireSpinLock(&pAd->MacTabLock);
+       pAd->MacTab.Content[BSSID_WCID].PortSecured = pAd->StaCfg.PortSecured;
+       NdisReleaseSpinLock(&pAd->MacTabLock);
+
+       pAd->StaCfg.MicErrCnt = 0;
+
+       // Turn off Ckip control flag
+       pAd->StaCfg.bCkipOn = FALSE;
+       pAd->StaCfg.CCXEnable = FALSE;
+
+    pAd->IndicateMediaState = NdisMediaStateDisconnected;
+       // Update extra information to link is up
+       pAd->ExtraInfo = GENERAL_LINK_DOWN;
+
+    //pAd->StaCfg.AdhocBOnlyJoined = FALSE;
+       //pAd->StaCfg.AdhocBGJoined = FALSE;
+       //pAd->StaCfg.Adhoc20NJoined = FALSE;
+    pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
+
+       // Reset the Current AP's IP address
+       NdisZeroMemory(pAd->StaCfg.AironetIPAddress, 4);
+#ifdef RT2870
+       pAd->bUsbTxBulkAggre = FALSE;
+#endif // RT2870 //
+
+       // Clean association information
+       NdisZeroMemory(&pAd->StaCfg.AssocInfo, sizeof(NDIS_802_11_ASSOCIATION_INFORMATION));
+       pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+       pAd->StaCfg.ReqVarIELen = 0;
+       pAd->StaCfg.ResVarIELen = 0;
+
+       //
+       // Reset RSSI value after link down
+       //
+       pAd->StaCfg.RssiSample.AvgRssi0 = 0;
+       pAd->StaCfg.RssiSample.AvgRssi0X8 = 0;
+       pAd->StaCfg.RssiSample.AvgRssi1 = 0;
+       pAd->StaCfg.RssiSample.AvgRssi1X8 = 0;
+       pAd->StaCfg.RssiSample.AvgRssi2 = 0;
+       pAd->StaCfg.RssiSample.AvgRssi2X8 = 0;
+
+       // Restore MlmeRate
+       pAd->CommonCfg.MlmeRate = pAd->CommonCfg.BasicMlmeRate;
+       pAd->CommonCfg.RtsRate = pAd->CommonCfg.BasicMlmeRate;
+
+#ifdef DOT11_N_SUPPORT
+       //
+       // After Link down, reset piggy-back setting in ASIC. Disable RDG.
+       //
+       if (pAd->CommonCfg.BBPCurrentBW == BW_40)
+       {
+               pAd->CommonCfg.BBPCurrentBW = BW_20;
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &ByteValue);
+               ByteValue &= (~0x18);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, ByteValue);
+       }
+#endif // DOT11_N_SUPPORT //
+       // Reset DAC
+       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &ByteValue);
+       ByteValue &= (~0x18);
+       if (pAd->Antenna.field.TxPath == 2)
+       {
+               ByteValue |= 0x10;
+       }
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, ByteValue);
+
+       RTMPSetPiggyBack(pAd,FALSE);
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED);
+
+#ifdef DOT11_N_SUPPORT
+       pAd->CommonCfg.BACapability.word = pAd->CommonCfg.REGBACapability.word;
+#endif // DOT11_N_SUPPORT //
+
+       // Restore all settings in the following.
+       AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE);
+       AsicDisableRDG(pAd);
+       pAd->CommonCfg.IOTestParm.bCurrentAtheros = FALSE;
+       pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE;
+
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+       OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SCAN_2040);
+       pAd->CommonCfg.BSSCoexist2040.word = 0;
+       TriEventInit(pAd);
+       for (i = 0; i < (pAd->ChannelListNum - 1); i++)
+       {
+               pAd->ChannelList[i].bEffectedChannel = FALSE;
+       }
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+       RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x1fff);
+       RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+       if (pAd->StaCfg.WpaSupplicantUP) {
+               union iwreq_data    wrqu;
+               //send disassociate event to wpa_supplicant
+               memset(&wrqu, 0, sizeof(wrqu));
+               wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
+               wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+       }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+       {
+               union iwreq_data    wrqu;
+               memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+               wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+       }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID IterateOnBssTab(
+       IN PRTMP_ADAPTER pAd)
+{
+       MLME_START_REQ_STRUCT   StartReq;
+       MLME_JOIN_REQ_STRUCT    JoinReq;
+       ULONG                   BssIdx;
+
+       // Change the wepstatus to original wepstatus
+       pAd->StaCfg.WepStatus   = pAd->StaCfg.OrigWepStatus;
+       pAd->StaCfg.PairCipher  = pAd->StaCfg.OrigWepStatus;
+       pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus;
+
+       BssIdx = pAd->MlmeAux.BssIdx;
+       if (BssIdx < pAd->MlmeAux.SsidBssTab.BssNr)
+       {
+               // Check cipher suite, AP must have more secured cipher than station setting
+               // Set the Pairwise and Group cipher to match the intended AP setting
+               // We can only connect to AP with less secured cipher setting
+               if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+               {
+                       pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.GroupCipher;
+
+                       if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher)
+                               pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher;
+                       else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled)
+                               pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux;
+                       else    // There is no PairCipher Aux, downgrade our capability to TKIP
+                               pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
+               }
+               else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+               {
+                       pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.GroupCipher;
+
+                       if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher)
+                               pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher;
+                       else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled)
+                               pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux;
+                       else    // There is no PairCipher Aux, downgrade our capability to TKIP
+                               pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
+
+                       // RSN capability
+                       pAd->StaCfg.RsnCapability = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.RsnCapability;
+               }
+
+               // Set Mix cipher flag
+               pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE;
+               if (pAd->StaCfg.bMixCipher == TRUE)
+               {
+                       // If mix cipher, re-build RSNIE
+                       RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0);
+               }
+
+               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.SsidBssTab.BssNr));
+               JoinParmFill(pAd, &JoinReq, BssIdx);
+               MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT),
+                                       &JoinReq);
+               pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN;
+       }
+       else if (pAd->StaCfg.BssType == BSS_ADHOC)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All BSS fail; start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid));
+               StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+               MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
+               pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
+       }
+       else // no more BSS
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All roaming failed, stay @ ch #%d\n", pAd->CommonCfg.Channel));
+               AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+               AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+               pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+       }
+}
+
+// for re-association only
+// IRQL = DISPATCH_LEVEL
+VOID IterateOnBssTab2(
+       IN PRTMP_ADAPTER pAd)
+{
+       MLME_REASSOC_REQ_STRUCT ReassocReq;
+       ULONG                   BssIdx;
+       BSS_ENTRY               *pBss;
+
+       BssIdx = pAd->MlmeAux.RoamIdx;
+       pBss = &pAd->MlmeAux.RoamTab.BssEntry[BssIdx];
+
+       if (BssIdx < pAd->MlmeAux.RoamTab.BssNr)
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.RoamTab.BssNr));
+
+               AsicSwitchChannel(pAd, pBss->Channel, FALSE);
+               AsicLockChannel(pAd, pBss->Channel);
+
+               // reassociate message has the same structure as associate message
+               AssocParmFill(pAd, &ReassocReq, pBss->Bssid, pBss->CapabilityInfo,
+                                         ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount);
+               MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ,
+                                       sizeof(MLME_REASSOC_REQ_STRUCT), &ReassocReq);
+
+               pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC;
+       }
+       else // no more BSS
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All fast roaming failed, back to ch #%d\n",pAd->CommonCfg.Channel));
+               AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+               AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+               pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID JoinParmFill(
+       IN PRTMP_ADAPTER pAd,
+       IN OUT MLME_JOIN_REQ_STRUCT *JoinReq,
+       IN ULONG BssIdx)
+{
+       JoinReq->BssIdx = BssIdx;
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID ScanParmFill(
+       IN PRTMP_ADAPTER pAd,
+       IN OUT MLME_SCAN_REQ_STRUCT *ScanReq,
+       IN CHAR Ssid[],
+       IN UCHAR SsidLen,
+       IN UCHAR BssType,
+       IN UCHAR ScanType)
+{
+    NdisZeroMemory(ScanReq->Ssid, MAX_LEN_OF_SSID);
+       ScanReq->SsidLen = SsidLen;
+       NdisMoveMemory(ScanReq->Ssid, Ssid, SsidLen);
+       ScanReq->BssType = BssType;
+       ScanReq->ScanType = ScanType;
+}
+
+#ifdef QOS_DLS_SUPPORT
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID DlsParmFill(
+       IN PRTMP_ADAPTER pAd,
+       IN OUT MLME_DLS_REQ_STRUCT *pDlsReq,
+       IN PRT_802_11_DLS pDls,
+       IN USHORT reason)
+{
+       pDlsReq->pDLS = pDls;
+       pDlsReq->Reason = reason;
+}
+#endif // QOS_DLS_SUPPORT //
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID StartParmFill(
+       IN PRTMP_ADAPTER pAd,
+       IN OUT MLME_START_REQ_STRUCT *StartReq,
+       IN CHAR Ssid[],
+       IN UCHAR SsidLen)
+{
+       ASSERT(SsidLen <= MAX_LEN_OF_SSID);
+       NdisMoveMemory(StartReq->Ssid, Ssid, SsidLen);
+       StartReq->SsidLen = SsidLen;
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+VOID AuthParmFill(
+       IN PRTMP_ADAPTER pAd,
+       IN OUT MLME_AUTH_REQ_STRUCT *AuthReq,
+       IN PUCHAR pAddr,
+       IN USHORT Alg)
+{
+       COPY_MAC_ADDR(AuthReq->Addr, pAddr);
+       AuthReq->Alg = Alg;
+       AuthReq->Timeout = AUTH_TIMEOUT;
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+
+
+#ifdef RT2870
+
+VOID MlmeCntlConfirm(
+       IN PRTMP_ADAPTER pAd,
+       IN ULONG MsgType,
+       IN USHORT Msg)
+{
+       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MsgType, sizeof(USHORT), &Msg);
+}
+
+VOID ComposePsPoll(
+       IN PRTMP_ADAPTER pAd)
+{
+       PTXINFO_STRUC           pTxInfo;
+       PTXWI_STRUC             pTxWI;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("ComposePsPoll\n"));
+       NdisZeroMemory(&pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
+
+       pAd->PsPollFrame.FC.PwrMgmt = 0;
+       pAd->PsPollFrame.FC.Type = BTYPE_CNTL;
+       pAd->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL;
+       pAd->PsPollFrame.Aid = pAd->StaActive.Aid | 0xC000;
+       COPY_MAC_ADDR(pAd->PsPollFrame.Bssid, pAd->CommonCfg.Bssid);
+       COPY_MAC_ADDR(pAd->PsPollFrame.Ta, pAd->CurrentAddress);
+
+       RTMPZeroMemory(&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[0], 100);
+       pTxInfo = (PTXINFO_STRUC)&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[0];
+       RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(PSPOLL_FRAME)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE,  FALSE);
+       pTxWI = (PTXWI_STRUC)&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE];
+       RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(PSPOLL_FRAME)),
+               0,  0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
+       RTMPMoveMemory(&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[TXWI_SIZE+TXINFO_SIZE], &pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
+       // Append 4 extra zero bytes.
+       pAd->PsPollContext.BulkOutSize =  TXINFO_SIZE + TXWI_SIZE + sizeof(PSPOLL_FRAME) + 4;
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID ComposeNullFrame(
+       IN PRTMP_ADAPTER pAd)
+{
+       PTXINFO_STRUC           pTxInfo;
+       PTXWI_STRUC             pTxWI;
+
+       NdisZeroMemory(&pAd->NullFrame, sizeof(HEADER_802_11));
+       pAd->NullFrame.FC.Type = BTYPE_DATA;
+       pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC;
+       pAd->NullFrame.FC.ToDs = 1;
+       COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid);
+       COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress);
+       COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid);
+       RTMPZeroMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[0], 100);
+       pTxInfo = (PTXINFO_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[0];
+       RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE,  FALSE);
+       pTxWI = (PTXWI_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE];
+       RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)),
+               0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
+       RTMPMoveMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11));
+       pAd->NullContext.BulkOutSize =  TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4;
+}
+#endif // RT2870 //
+
+
+/*
+       ==========================================================================
+       Description:
+               Pre-build a BEACON frame in the shared memory
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+*/
+ULONG MakeIbssBeacon(
+       IN PRTMP_ADAPTER pAd)
+{
+       UCHAR         DsLen = 1, IbssLen = 2;
+       UCHAR         LocalErpIe[3] = {IE_ERP, 1, 0x04};
+       HEADER_802_11 BcnHdr;
+       USHORT        CapabilityInfo;
+       LARGE_INTEGER FakeTimestamp;
+       ULONG         FrameLen = 0;
+       PTXWI_STRUC       pTxWI = &pAd->BeaconTxWI;
+       CHAR         *pBeaconFrame = pAd->BeaconBuf;
+       BOOLEAN       Privacy;
+       UCHAR         SupRate[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR         SupRateLen = 0;
+       UCHAR         ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR         ExtRateLen = 0;
+       UCHAR         RSNIe = IE_WPA;
+
+       if ((pAd->CommonCfg.PhyMode == PHY_11B) && (pAd->CommonCfg.Channel <= 14))
+       {
+               SupRate[0] = 0x82; // 1 mbps
+               SupRate[1] = 0x84; // 2 mbps
+               SupRate[2] = 0x8b; // 5.5 mbps
+               SupRate[3] = 0x96; // 11 mbps
+               SupRateLen = 4;
+               ExtRateLen = 0;
+       }
+       else if (pAd->CommonCfg.Channel > 14)
+       {
+               SupRate[0]  = 0x8C;    // 6 mbps, in units of 0.5 Mbps, basic rate
+               SupRate[1]  = 0x12;    // 9 mbps, in units of 0.5 Mbps
+               SupRate[2]  = 0x98;    // 12 mbps, in units of 0.5 Mbps, basic rate
+               SupRate[3]  = 0x24;    // 18 mbps, in units of 0.5 Mbps
+               SupRate[4]  = 0xb0;    // 24 mbps, in units of 0.5 Mbps, basic rate
+               SupRate[5]  = 0x48;    // 36 mbps, in units of 0.5 Mbps
+               SupRate[6]  = 0x60;    // 48 mbps, in units of 0.5 Mbps
+               SupRate[7]  = 0x6c;    // 54 mbps, in units of 0.5 Mbps
+               SupRateLen  = 8;
+               ExtRateLen  = 0;
+
+               //
+               // Also Update MlmeRate & RtsRate for G only & A only
+               //
+               pAd->CommonCfg.MlmeRate = RATE_6;
+               pAd->CommonCfg.RtsRate = RATE_6;
+               pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+               pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+               pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
+               pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+       }
+       else
+       {
+               SupRate[0] = 0x82; // 1 mbps
+               SupRate[1] = 0x84; // 2 mbps
+               SupRate[2] = 0x8b; // 5.5 mbps
+               SupRate[3] = 0x96; // 11 mbps
+               SupRateLen = 4;
+
+               ExtRate[0]  = 0x0C;    // 6 mbps, in units of 0.5 Mbps,
+               ExtRate[1]  = 0x12;    // 9 mbps, in units of 0.5 Mbps
+               ExtRate[2]  = 0x18;    // 12 mbps, in units of 0.5 Mbps,
+               ExtRate[3]  = 0x24;    // 18 mbps, in units of 0.5 Mbps
+               ExtRate[4]  = 0x30;    // 24 mbps, in units of 0.5 Mbps,
+               ExtRate[5]  = 0x48;    // 36 mbps, in units of 0.5 Mbps
+               ExtRate[6]  = 0x60;    // 48 mbps, in units of 0.5 Mbps
+               ExtRate[7]  = 0x6c;    // 54 mbps, in units of 0.5 Mbps
+               ExtRateLen  = 8;
+       }
+
+       pAd->StaActive.SupRateLen = SupRateLen;
+       NdisMoveMemory(pAd->StaActive.SupRate, SupRate, SupRateLen);
+       pAd->StaActive.ExtRateLen = ExtRateLen;
+       NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, ExtRateLen);
+
+       // compose IBSS beacon frame
+       MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pAd->CommonCfg.Bssid);
+       Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
+                         (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
+                         (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
+       CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0);
+
+       MakeOutgoingFrame(pBeaconFrame,                &FrameLen,
+                                         sizeof(HEADER_802_11),           &BcnHdr,
+                                         TIMESTAMP_LEN,                   &FakeTimestamp,
+                                         2,                               &pAd->CommonCfg.BeaconPeriod,
+                                         2,                               &CapabilityInfo,
+                                         1,                               &SsidIe,
+                                         1,                               &pAd->CommonCfg.SsidLen,
+                                         pAd->CommonCfg.SsidLen,          pAd->CommonCfg.Ssid,
+                                         1,                               &SupRateIe,
+                                         1,                               &SupRateLen,
+                                         SupRateLen,                      SupRate,
+                                         1,                               &DsIe,
+                                         1,                               &DsLen,
+                                         1,                               &pAd->CommonCfg.Channel,
+                                         1,                               &IbssIe,
+                                         1,                               &IbssLen,
+                                         2,                               &pAd->StaActive.AtimWin,
+                                         END_OF_ARGS);
+
+       // add ERP_IE and EXT_RAE IE of in 802.11g
+       if (ExtRateLen)
+       {
+               ULONG   tmp;
+
+               MakeOutgoingFrame(pBeaconFrame + FrameLen,         &tmp,
+                                                 3,                               LocalErpIe,
+                                                 1,                               &ExtRateIe,
+                                                 1,                               &ExtRateLen,
+                                                 ExtRateLen,                      ExtRate,
+                                                 END_OF_ARGS);
+               FrameLen += tmp;
+       }
+
+       // If adhoc secruity is set for WPA-None, append the cipher suite IE
+       if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+       {
+               ULONG tmp;
+        RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0);
+
+               MakeOutgoingFrame(pBeaconFrame + FrameLen,              &tmp,
+                                                 1,                                    &RSNIe,
+                                                 1,                                    &pAd->StaCfg.RSNIE_Len,
+                                                 pAd->StaCfg.RSNIE_Len,                pAd->StaCfg.RSN_IE,
+                                                 END_OF_ARGS);
+               FrameLen += tmp;
+       }
+
+#ifdef DOT11_N_SUPPORT
+       if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+       {
+               ULONG TmpLen;
+               UCHAR HtLen, HtLen1;
+
+#ifdef RT_BIG_ENDIAN
+               HT_CAPABILITY_IE HtCapabilityTmp;
+               ADD_HT_INFO_IE  addHTInfoTmp;
+               USHORT  b2lTmp, b2lTmp2;
+#endif
+
+               // add HT Capability IE
+               HtLen = sizeof(pAd->CommonCfg.HtCapability);
+               HtLen1 = sizeof(pAd->CommonCfg.AddHTInfo);
+#ifndef RT_BIG_ENDIAN
+               MakeOutgoingFrame(pBeaconFrame+FrameLen,        &TmpLen,
+                                                 1,                                            &HtCapIe,
+                                                 1,                                            &HtLen,
+                                                 HtLen,                                        &pAd->CommonCfg.HtCapability,
+                                                 1,                                            &AddHtInfoIe,
+                                                 1,                                            &HtLen1,
+                                                 HtLen1,                                       &pAd->CommonCfg.AddHTInfo,
+                                                 END_OF_ARGS);
+#else
+               NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
+               *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+               *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+               NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, HtLen1);
+               *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2));
+               *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3));
+
+               MakeOutgoingFrame(pBeaconFrame+FrameLen,        &TmpLen,
+                                                 1,                                            &HtCapIe,
+                                                 1,                                            &HtLen,
+                                                 HtLen,                                        &HtCapabilityTmp,
+                                                 1,                                            &AddHtInfoIe,
+                                                 1,                                            &HtLen1,
+                                                 HtLen1,                                       &addHTInfoTmp,
+                                                 END_OF_ARGS);
+#endif
+               FrameLen += TmpLen;
+       }
+#endif // DOT11_N_SUPPORT //
+
+       //beacon use reserved WCID 0xff
+    if (pAd->CommonCfg.Channel > 14)
+    {
+               RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE,  TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen,
+                       PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit);
+    }
+    else
+    {
+        // Set to use 1Mbps for Adhoc beacon.
+               HTTRANSMIT_SETTING Transmit;
+        Transmit.word = 0;
+        RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE,  TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen,
+               PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &Transmit);
+    }
+
+#ifdef RT_BIG_ENDIAN
+       RTMPFrameEndianChange(pAd, pBeaconFrame, DIR_WRITE, FALSE);
+       RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
+#endif
+
+    DBGPRINT(RT_DEBUG_TRACE, ("MakeIbssBeacon (len=%ld), SupRateLen=%d, ExtRateLen=%d, Channel=%d, PhyMode=%d\n",
+                                       FrameLen, SupRateLen, ExtRateLen, pAd->CommonCfg.Channel, pAd->CommonCfg.PhyMode));
+       return FrameLen;
+}
+
+
diff --git a/drivers/staging/rt2870/sta/dls.c b/drivers/staging/rt2870/sta/dls.c
new file mode 100644 (file)
index 0000000..56bfbc3
--- /dev/null
@@ -0,0 +1,2210 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    dls.c
+
+    Abstract:
+    Handle WMM-DLS state machine
+
+    Revision History:
+    Who         When          What
+    --------    ----------    ----------------------------------------------
+    Rory Chen   02-14-2006
+       Arvin Tai       06-03-2008        Modified for RT28xx
+ */
+
+#include "../rt_config.h"
+
+/*
+    ==========================================================================
+    Description:
+        dls state machine init, including state transition and timer init
+    Parameters:
+        Sm - pointer to the dls state machine
+    Note:
+        The state machine looks like this
+
+                            DLS_IDLE
+    MT2_MLME_DLS_REQUEST   MlmeDlsReqAction
+    MT2_PEER_DLS_REQUEST   PeerDlsReqAction
+    MT2_PEER_DLS_RESPONSE  PeerDlsRspAction
+    MT2_MLME_DLS_TEARDOWN  MlmeTearDownAction
+    MT2_PEER_DLS_TEARDOWN  PeerTearDownAction
+
+       IRQL = PASSIVE_LEVEL
+
+    ==========================================================================
+ */
+void DlsStateMachineInit(
+    IN PRTMP_ADAPTER pAd,
+    IN STATE_MACHINE *Sm,
+    OUT STATE_MACHINE_FUNC Trans[])
+{
+       UCHAR   i;
+
+    StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, MAX_DLS_STATE, MAX_DLS_MSG, (STATE_MACHINE_FUNC)Drop, DLS_IDLE, DLS_MACHINE_BASE);
+
+    // the first column
+    StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_REQ, (STATE_MACHINE_FUNC)MlmeDlsReqAction);
+    StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_REQ, (STATE_MACHINE_FUNC)PeerDlsReqAction);
+    StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_RSP, (STATE_MACHINE_FUNC)PeerDlsRspAction);
+    StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)MlmeDlsTearDownAction);
+    StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)PeerDlsTearDownAction);
+
+       for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
+       {
+               pAd->StaCfg.DLSEntry[i].pAd = pAd;
+               RTMPInitTimer(pAd, &pAd->StaCfg.DLSEntry[i].Timer, GET_TIMER_FUNCTION(DlsTimeoutAction), pAd, FALSE);
+       }
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID MlmeDlsReqAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+       PUCHAR                  pOutBuffer = NULL;
+       NDIS_STATUS             NStatus;
+       ULONG                   FrameLen = 0;
+       HEADER_802_11   DlsReqHdr;
+       PRT_802_11_DLS  pDLS = NULL;
+       UCHAR                   Category = CATEGORY_DLS;
+       UCHAR                   Action = ACTION_DLS_REQUEST;
+       ULONG                   tmp;
+       USHORT                  reason;
+       ULONG                   Timeout;
+       BOOLEAN                 TimerCancelled;
+
+       if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &reason))
+               return;
+
+       DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsReqAction() \n"));
+
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if (NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsReqAction() allocate memory failed \n"));
+               return;
+       }
+
+       ActHeaderInit(pAd, &DlsReqHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+
+       // Build basic frame first
+       MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
+                                       sizeof(HEADER_802_11),          &DlsReqHdr,
+                                       1,                                                      &Category,
+                                       1,                                                      &Action,
+                                       6,                                                      &pDLS->MacAddr,
+                                       6,                                                      pAd->CurrentAddress,
+                                       2,                                                      &pAd->StaActive.CapabilityInfo,
+                                       2,                                                      &pDLS->TimeOut,
+                                       1,                                                      &SupRateIe,
+                                       1,                                                      &pAd->MlmeAux.SupRateLen,
+                                       pAd->MlmeAux.SupRateLen,        pAd->MlmeAux.SupRate,
+                                       END_OF_ARGS);
+
+       if (pAd->MlmeAux.ExtRateLen != 0)
+       {
+               MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
+                                                 1,                                            &ExtRateIe,
+                                                 1,                                            &pAd->MlmeAux.ExtRateLen,
+                                                 pAd->MlmeAux.ExtRateLen,      pAd->MlmeAux.ExtRate,
+                                                 END_OF_ARGS);
+               FrameLen += tmp;
+       }
+
+#ifdef DOT11_N_SUPPORT
+       if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+       {
+               UCHAR HtLen;
+
+#ifdef RT_BIG_ENDIAN
+               HT_CAPABILITY_IE HtCapabilityTmp;
+#endif
+
+               // add HT Capability IE
+               HtLen = sizeof(HT_CAPABILITY_IE);
+#ifndef RT_BIG_ENDIAN
+               MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
+                                                       1,                                              &HtCapIe,
+                                                       1,                                              &HtLen,
+                                                       HtLen,                                  &pAd->CommonCfg.HtCapability,
+                                                       END_OF_ARGS);
+#else
+               NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
+                                                       *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+                                                       *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+               MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
+                                                       1,                                              &HtCapIe,
+                                                       1,                                              &HtLen,
+                                                       HtLen,                                  &HtCapabilityTmp,
+                                                       END_OF_ARGS);
+#endif
+               FrameLen = FrameLen + tmp;
+       }
+#endif // DOT11_N_SUPPORT //
+
+       RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
+       Timeout = DLS_TIMEOUT;
+       RTMPSetTimer(&pDLS->Timer, Timeout);
+
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID PeerDlsReqAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+       PUCHAR                  pOutBuffer = NULL;
+       NDIS_STATUS             NStatus;
+       ULONG                   FrameLen = 0;
+       USHORT                  StatusCode = MLME_SUCCESS;
+       HEADER_802_11   DlsRspHdr;
+       UCHAR                   Category = CATEGORY_DLS;
+       UCHAR                   Action = ACTION_DLS_RESPONSE;
+       ULONG                   tmp;
+       USHORT                  CapabilityInfo;
+       UCHAR                   DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
+       USHORT                  DLSTimeOut;
+       SHORT                   i;
+       ULONG                   Timeout;
+       BOOLEAN                 TimerCancelled;
+       PRT_802_11_DLS  pDLS = NULL;
+       UCHAR                   MaxSupportedRateIn500Kbps = 0;
+    UCHAR                      SupportedRatesLen;
+    UCHAR                      SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR                   HtCapabilityLen;
+       HT_CAPABILITY_IE        HtCapability;
+
+       if (!PeerDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &DLSTimeOut,
+                                                       &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability))
+               return;
+
+    // supported rates array may not be sorted. sort it and find the maximum rate
+    for (i = 0; i < SupportedRatesLen; i++)
+    {
+        if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f))
+            MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f;
+    }
+
+       DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if (NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() allocate memory failed \n"));
+               return;
+       }
+
+       if (!INFRA_ON(pAd))
+       {
+               StatusCode = MLME_REQUEST_DECLINED;
+       }
+       else if (!pAd->CommonCfg.bWmmCapable)
+       {
+               StatusCode = MLME_DEST_STA_IS_NOT_A_QSTA;
+       }
+       else if (!pAd->CommonCfg.bDLSCapable)
+       {
+               StatusCode = MLME_REQUEST_DECLINED;
+       }
+       else
+       {
+               // find table to update parameters
+               for (i = (MAX_NUM_OF_DLS_ENTRY-1); i >= 0; i--)
+               {
+                       if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
+                       {
+                               if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+                                       pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
+                               else
+                               {
+                                       RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+                                       pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+                               }
+
+                               pAd->StaCfg.DLSEntry[i].Sequence = 0;
+                               pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut;
+                               pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut;
+                               if (HtCapabilityLen != 0)
+                                       pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
+                               else
+                                       pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
+                               pDLS = &pAd->StaCfg.DLSEntry[i];
+                               break;
+                       }
+               }
+
+               // can not find in table, create a new one
+               if (i < 0)
+               {
+                       DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() can not find same entry \n"));
+                       for (i=(MAX_NUM_OF_DLS_ENTRY - 1); i >= MAX_NUM_OF_INIT_DLS_ENTRY; i--)
+                       {
+                               if (!pAd->StaCfg.DLSEntry[i].Valid)
+                               {
+                                       MAC_TABLE_ENTRY *pEntry;
+                                       UCHAR MaxSupportedRate = RATE_11;
+
+                                       if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+                                       {
+                                               pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
+                                       }
+                                       else
+                                       {
+                                               RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+                                               pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+                                       }
+
+                                       pAd->StaCfg.DLSEntry[i].Sequence = 0;
+                                       pAd->StaCfg.DLSEntry[i].Valid = TRUE;
+                                       pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut;
+                                       pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut;
+                                       NdisMoveMemory(pAd->StaCfg.DLSEntry[i].MacAddr, SA, MAC_ADDR_LEN);
+                                       if (HtCapabilityLen != 0)
+                                               pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
+                                       else
+                                               pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
+                                       pDLS = &pAd->StaCfg.DLSEntry[i];
+                                       pEntry = MacTableInsertDlsEntry(pAd, SA, i);
+
+                                       switch (MaxSupportedRateIn500Kbps)
+                                       {
+                                               case 108: MaxSupportedRate = RATE_54;   break;
+                                               case 96:  MaxSupportedRate = RATE_48;   break;
+                                               case 72:  MaxSupportedRate = RATE_36;   break;
+                                               case 48:  MaxSupportedRate = RATE_24;   break;
+                                               case 36:  MaxSupportedRate = RATE_18;   break;
+                                               case 24:  MaxSupportedRate = RATE_12;   break;
+                                               case 18:  MaxSupportedRate = RATE_9;    break;
+                                               case 12:  MaxSupportedRate = RATE_6;    break;
+                                               case 22:  MaxSupportedRate = RATE_11;   break;
+                                               case 11:  MaxSupportedRate = RATE_5_5;  break;
+                                               case 4:   MaxSupportedRate = RATE_2;    break;
+                                               case 2:   MaxSupportedRate = RATE_1;    break;
+                                               default:  MaxSupportedRate = RATE_11;   break;
+                                       }
+
+                                       pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
+
+                                       if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
+                                       {
+                                               pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
+                                               pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+                                               pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
+                                               pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+                                               pEntry->HTPhyMode.field.MODE = MODE_CCK;
+                                               pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+                                       }
+                                       else
+                                       {
+                                               pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
+                                               pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+                                               pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
+                                               pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+                                               pEntry->HTPhyMode.field.MODE = MODE_OFDM;
+                                               pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+                                       }
+
+                                       pEntry->MaxHTPhyMode.field.BW = BW_20;
+                                       pEntry->MinHTPhyMode.field.BW = BW_20;
+
+#ifdef DOT11_N_SUPPORT
+                                       pEntry->HTCapability.MCSSet[0] = 0;
+                                       pEntry->HTCapability.MCSSet[1] = 0;
+
+                                       // If this Entry supports 802.11n, upgrade to HT rate.
+                                       if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+                                       {
+                                               UCHAR   j, bitmask; //k,bitmask;
+                                               CHAR    ii;
+
+                                               DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsReqAction() Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                                                       SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+
+                                               if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
+                                               {
+                                                       pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
+                                               }
+                                               else
+                                               {
+                                                       pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+                                                       pAd->MacTab.fAnyStationNonGF = TRUE;
+                                                       pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
+                                               }
+
+                                               if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
+                                               {
+                                                       pEntry->MaxHTPhyMode.field.BW= BW_40;
+                                                       pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
+                                               }
+                                               else
+                                               {
+                                                       pEntry->MaxHTPhyMode.field.BW = BW_20;
+                                                       pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
+                                                       pAd->MacTab.fAnyStation20Only = TRUE;
+                                               }
+
+                                               // find max fixed rate
+                                               for (ii=15; ii>=0; ii--)
+                                               {
+                                                       j = ii/8;
+                                                       bitmask = (1<<(ii-(j*8)));
+                                                       if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
+                                                       {
+                                                               pEntry->MaxHTPhyMode.field.MCS = ii;
+                                                               break;
+                                                       }
+                                                       if (ii==0)
+                                                               break;
+                                               }
+
+
+                                               if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
+                                               {
+
+                                                       printk("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n",
+                                                               pAd->StaCfg.DesiredTransmitSetting.field.MCS);
+                                                       if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
+                                                       {
+                                                               // Fix MCS as HT Duplicated Mode
+                                                               pEntry->MaxHTPhyMode.field.BW = 1;
+                                                               pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+                                                               pEntry->MaxHTPhyMode.field.STBC = 0;
+                                                               pEntry->MaxHTPhyMode.field.ShortGI = 0;
+                                                               pEntry->MaxHTPhyMode.field.MCS = 32;
+                                                       }
+                                                       else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
+                                                       {
+                                                               // STA supports fixed MCS
+                                                               pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+                                                       }
+                                               }
+
+                                               pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
+                                               pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
+                                               pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
+                                               pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
+                                               pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
+                                               pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+
+                                               if (HtCapability.HtCapInfo.ShortGIfor20)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
+                                               if (HtCapability.HtCapInfo.ShortGIfor40)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
+                                               if (HtCapability.HtCapInfo.TxSTBC)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
+                                               if (HtCapability.HtCapInfo.RxSTBC)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
+                                               if (HtCapability.ExtHtCapInfo.PlusHTC)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
+                                               if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
+                                               if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
+
+                                               NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
+                                       }
+#endif // DOT11_N_SUPPORT //
+
+                                       pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+                                       pEntry->CurrTxRate = pEntry->MaxSupportedRate;
+                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
+
+                                       if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
+                                       {
+                                               PUCHAR pTable;
+                                               UCHAR TableSize = 0;
+
+                                               MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
+                                               pEntry->bAutoTxRateSwitch = TRUE;
+                                       }
+                                       else
+                                       {
+                                               pEntry->HTPhyMode.field.MODE    = pAd->StaCfg.HTPhyMode.field.MODE;
+                                               pEntry->HTPhyMode.field.MCS     = pAd->StaCfg.HTPhyMode.field.MCS;
+                                               pEntry->bAutoTxRateSwitch = FALSE;
+
+                                               RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
+                                       }
+                                       pEntry->RateLen = SupportedRatesLen;
+
+                                       break;
+                               }
+                       }
+               }
+               StatusCode = MLME_SUCCESS;
+
+               // can not find in table, create a new one
+               if (i < 0)
+               {
+                       StatusCode = MLME_QOS_UNSPECIFY;
+                       DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() DLSEntry table full(only can support %d DLS session) \n", MAX_NUM_OF_DLS_ENTRY - MAX_NUM_OF_INIT_DLS_ENTRY));
+               }
+               else
+               {
+                       DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() use entry(%d) %02x:%02x:%02x:%02x:%02x:%02x\n",
+                               i, SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+               }
+       }
+
+       ActHeaderInit(pAd, &DlsRspHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+
+       // Build basic frame first
+       if (StatusCode == MLME_SUCCESS)
+       {
+               MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
+                                               sizeof(HEADER_802_11),          &DlsRspHdr,
+                                               1,                                                      &Category,
+                                               1,                                                      &Action,
+                                               2,                                                      &StatusCode,
+                                               6,                                                      SA,
+                                               6,                                                      pAd->CurrentAddress,
+                                               2,                                                      &pAd->StaActive.CapabilityInfo,
+                                               1,                                                      &SupRateIe,
+                                               1,                                                      &pAd->MlmeAux.SupRateLen,
+                                               pAd->MlmeAux.SupRateLen,        pAd->MlmeAux.SupRate,
+                                               END_OF_ARGS);
+
+               if (pAd->MlmeAux.ExtRateLen != 0)
+               {
+                       MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
+                                                         1,                                            &ExtRateIe,
+                                                         1,                                            &pAd->MlmeAux.ExtRateLen,
+                                                         pAd->MlmeAux.ExtRateLen,      pAd->MlmeAux.ExtRate,
+                                                         END_OF_ARGS);
+                       FrameLen += tmp;
+               }
+
+#ifdef DOT11_N_SUPPORT
+               if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+               {
+                       UCHAR HtLen;
+
+#ifdef RT_BIG_ENDIAN
+                       HT_CAPABILITY_IE HtCapabilityTmp;
+#endif
+
+                       // add HT Capability IE
+                       HtLen = sizeof(HT_CAPABILITY_IE);
+#ifndef RT_BIG_ENDIAN
+                       MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
+                                                               1,                                              &HtCapIe,
+                                                               1,                                              &HtLen,
+                                                               HtLen,                                  &pAd->CommonCfg.HtCapability,
+                                                               END_OF_ARGS);
+#else
+                       NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
+                                                               *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+                                                               *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+                       MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
+                                                               1,                                              &HtCapIe,
+                                                               1,                                              &HtLen,
+                                                               HtLen,                                  &HtCapabilityTmp,
+                                                               END_OF_ARGS);
+#endif
+                       FrameLen = FrameLen + tmp;
+               }
+#endif // DOT11_N_SUPPORT //
+
+               if (pDLS && (pDLS->Status != DLS_FINISH))
+               {
+                       RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
+                       Timeout = DLS_TIMEOUT;
+                       RTMPSetTimer(&pDLS->Timer, Timeout);
+               }
+       }
+       else
+       {
+               MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
+                                               sizeof(HEADER_802_11),          &DlsRspHdr,
+                                               1,                                                      &Category,
+                                               1,                                                      &Action,
+                                               2,                                                      &StatusCode,
+                                               6,                                                      SA,
+                                               6,                                                      pAd->CurrentAddress,
+                                               END_OF_ARGS);
+       }
+
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID PeerDlsRspAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT          CapabilityInfo;
+       UCHAR           DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
+       USHORT          StatusCode;
+       SHORT           i;
+       BOOLEAN         TimerCancelled;
+       UCHAR           MaxSupportedRateIn500Kbps = 0;
+    UCHAR              SupportedRatesLen;
+    UCHAR              SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR           HtCapabilityLen;
+       HT_CAPABILITY_IE        HtCapability;
+
+       if (!pAd->CommonCfg.bDLSCapable)
+               return;
+
+       if (!INFRA_ON(pAd))
+               return;
+
+       if (!PeerDlsRspSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &StatusCode,
+                                                       &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability))
+               return;
+
+    // supported rates array may not be sorted. sort it and find the maximum rate
+    for (i=0; i<SupportedRatesLen; i++)
+    {
+        if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f))
+            MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f;
+    }
+
+       DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d, CapabilityInfo=0x%x\n",
+               SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], StatusCode, CapabilityInfo));
+
+       for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+       {
+               if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
+               {
+                       if (StatusCode == MLME_SUCCESS)
+                       {
+                               MAC_TABLE_ENTRY *pEntry;
+                               UCHAR MaxSupportedRate = RATE_11;
+
+                               pEntry = MacTableInsertDlsEntry(pAd, SA, i);
+
+                               switch (MaxSupportedRateIn500Kbps)
+                               {
+                                       case 108: MaxSupportedRate = RATE_54;   break;
+                                       case 96:  MaxSupportedRate = RATE_48;   break;
+                                       case 72:  MaxSupportedRate = RATE_36;   break;
+                                       case 48:  MaxSupportedRate = RATE_24;   break;
+                                       case 36:  MaxSupportedRate = RATE_18;   break;
+                                       case 24:  MaxSupportedRate = RATE_12;   break;
+                                       case 18:  MaxSupportedRate = RATE_9;    break;
+                                       case 12:  MaxSupportedRate = RATE_6;    break;
+                                       case 22:  MaxSupportedRate = RATE_11;   break;
+                                       case 11:  MaxSupportedRate = RATE_5_5;  break;
+                                       case 4:   MaxSupportedRate = RATE_2;    break;
+                                       case 2:   MaxSupportedRate = RATE_1;    break;
+                                       default:  MaxSupportedRate = RATE_11;   break;
+                               }
+
+                               pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
+
+                               if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
+                               {
+                                       pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
+                                       pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+                                       pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
+                                       pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+                                       pEntry->HTPhyMode.field.MODE = MODE_CCK;
+                                       pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+                               }
+                               else
+                               {
+                                       pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
+                                       pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+                                       pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
+                                       pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+                                       pEntry->HTPhyMode.field.MODE = MODE_OFDM;
+                                       pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+                               }
+
+                               pEntry->MaxHTPhyMode.field.BW = BW_20;
+                               pEntry->MinHTPhyMode.field.BW = BW_20;
+
+#ifdef DOT11_N_SUPPORT
+                               pEntry->HTCapability.MCSSet[0] = 0;
+                               pEntry->HTCapability.MCSSet[1] = 0;
+
+                               // If this Entry supports 802.11n, upgrade to HT rate.
+                               if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+                               {
+                                       UCHAR   j, bitmask; //k,bitmask;
+                                       CHAR    ii;
+
+                                       DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                                               SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+
+                                       if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
+                                       {
+                                               pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
+                                       }
+                                       else
+                                       {
+                                               pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+                                               pAd->MacTab.fAnyStationNonGF = TRUE;
+                                               pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
+                                       }
+
+                                       if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
+                                       {
+                                               pEntry->MaxHTPhyMode.field.BW= BW_40;
+                                               pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
+                                       }
+                                       else
+                                       {
+                                               pEntry->MaxHTPhyMode.field.BW = BW_20;
+                                               pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
+                                               pAd->MacTab.fAnyStation20Only = TRUE;
+                                       }
+
+                                       // find max fixed rate
+                                       for (ii=15; ii>=0; ii--)
+                                       {
+                                               j = ii/8;
+                                               bitmask = (1<<(ii-(j*8)));
+                                               if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
+                                               {
+                                                       pEntry->MaxHTPhyMode.field.MCS = ii;
+                                                       break;
+                                               }
+                                               if (ii==0)
+                                                       break;
+                                       }
+
+                                       if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
+                                       {
+                                               if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
+                                               {
+                                                       // Fix MCS as HT Duplicated Mode
+                                                       pEntry->MaxHTPhyMode.field.BW = 1;
+                                                       pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+                                                       pEntry->MaxHTPhyMode.field.STBC = 0;
+                                                       pEntry->MaxHTPhyMode.field.ShortGI = 0;
+                                                       pEntry->MaxHTPhyMode.field.MCS = 32;
+                                               }
+                                               else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
+                                               {
+                                                       // STA supports fixed MCS
+                                                       pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+                                               }
+                                       }
+
+                                       pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
+                                       pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
+                                       pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
+                                       pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
+                                       pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
+                                       pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+
+                                       if (HtCapability.HtCapInfo.ShortGIfor20)
+                                               CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
+                                       if (HtCapability.HtCapInfo.ShortGIfor40)
+                                               CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
+                                       if (HtCapability.HtCapInfo.TxSTBC)
+                                               CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
+                                       if (HtCapability.HtCapInfo.RxSTBC)
+                                               CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
+                                       if (HtCapability.ExtHtCapInfo.PlusHTC)
+                                               CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
+                                       if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
+                                               CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
+                                       if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
+                                               CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
+
+                                       NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
+                               }
+#endif // DOT11_N_SUPPORT //
+                               pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+                               pEntry->CurrTxRate = pEntry->MaxSupportedRate;
+                               CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
+
+                               if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
+                               {
+                                       PUCHAR pTable;
+                                       UCHAR TableSize = 0;
+
+                                       MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
+                                       pEntry->bAutoTxRateSwitch = TRUE;
+                               }
+                               else
+                               {
+                                       pEntry->HTPhyMode.field.MODE    = pAd->StaCfg.HTPhyMode.field.MODE;
+                                       pEntry->HTPhyMode.field.MCS     = pAd->StaCfg.HTPhyMode.field.MCS;
+                                       pEntry->bAutoTxRateSwitch = FALSE;
+
+                                       RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
+                               }
+                               pEntry->RateLen = SupportedRatesLen;
+
+                               if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+                               {
+                                       // If support WPA or WPA2, start STAKey hand shake,
+                                       // If failed hand shake, just tear down peer DLS
+                                       if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS)
+                                       {
+                                               MLME_DLS_REQ_STRUCT     MlmeDlsReq;
+                                               USHORT                          reason = REASON_QOS_CIPHER_NOT_SUPPORT;
+
+                                               DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+                                               MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+                                               pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+                                               pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                                               DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n"));
+                                       }
+                                       else
+                                       {
+                                               pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
+                                               DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n"));
+                                       }
+                               }
+                               else
+                               {
+                                       RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+                                       pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+                                       DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+                               }
+
+                               //initialize seq no for DLS frames.
+                               pAd->StaCfg.DLSEntry[i].Sequence = 0;
+                               if (HtCapabilityLen != 0)
+                                       pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
+                               else
+                                       pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
+                       }
+                       else
+                       {
+                               // DLS setup procedure failed.
+                               pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+                               pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                               RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+                               DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode));
+                       }
+               }
+       }
+
+       if (i >= MAX_NUM_OF_INIT_DLS_ENTRY)
+       {
+               DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() update timeout value \n"));
+               for (i=(MAX_NUM_OF_DLS_ENTRY-1); i>=MAX_NUM_OF_INIT_DLS_ENTRY; i--)
+               {
+                       if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
+                       {
+                               if (StatusCode == MLME_SUCCESS)
+                               {
+                                       MAC_TABLE_ENTRY *pEntry;
+                                       UCHAR MaxSupportedRate = RATE_11;
+
+                                       pEntry = MacTableInsertDlsEntry(pAd, SA, i);
+
+                                       switch (MaxSupportedRateIn500Kbps)
+                                       {
+                                               case 108: MaxSupportedRate = RATE_54;   break;
+                                               case 96:  MaxSupportedRate = RATE_48;   break;
+                                               case 72:  MaxSupportedRate = RATE_36;   break;
+                                               case 48:  MaxSupportedRate = RATE_24;   break;
+                                               case 36:  MaxSupportedRate = RATE_18;   break;
+                                               case 24:  MaxSupportedRate = RATE_12;   break;
+                                               case 18:  MaxSupportedRate = RATE_9;    break;
+                                               case 12:  MaxSupportedRate = RATE_6;    break;
+                                               case 22:  MaxSupportedRate = RATE_11;   break;
+                                               case 11:  MaxSupportedRate = RATE_5_5;  break;
+                                               case 4:   MaxSupportedRate = RATE_2;    break;
+                                               case 2:   MaxSupportedRate = RATE_1;    break;
+                                               default:  MaxSupportedRate = RATE_11;   break;
+                                       }
+
+                                       pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
+
+                                       if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
+                                       {
+                                               pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
+                                               pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+                                               pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
+                                               pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+                                               pEntry->HTPhyMode.field.MODE = MODE_CCK;
+                                               pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+                                       }
+                                       else
+                                       {
+                                               pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
+                                               pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+                                               pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
+                                               pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+                                               pEntry->HTPhyMode.field.MODE = MODE_OFDM;
+                                               pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+                                       }
+
+                                       pEntry->MaxHTPhyMode.field.BW = BW_20;
+                                       pEntry->MinHTPhyMode.field.BW = BW_20;
+
+#ifdef DOT11_N_SUPPORT
+                                       pEntry->HTCapability.MCSSet[0] = 0;
+                                       pEntry->HTCapability.MCSSet[1] = 0;
+
+                                       // If this Entry supports 802.11n, upgrade to HT rate.
+                                       if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+                                       {
+                                               UCHAR   j, bitmask; //k,bitmask;
+                                               CHAR    ii;
+
+                                               DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                                                       SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+
+                                               if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
+                                               {
+                                                       pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
+                                               }
+                                               else
+                                               {
+                                                       pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+                                                       pAd->MacTab.fAnyStationNonGF = TRUE;
+                                                       pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
+                                               }
+
+                                               if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
+                                               {
+                                                       pEntry->MaxHTPhyMode.field.BW= BW_40;
+                                                       pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
+                                               }
+                                               else
+                                               {
+                                                       pEntry->MaxHTPhyMode.field.BW = BW_20;
+                                                       pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
+                                                       pAd->MacTab.fAnyStation20Only = TRUE;
+                                               }
+
+                                               // find max fixed rate
+                                               for (ii=15; ii>=0; ii--)
+                                               {
+                                                       j = ii/8;
+                                                       bitmask = (1<<(ii-(j*8)));
+                                                       if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
+                                                       {
+                                                               pEntry->MaxHTPhyMode.field.MCS = ii;
+                                                               break;
+                                                       }
+                                                       if (ii==0)
+                                                               break;
+                                               }
+
+                                               if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
+                                               {
+                                                       printk("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n",
+                                                               pAd->StaCfg.DesiredTransmitSetting.field.MCS);
+                                                       if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
+                                                       {
+                                                               // Fix MCS as HT Duplicated Mode
+                                                               pEntry->MaxHTPhyMode.field.BW = 1;
+                                                               pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+                                                               pEntry->MaxHTPhyMode.field.STBC = 0;
+                                                               pEntry->MaxHTPhyMode.field.ShortGI = 0;
+                                                               pEntry->MaxHTPhyMode.field.MCS = 32;
+                                                       }
+                                                       else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
+                                                       {
+                                                               // STA supports fixed MCS
+                                                               pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+                                                       }
+                                               }
+
+                                               pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
+                                               pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
+                                               pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
+                                               pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
+                                               pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
+                                               pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+
+                                               if (HtCapability.HtCapInfo.ShortGIfor20)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
+                                               if (HtCapability.HtCapInfo.ShortGIfor40)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
+                                               if (HtCapability.HtCapInfo.TxSTBC)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
+                                               if (HtCapability.HtCapInfo.RxSTBC)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
+                                               if (HtCapability.ExtHtCapInfo.PlusHTC)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
+                                               if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
+                                               if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
+                                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
+
+                                               NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
+                                       }
+#endif // DOT11_N_SUPPORT //
+
+                                       pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+                                       pEntry->CurrTxRate = pEntry->MaxSupportedRate;
+                                       CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
+
+                                       if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
+                                       {
+                                               PUCHAR pTable;
+                                               UCHAR TableSize = 0;
+
+                                               MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
+                                               pEntry->bAutoTxRateSwitch = TRUE;
+                                       }
+                                       else
+                                       {
+                                               pEntry->HTPhyMode.field.MODE    = pAd->StaCfg.HTPhyMode.field.MODE;
+                                               pEntry->HTPhyMode.field.MCS     = pAd->StaCfg.HTPhyMode.field.MCS;
+                                               pEntry->bAutoTxRateSwitch = FALSE;
+
+                                               RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
+                                       }
+                                       pEntry->RateLen = SupportedRatesLen;
+
+                                       if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+                                       {
+                                               // If support WPA or WPA2, start STAKey hand shake,
+                                               // If failed hand shake, just tear down peer DLS
+                                               if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS)
+                                               {
+                                                       MLME_DLS_REQ_STRUCT     MlmeDlsReq;
+                                                       USHORT                          reason = REASON_QOS_CIPHER_NOT_SUPPORT;
+
+                                                       DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+                                                       MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+                                                       pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+                                                       pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                                                       DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n"));
+                                               }
+                                               else
+                                               {
+                                                       pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
+                                                       DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n"));
+                                               }
+                                       }
+                                       else
+                                       {
+                                               RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+                                               pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+                                               DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+                                       }
+                                       pAd->StaCfg.DLSEntry[i].Sequence = 0;
+                                       if (HtCapabilityLen != 0)
+                                               pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
+                                       else
+                                               pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
+                               }
+                               else
+                               {
+                                       // DLS setup procedure failed.
+                                       pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+                                       pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                                       RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+                                       DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode));
+                               }
+                       }
+               }
+       }
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID MlmeDlsTearDownAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+       PUCHAR                  pOutBuffer = NULL;
+       NDIS_STATUS             NStatus;
+       ULONG                   FrameLen = 0;
+       UCHAR                   Category = CATEGORY_DLS;
+       UCHAR                   Action = ACTION_DLS_TEARDOWN;
+       USHORT                  ReasonCode = REASON_QOS_UNSPECIFY;
+       HEADER_802_11   DlsTearDownHdr;
+       PRT_802_11_DLS  pDLS;
+       BOOLEAN                 TimerCancelled;
+       UCHAR                   i;
+
+       if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &ReasonCode))
+               return;
+
+       DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsTearDownAction() with ReasonCode=%d \n", ReasonCode));
+
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if (NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsTearDownAction() allocate memory failed \n"));
+               return;
+       }
+
+       ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+
+       // Build basic frame first
+       MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
+                                       sizeof(HEADER_802_11),          &DlsTearDownHdr,
+                                       1,                                                      &Category,
+                                       1,                                                      &Action,
+                                       6,                                                      &pDLS->MacAddr,
+                                       6,                                                      pAd->CurrentAddress,
+                                       2,                                                      &ReasonCode,
+                                       END_OF_ARGS);
+
+       MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+       RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
+
+       // Remove key in local dls table entry
+       for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+       {
+               if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+               {
+                       MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+               }
+       }
+
+       // clear peer dls table entry
+       for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++)
+       {
+               if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+               {
+                       pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
+                       pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                       RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+                       MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+               }
+       }
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID PeerDlsTearDownAction(
+    IN PRTMP_ADAPTER pAd,
+    IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR                   DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
+       USHORT                  ReasonCode;
+       UINT                    i;
+       BOOLEAN                 TimerCancelled;
+
+       if (!pAd->CommonCfg.bDLSCapable)
+               return;
+
+       if (!INFRA_ON(pAd))
+               return;
+
+       if (!PeerDlsTearDownSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &ReasonCode))
+               return;
+
+       DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x with ReasonCode=%d\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], ReasonCode));
+
+       // clear local dls table entry
+       for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+       {
+               if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
+               {
+                       pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
+                       pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                       RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+                       //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
+                       //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
+                       MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+               }
+       }
+
+       // clear peer dls table entry
+       for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+       {
+               if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
+               {
+                       pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
+                       pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                       RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+                       //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
+                       //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
+                       MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+               }
+       }
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID RTMPCheckDLSTimeOut(
+       IN PRTMP_ADAPTER        pAd)
+{
+       ULONG                           i;
+       MLME_DLS_REQ_STRUCT     MlmeDlsReq;
+       USHORT                          reason = REASON_QOS_UNSPECIFY;
+
+       if (! pAd->CommonCfg.bDLSCapable)
+               return;
+
+       if (! INFRA_ON(pAd))
+               return;
+
+       // If timeout value is equaled to zero, it means always not be timeout.
+
+       // update local dls table entry
+       for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+       {
+               if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+                       && (pAd->StaCfg.DLSEntry[i].TimeOut != 0))
+               {
+                       pAd->StaCfg.DLSEntry[i].CountDownTimer --;
+
+                       if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0)
+                       {
+                               reason = REASON_QOS_REQUEST_TIMEOUT;
+                               pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                               pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
+                               DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+                               MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+                       }
+               }
+       }
+
+       // update peer dls table entry
+       for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+       {
+               if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+                       && (pAd->StaCfg.DLSEntry[i].TimeOut != 0))
+               {
+                       pAd->StaCfg.DLSEntry[i].CountDownTimer --;
+
+                       if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0)
+                       {
+                               reason = REASON_QOS_REQUEST_TIMEOUT;
+                               pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                               pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
+                               DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+                               MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+                       }
+               }
+       }
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+BOOLEAN RTMPRcvFrameDLSCheck(
+       IN PRTMP_ADAPTER        pAd,
+       IN PHEADER_802_11       pHeader,
+       IN ULONG                        Len,
+       IN PRT28XX_RXD_STRUC    pRxD)
+{
+       ULONG                   i;
+       BOOLEAN                 bFindEntry = FALSE;
+       BOOLEAN                 bSTAKeyFrame = FALSE;
+       PEAPOL_PACKET   pEap;
+       PUCHAR                  pProto, pAddr = NULL;
+       PUCHAR                  pSTAKey = NULL;
+       UCHAR                   ZeroReplay[LEN_KEY_DESC_REPLAY];
+       UCHAR                   Mic[16], OldMic[16];
+       UCHAR                   digest[80];
+       UCHAR                   DlsPTK[80];
+       UCHAR                   temp[64];
+       BOOLEAN                 TimerCancelled;
+       CIPHER_KEY              PairwiseKey;
+
+
+       if (! pAd->CommonCfg.bDLSCapable)
+               return bSTAKeyFrame;
+
+       if (! INFRA_ON(pAd))
+               return bSTAKeyFrame;
+
+       if (! (pHeader->FC.SubType & 0x08))
+               return bSTAKeyFrame;
+
+       if (Len < LENGTH_802_11 + 6 + 2 + 2)
+               return bSTAKeyFrame;
+
+       pProto  = (PUCHAR)pHeader + LENGTH_802_11 + 2 + 6;      // QOS Control field , 0xAA 0xAA 0xAA 0x00 0x00 0x00
+       pAddr   = pHeader->Addr2;
+
+       // L2PAD bit on will pad 2 bytes at LLC
+       if (pRxD->L2PAD)
+       {
+               pProto += 2;
+       }
+
+       if (RTMPEqualMemory(EAPOL, pProto, 2) && (pAd->StaCfg.AuthMode >=  Ndis802_11AuthModeWPA))
+       {
+               pEap = (PEAPOL_PACKET) (pProto + 2);
+
+               DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff Len=%ld, DataLen=%d, KeyMic=%d, Install=%d, KeyAck=%d, Secure=%d, EKD_DL=%d, Error=%d, Request=%d\n", Len,
+                                                                                    (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16),
+                                                                                    pEap->KeyDesc.KeyInfo.KeyMic,
+                                                                                    pEap->KeyDesc.KeyInfo.Install,
+                                                                                    pEap->KeyDesc.KeyInfo.KeyAck,
+                                                                                    pEap->KeyDesc.KeyInfo.Secure,
+                                                                                    pEap->KeyDesc.KeyInfo.EKD_DL,
+                                                                                    pEap->KeyDesc.KeyInfo.Error,
+                                                                                    pEap->KeyDesc.KeyInfo.Request));
+
+               if ((Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16)) && pEap->KeyDesc.KeyInfo.KeyMic
+                       && pEap->KeyDesc.KeyInfo.Install && pEap->KeyDesc.KeyInfo.KeyAck && pEap->KeyDesc.KeyInfo.Secure
+                       && pEap->KeyDesc.KeyInfo.EKD_DL && !pEap->KeyDesc.KeyInfo.Error && !pEap->KeyDesc.KeyInfo.Request)
+               {
+                       // First validate replay counter, only accept message with larger replay counter
+                       // Let equal pass, some AP start with all zero replay counter
+                       NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
+                       if ((RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
+                               (RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
+                               return bSTAKeyFrame;
+
+                       //RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+                       RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+                       DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter (%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n",
+                               pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2],
+                               pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4],     pAd->StaCfg.ReplayCounter[5],
+                               pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1]));
+
+                       // put these code segment to get the replay counter
+                       if (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)
+                               return bSTAKeyFrame;
+
+                       // Check MIC value
+                       // Save the MIC and replace with zero
+                       // use proprietary PTK
+                       NdisZeroMemory(temp, 64);
+                       NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
+                       WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
+
+                       NdisMoveMemory(OldMic, pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+                       NdisZeroMemory(pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+                       if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+                       {
+                               // AES
+                               HMAC_SHA1((PUCHAR) pEap, pEap->Body_Len[1] + 4, DlsPTK, LEN_EAP_MICK, digest);
+                               NdisMoveMemory(Mic,     digest, LEN_KEY_DESC_MIC);
+                       }
+                       else
+                       {
+                               hmac_md5(DlsPTK, LEN_EAP_MICK, (PUCHAR) pEap, pEap->Body_Len[1] + 4, Mic);
+                       }
+
+                       if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
+                       {
+                               DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in Msg1 of STAKey handshake! \n"));
+                               return bSTAKeyFrame;
+                       }
+                       else
+                               DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in Msg1 of STAKey handshake! \n"));
+#if 1
+                       if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0C)
+                               && (pEap->KeyDesc.KeyData[4] == 0x43) && (pEap->KeyDesc.KeyData[5] == 0x02))
+                       {
+                               pAddr                   = pEap->KeyDesc.KeyData + 8;            // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2)
+                               pSTAKey                 = pEap->KeyDesc.KeyData + 14;   // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6)
+
+                               DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%ld, KeyDataLen=%d\n",
+                                       pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1]));
+
+                               bSTAKeyFrame = TRUE;
+                       }
+#else
+                       if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0F)
+                               && (pEap->KeyDesc.KeyData[4] == 0xAC) && (pEap->KeyDesc.KeyData[5] == 0x02))
+                       {
+                               pAddr                   = pEap->KeyDesc.KeyData + 8;            // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2)
+                               pSTAKey                 = pEap->KeyDesc.KeyData + 14;   // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6)
+
+                               DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%d, KeyDataLen=%d\n",
+                                       pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1]));
+
+                               bSTAKeyFrame = TRUE;
+                       }
+#endif
+
+               }
+               else if (Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE))
+               {
+#if 0
+                       RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+#endif
+                       RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+                       DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter 2(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n",
+                               pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2],
+                               pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4],     pAd->StaCfg.ReplayCounter[5],
+                               pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1]));
+
+               }
+       }
+
+       // If timeout value is equaled to zero, it means always not be timeout.
+       // update local dls table entry
+       for (i= 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+       {
+               if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+               {
+                       if (bSTAKeyFrame)
+                       {
+                               PMAC_TABLE_ENTRY pEntry;
+
+                               // STAKey frame, add pairwise key table
+                               pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+                               RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+
+                               PairwiseKey.KeyLen = LEN_TKIP_EK;
+                               NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK);
+                               NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK);
+                               NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK);
+
+                               PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg;
+
+                               pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
+                               //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE);     // reserve 0 for multicast, 1 for unicast
+                               //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
+                               // Add Pair-wise key to Asic
+#ifdef RT2870
+                               {
+                                       RT_ADD_PAIRWISE_KEY_ENTRY KeyInfo;
+                                       COPY_MAC_ADDR(KeyInfo.MacAddr,pAd->StaCfg.DLSEntry[i].MacAddr);
+                                       KeyInfo.MacTabMatchWCID=pAd->StaCfg.DLSEntry[i].MacTabMatchWCID;
+                                       NdisMoveMemory(&KeyInfo.CipherKey,  &PairwiseKey,sizeof(CIPHER_KEY));
+                                       RTUSBEnqueueInternalCmd(pAd, RT_CMD_SET_KEY_TABLE, &KeyInfo, sizeof(RT_ADD_PAIRWISE_KEY_ENTRY));
+                               }
+                               {
+                                       PMAC_TABLE_ENTRY pDLSEntry;
+                                       pDLSEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
+                                       pDLSEntry->PairwiseKey.CipherAlg=PairwiseKey.CipherAlg;
+                                       RTUSBEnqueueInternalCmd(pAd, RT_CMD_SET_RX_WCID_TABLE, pDLSEntry, sizeof(MAC_TABLE_ENTRY));
+                               }
+#endif // RT2870 //
+                               NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
+                               DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Peer STA MAC Address STAKey) \n"));
+
+                               RTMPSendSTAKeyHandShake(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+
+                               DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Initiator side)\n"));
+                       }
+                       else
+                       {
+                               // Data frame, update timeout value
+                               if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+                               {
+                                       pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
+                                       //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
+                               }
+                       }
+
+                       bFindEntry = TRUE;
+               }
+       }
+
+       // update peer dls table entry
+       for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+       {
+               if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+               {
+                       if (bSTAKeyFrame)
+                       {
+                               PMAC_TABLE_ENTRY pEntry = NULL;
+
+                               // STAKey frame, add pairwise key table, and send STAkey Msg-2
+                               pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+                               RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+
+                               PairwiseKey.KeyLen = LEN_TKIP_EK;
+                               NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK);
+                               NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK);
+                               NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK);
+
+                               PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg;
+
+                               pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
+                               //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE);     // reserve 0 for multicast, 1 for unicast
+                               //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
+                               // Add Pair-wise key to Asic
+#ifdef RT2870
+                               {
+                                       RT_ADD_PAIRWISE_KEY_ENTRY KeyInfo;
+                                       COPY_MAC_ADDR(KeyInfo.MacAddr,pAd->StaCfg.DLSEntry[i].MacAddr);
+                                       KeyInfo.MacTabMatchWCID=pAd->StaCfg.DLSEntry[i].MacTabMatchWCID;
+                                       NdisMoveMemory(&KeyInfo.CipherKey,  &PairwiseKey,sizeof(CIPHER_KEY));
+                                       RTUSBEnqueueInternalCmd(pAd, RT_CMD_SET_KEY_TABLE, &KeyInfo, sizeof(RT_ADD_PAIRWISE_KEY_ENTRY));
+                               }
+                               {
+                                       PMAC_TABLE_ENTRY pDLSEntry;
+                                       pDLSEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
+                                       pDLSEntry->PairwiseKey.CipherAlg=PairwiseKey.CipherAlg;
+                                       RTUSBEnqueueInternalCmd(pAd, RT_CMD_SET_RX_WCID_TABLE, pDLSEntry, sizeof(MAC_TABLE_ENTRY));
+                               }
+#endif // RT2870 //
+                               NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
+                               DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Initiator STA MAC Address STAKey)\n"));
+
+                               // If support WPA or WPA2, start STAKey hand shake,
+                               // If failed hand shake, just tear down peer DLS
+                               if (RTMPSendSTAKeyHandShake(pAd, pAddr) != NDIS_STATUS_SUCCESS)
+                               {
+                                       MLME_DLS_REQ_STRUCT     MlmeDlsReq;
+                                       USHORT                          reason = REASON_QOS_CIPHER_NOT_SUPPORT;
+
+                                       pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
+                                       pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
+                                       DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+                                       MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+                               }
+                               else
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Peer side)\n"));
+                               }
+                       }
+                       else
+                       {
+                               // Data frame, update timeout value
+                               if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+                               {
+                                       pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
+                               }
+                       }
+
+                       bFindEntry = TRUE;
+               }
+       }
+
+
+       return bSTAKeyFrame;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Check if the frame can be sent through DLS direct link interface
+
+       Arguments:
+               pAd             Pointer to adapter
+
+       Return Value:
+               DLS entry index
+
+       Note:
+
+       ========================================================================
+*/
+INT    RTMPCheckDLSFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pDA)
+{
+       INT rval = -1;
+       INT     i;
+
+       if (!pAd->CommonCfg.bDLSCapable)
+               return rval;
+
+       if (!INFRA_ON(pAd))
+               return rval;
+
+       do{
+               // check local dls table entry
+               for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+               {
+                       if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
+                               MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
+                       {
+                               rval = i;
+                               break;
+                       }
+               }
+
+               // check peer dls table entry
+               for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+               {
+                       if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
+                               MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
+                       {
+                               rval = i;
+                               break;
+                       }
+               }
+       } while (FALSE);
+
+       return rval;
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+VOID RTMPSendDLSTearDownFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pDA)
+{
+       PUCHAR                  pOutBuffer = NULL;
+       NDIS_STATUS             NStatus;
+       HEADER_802_11   DlsTearDownHdr;
+       ULONG                   FrameLen = 0;
+       USHORT                  Reason = REASON_QOS_QSTA_LEAVING_QBSS;
+       UCHAR                   Category = CATEGORY_DLS;
+       UCHAR                   Action = ACTION_DLS_TEARDOWN;
+       UCHAR                   i = 0;
+
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
+               RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
+               return;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame \n"));
+
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if (NStatus != NDIS_STATUS_SUCCESS)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("ASSOC - RTMPSendDLSTearDownFrame() allocate memory failed \n"));
+               return;
+       }
+
+       ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+       MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
+                                       sizeof(HEADER_802_11),          &DlsTearDownHdr,
+                                       1,                                                      &Category,
+                                       1,                                                      &Action,
+                                       6,                                                      pDA,
+                                       6,                                                      pAd->CurrentAddress,
+                                       2,                                                      &Reason,
+                                       END_OF_ARGS);
+
+       MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       // Remove key in local dls table entry
+       for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+       {
+               if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+                       && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
+               {
+                       MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+               }
+       }
+
+       // Remove key in peer dls table entry
+       for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+       {
+               if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+                       && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
+               {
+                       MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+               }
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame and remove key in (i=%d) \n", i));
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+NDIS_STATUS RTMPSendSTAKeyRequest(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pDA)
+{
+       UCHAR                           Header802_3[14];
+       NDIS_STATUS                     NStatus;
+       ULONG                           FrameLen = 0;
+       EAPOL_PACKET            Packet;
+       UCHAR                           Mic[16];
+       UCHAR                           digest[80];
+       PUCHAR                          pOutBuffer = NULL;
+       PNDIS_PACKET            pNdisPacket;
+       UCHAR                           temp[64];
+       UCHAR                           DlsPTK[80];
+
+       DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyRequest() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5]));
+
+       pAd->Sequence ++;
+       MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
+
+       // Zero message body
+       NdisZeroMemory(&Packet, sizeof(Packet));
+       Packet.ProVer = EAPOL_VER;
+       Packet.ProType    = EAPOLKey;
+       Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN;             // data field contain KDE andPeer MAC address
+
+       // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE)
+       if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+    {
+        Packet.KeyDesc.Type = WPA1_KEY_DESC;
+    }
+    else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+    {
+        Packet.KeyDesc.Type = WPA2_KEY_DESC;
+    }
+
+       // Key descriptor version
+       Packet.KeyDesc.KeyInfo.KeyDescVer =
+               (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
+
+       Packet.KeyDesc.KeyInfo.KeyMic   = 1;
+       Packet.KeyDesc.KeyInfo.Secure   = 1;
+       Packet.KeyDesc.KeyInfo.Request  = 1;
+
+       Packet.KeyDesc.KeyDataLen[1]    = 12;
+
+       // use our own OUI to distinguish proprietary with standard.
+       Packet.KeyDesc.KeyData[0]               = 0xDD;
+       Packet.KeyDesc.KeyData[1]               = 0x0A;
+       Packet.KeyDesc.KeyData[2]               = 0x00;
+       Packet.KeyDesc.KeyData[3]               = 0x0C;
+       Packet.KeyDesc.KeyData[4]               = 0x43;
+       Packet.KeyDesc.KeyData[5]               = 0x03;
+       NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN);
+
+       NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // Allocate buffer for transmitting message
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+       if (NStatus     != NDIS_STATUS_SUCCESS)
+               return NStatus;
+
+       // Prepare EAPOL frame for MIC calculation
+       // Be careful, only EAPOL frame is counted for MIC calculation
+       MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+                             Packet.Body_Len[1] + 4,    &Packet,
+                             END_OF_ARGS);
+
+       // use proprietary PTK
+       NdisZeroMemory(temp, 64);
+       NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
+       WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
+
+       // calculate MIC
+       if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+       {
+               // AES
+               NdisZeroMemory(digest,  sizeof(digest));
+               HMAC_SHA1(pOutBuffer, FrameLen, DlsPTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
+       }
+       else
+       {
+               NdisZeroMemory(Mic,     sizeof(Mic));
+               hmac_md5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
+               NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
+       }
+
+       MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+                         sizeof(Header802_3),  Header802_3,
+                             Packet.Body_Len[1] + 4,   &Packet,
+                             END_OF_ARGS);
+
+       NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen);
+       if (NStatus == NDIS_STATUS_SUCCESS)
+       {
+               RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID);
+               STASendPacket(pAd, pNdisPacket);
+               RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+       }
+
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyRequest- Send STAKey request (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen));
+
+       return NStatus;
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+NDIS_STATUS RTMPSendSTAKeyHandShake(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pDA)
+{
+       UCHAR                           Header802_3[14];
+       NDIS_STATUS                     NStatus;
+       ULONG                           FrameLen = 0;
+       EAPOL_PACKET            Packet;
+       UCHAR                           Mic[16];
+       UCHAR                           digest[80];
+       PUCHAR                          pOutBuffer = NULL;
+       PNDIS_PACKET            pNdisPacket;
+       UCHAR                           temp[64];
+       UCHAR                           DlsPTK[80];                     // Due to dirver can not get PTK, use proprietary PTK
+
+       DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyHandShake() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5]));
+
+       pAd->Sequence ++;
+       MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
+
+       // Zero message body
+       NdisZeroMemory(&Packet, sizeof(Packet));
+       Packet.ProVer = EAPOL_VER;
+       Packet.ProType    = EAPOLKey;
+       Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN;             // data field contain KDE and Peer MAC address
+
+       // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE)
+       if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+    {
+        Packet.KeyDesc.Type = WPA1_KEY_DESC;
+    }
+    else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+    {
+        Packet.KeyDesc.Type = WPA2_KEY_DESC;
+    }
+
+       // Key descriptor version
+       Packet.KeyDesc.KeyInfo.KeyDescVer =
+               (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
+
+       Packet.KeyDesc.KeyInfo.KeyMic   = 1;
+       Packet.KeyDesc.KeyInfo.Secure   = 1;
+
+       Packet.KeyDesc.KeyDataLen[1]    = 12;
+
+       // use our own OUI to distinguish proprietary with standard.
+       Packet.KeyDesc.KeyData[0]               = 0xDD;
+       Packet.KeyDesc.KeyData[1]               = 0x0A;
+       Packet.KeyDesc.KeyData[2]               = 0x00;
+       Packet.KeyDesc.KeyData[3]               = 0x0C;
+       Packet.KeyDesc.KeyData[4]               = 0x43;
+       Packet.KeyDesc.KeyData[5]               = 0x03;
+       NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN);
+
+       NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // Allocate buffer for transmitting message
+       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+       if (NStatus     != NDIS_STATUS_SUCCESS)
+               return NStatus;
+
+       // Prepare EAPOL frame for MIC calculation
+       // Be careful, only EAPOL frame is counted for MIC calculation
+       MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+                             Packet.Body_Len[1] + 4,    &Packet,
+                             END_OF_ARGS);
+
+       // use proprietary PTK
+       NdisZeroMemory(temp, 64);
+       NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
+       WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
+
+       // calculate MIC
+       if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+       {
+               // AES
+               NdisZeroMemory(digest,  sizeof(digest));
+               HMAC_SHA1(pOutBuffer, FrameLen, DlsPTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
+       }
+       else
+       {
+               NdisZeroMemory(Mic,     sizeof(Mic));
+               hmac_md5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
+               NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
+       }
+
+       MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+                         sizeof(Header802_3),  Header802_3,
+                             Packet.Body_Len[1] + 4,   &Packet,
+                             END_OF_ARGS);
+
+       NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen);
+       if (NStatus == NDIS_STATUS_SUCCESS)
+       {
+               RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID);
+               STASendPacket(pAd, pNdisPacket);
+               RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+       }
+
+       MlmeFreeMemory(pAd, pOutBuffer);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyHandShake- Send STAKey Message-2 (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen));
+
+       return NStatus;
+}
+
+VOID DlsTimeoutAction(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3)
+{
+       MLME_DLS_REQ_STRUCT             MlmeDlsReq;
+       USHORT                                  reason;
+       PRT_802_11_DLS                  pDLS = (PRT_802_11_DLS)FunctionContext;
+       PRTMP_ADAPTER                   pAd = pDLS->pAd;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("DlsTimeout - Tear down DLS links (%02x:%02x:%02x:%02x:%02x:%02x)\n",
+               pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5]));
+
+       if ((pDLS) && (pDLS->Valid))
+       {
+               reason                  = REASON_QOS_REQUEST_TIMEOUT;
+               pDLS->Valid             = FALSE;
+               pDLS->Status    = DLS_NONE;
+               DlsParmFill(pAd, &MlmeDlsReq, pDLS, reason);
+               MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+               RT28XX_MLME_HANDLER(pAd);
+       }
+}
+
+/*
+================================================================
+Description : because DLS and CLI share the same WCID table in ASIC.
+Mesh entry also insert to pAd->MacTab.content[].  Such is marked as ValidAsDls = TRUE.
+Also fills the pairwise key.
+Because front MAX_AID_BA entries have direct mapping to BAEntry, which is only used as CLI. So we insert Dls
+from index MAX_AID_BA.
+================================================================
+*/
+MAC_TABLE_ENTRY *MacTableInsertDlsEntry(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR      pAddr,
+       IN  UINT        DlsEntryIdx)
+{
+       PMAC_TABLE_ENTRY pEntry = NULL;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableInsertDlsEntry\n"));
+       // if FULL, return
+       if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
+               return NULL;
+
+       do
+       {
+               if((pEntry = DlsEntryTableLookup(pAd, pAddr, TRUE)) != NULL)
+                       break;
+
+               // allocate one MAC entry
+               pEntry = MacTableInsertEntry(pAd, pAddr, DlsEntryIdx + MIN_NET_DEVICE_FOR_DLS, TRUE);
+               if (pEntry)
+               {
+                       pAd->StaCfg.DLSEntry[DlsEntryIdx].MacTabMatchWCID = pEntry->Aid;
+                       pEntry->MatchDlsEntryIdx = DlsEntryIdx;
+                       pEntry->AuthMode = pAd->StaCfg.AuthMode;
+                       pEntry->WepStatus = pAd->StaCfg.WepStatus;
+                       pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertDlsEntry - allocate entry #%d, Total= %d\n",pEntry->Aid, pAd->MacTab.Size));
+
+                       // If legacy WEP is used, set pair-wise cipherAlg into WCID attribute table for this entry
+                       if ((pEntry->ValidAsDls) && (pEntry->WepStatus == Ndis802_11WEPEnabled))
+                       {
+                               UCHAR KeyIdx = 0;
+                               UCHAR CipherAlg = 0;
+
+                               KeyIdx  = pAd->StaCfg.DefaultKeyId;
+
+                               CipherAlg       = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
+
+                               RTMPAddWcidAttributeEntry(pAd,
+                                                                                       BSS0,
+                                                                                       pAd->StaCfg.DefaultKeyId,
+                                                                                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+                                                                                       pEntry);
+                       }
+
+                       break;
+               }
+       } while(FALSE);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableInsertDlsEntry\n"));
+
+       return pEntry;
+}
+
+
+/*
+       ==========================================================================
+       Description:
+               Delete all Mesh Entry in pAd->MacTab
+       ==========================================================================
+ */
+BOOLEAN MacTableDeleteDlsEntry(
+       IN PRTMP_ADAPTER pAd,
+       IN USHORT wcid,
+       IN PUCHAR pAddr)
+{
+       DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableDeleteDlsEntry\n"));
+
+       if (!VALID_WCID(wcid))
+               return FALSE;
+
+       MacTableDeleteEntry(pAd, wcid, pAddr);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableDeleteDlsEntry\n"));
+
+       return TRUE;
+}
+
+MAC_TABLE_ENTRY *DlsEntryTableLookup(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR       pAddr,
+       IN BOOLEAN      bResetIdelCount)
+{
+       ULONG HashIdx;
+       MAC_TABLE_ENTRY *pEntry = NULL;
+
+       RTMP_SEM_LOCK(&pAd->MacTabLock);
+       HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+       pEntry = pAd->MacTab.Hash[HashIdx];
+
+       while (pEntry)
+       {
+               if ((pEntry->ValidAsDls == TRUE)
+                       && MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
+               {
+                       if(bResetIdelCount)
+                               pEntry->NoDataIdleCount = 0;
+                       break;
+               }
+               else
+                       pEntry = pEntry->pNext;
+       }
+
+       RTMP_SEM_UNLOCK(&pAd->MacTabLock);
+       return pEntry;
+}
+
+MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid(
+       IN PRTMP_ADAPTER pAd,
+       IN UCHAR        wcid,
+       IN PUCHAR       pAddr,
+       IN BOOLEAN      bResetIdelCount)
+{
+       ULONG DLsIndex;
+       PMAC_TABLE_ENTRY pCurEntry = NULL;
+       PMAC_TABLE_ENTRY pEntry = NULL;
+
+       if (!VALID_WCID(wcid))
+               return NULL;
+
+       RTMP_SEM_LOCK(&pAd->MacTabLock);
+
+       do
+       {
+               pCurEntry = &pAd->MacTab.Content[wcid];
+
+               DLsIndex = 0xff;
+               if ((pCurEntry) && (pCurEntry->ValidAsDls== TRUE))
+               {
+                       DLsIndex = pCurEntry->MatchDlsEntryIdx;
+               }
+
+               if (DLsIndex == 0xff)
+                       break;
+
+               if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr))
+               {
+                       if(bResetIdelCount)
+                               pCurEntry->NoDataIdleCount = 0;
+                       pEntry = pCurEntry;
+                       break;
+               }
+       } while(FALSE);
+
+       RTMP_SEM_UNLOCK(&pAd->MacTabLock);
+
+       return pEntry;
+}
+
+INT Set_DlsEntryInfo_Display_Proc(
+       IN PRTMP_ADAPTER pAd,
+       IN PUCHAR arg)
+{
+       INT i;
+
+       printk("\n%-19s%-8s\n", "MAC", "TIMEOUT\n");
+       for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
+       {
+               if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+               {
+                       PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[pAd->StaCfg.DLSEntry[i].MacTabMatchWCID];
+
+                       printk("%02x:%02x:%02x:%02x:%02x:%02x  ",
+                               pAd->StaCfg.DLSEntry[i].MacAddr[0], pAd->StaCfg.DLSEntry[i].MacAddr[1], pAd->StaCfg.DLSEntry[i].MacAddr[2],
+                               pAd->StaCfg.DLSEntry[i].MacAddr[3], pAd->StaCfg.DLSEntry[i].MacAddr[4], pAd->StaCfg.DLSEntry[i].MacAddr[5]);
+                       printk("%-8d\n", pAd->StaCfg.DLSEntry[i].TimeOut);
+
+                       printk("\n");
+                       printk("\n%-19s%-4s%-4s%-4s%-4s%-7s%-7s%-7s","MAC", "AID", "BSS", "PSM", "WMM", "RSSI0", "RSSI1", "RSSI2");
+#ifdef DOT11_N_SUPPORT
+                       printk("%-8s%-10s%-6s%-6s%-6s%-6s", "MIMOPS", "PhMd", "BW", "MCS", "SGI", "STBC");
+#endif // DOT11_N_SUPPORT //
+                       printk("\n%02X:%02X:%02X:%02X:%02X:%02X  ",
+                               pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+                               pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]);
+                       printk("%-4d", (int)pEntry->Aid);
+                       printk("%-4d", (int)pEntry->apidx);
+                       printk("%-4d", (int)pEntry->PsMode);
+                       printk("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE));
+                       printk("%-7d", pEntry->RssiSample.AvgRssi0);
+                       printk("%-7d", pEntry->RssiSample.AvgRssi1);
+                       printk("%-7d", pEntry->RssiSample.AvgRssi2);
+#ifdef DOT11_N_SUPPORT
+                       printk("%-8d", (int)pEntry->MmpsMode);
+                       printk("%-10s", GetPhyMode(pEntry->HTPhyMode.field.MODE));
+                       printk("%-6s", GetBW(pEntry->HTPhyMode.field.BW));
+                       printk("%-6d", pEntry->HTPhyMode.field.MCS);
+                       printk("%-6d", pEntry->HTPhyMode.field.ShortGI);
+                       printk("%-6d", pEntry->HTPhyMode.field.STBC);
+#endif // DOT11_N_SUPPORT //
+                       printk("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount,
+                                               (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0);
+                       printk("\n");
+
+               }
+       }
+
+       return TRUE;
+}
+
+INT    Set_DlsAddEntry_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+    UCHAR      mac[MAC_ADDR_LEN];
+       USHORT  Timeout;
+       char *token, sepValue[] = ":", DASH = '-';
+       INT i;
+    RT_802_11_DLS      Dls;
+
+    if(strlen(arg) < 19)  //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and timeout value in decimal format.
+               return FALSE;
+
+       token = strchr(arg, DASH);
+       if ((token != NULL) && (strlen(token)>1))
+       {
+               Timeout = simple_strtol((token+1), 0, 10);
+
+               *token = '\0';
+               for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
+               {
+                       if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
+                               return FALSE;
+                       AtoH(token, (PUCHAR)(&mac[i]), 1);
+               }
+               if(i != 6)
+                       return FALSE;
+
+           printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%d", mac[0], mac[1],
+                  mac[2], mac[3], mac[4], mac[5], (int)Timeout);
+
+               NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
+               Dls.TimeOut = Timeout;
+               COPY_MAC_ADDR(Dls.MacAddr, mac);
+               Dls.Valid = 1;
+
+               MlmeEnqueue(pAd,
+                                       MLME_CNTL_STATE_MACHINE,
+                                       RT_OID_802_11_SET_DLS_PARAM,
+                                       sizeof(RT_802_11_DLS),
+                                       &Dls);
+
+               return TRUE;
+       }
+
+       return FALSE;
+
+}
+
+INT    Set_DlsTearDownEntry_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       UCHAR                   macAddr[MAC_ADDR_LEN];
+       CHAR                    *value;
+       INT                             i;
+       RT_802_11_DLS   Dls;
+
+       if(strlen(arg) != 17)  //Mac address acceptable format 01:02:03:04:05:06 length 17
+               return FALSE;
+
+       for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":"))
+       {
+               if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
+                       return FALSE;  //Invalid
+
+               AtoH(value, &macAddr[i++], 2);
+       }
+
+       printk("\n%02x:%02x:%02x:%02x:%02x:%02x", macAddr[0], macAddr[1],
+                  macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
+
+       NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
+       COPY_MAC_ADDR(Dls.MacAddr, macAddr);
+       Dls.Valid = 0;
+
+       MlmeEnqueue(pAd,
+                               MLME_CNTL_STATE_MACHINE,
+                               RT_OID_802_11_SET_DLS_PARAM,
+                               sizeof(RT_802_11_DLS),
+                               &Dls);
+
+       return TRUE;
+}
+
diff --git a/drivers/staging/rt2870/sta/rtmp_data.c b/drivers/staging/rt2870/sta/rtmp_data.c
new file mode 100644 (file)
index 0000000..9942eca
--- /dev/null
@@ -0,0 +1,2619 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       rtmp_data.c
+
+       Abstract:
+       Data path subroutines
+
+       Revision History:
+       Who             When                    What
+       --------        ----------              ----------------------------------------------
+       John                  Aug/17/04         major modification for RT2561/2661
+       Jan Lee       Mar/17/06         major modification for RT2860 New Ring Design
+*/
+#include "../rt_config.h"
+
+
+VOID STARxEAPOLFrameIndicate(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MAC_TABLE_ENTRY *pEntry,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID)
+{
+       PRT28XX_RXD_STRUC       pRxD = &(pRxBlk->RxD);
+       PRXWI_STRUC             pRxWI = pRxBlk->pRxWI;
+       UCHAR                   *pTmpBuf;
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+       if (pAd->StaCfg.WpaSupplicantUP)
+       {
+               // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
+               // TBD : process fragmented EAPol frames
+               {
+                       // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
+                       if ( pAd->StaCfg.IEEE8021X == TRUE &&
+                                (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
+                       {
+                               PUCHAR  Key;
+                               UCHAR   CipherAlg;
+                               int     idx = 0;
+
+                               DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
+                               //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               STA_PORT_SECURED(pAd);
+
+                if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
+                {
+                    idx = pAd->StaCfg.DesireSharedKeyId;
+                    CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
+                                       Key = pAd->StaCfg.DesireSharedKey[idx].Key;
+
+                    if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
+                               {
+#ifdef RT2870
+                                               union
+                                               {
+                                                       char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
+                                                       NDIS_802_11_WEP keyinfo;
+                                               }  WepKey;
+                                               int len;
+
+
+                                               NdisZeroMemory(&WepKey, sizeof(WepKey));
+                                               len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
+
+                                               NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
+                                                       pAd->StaCfg.DesireSharedKey[idx].Key,
+                                                       pAd->StaCfg.DesireSharedKey[idx].KeyLen);
+
+                                               WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
+                                               WepKey.keyinfo.KeyLength = len;
+                                               pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
+
+                                               pAd->IndicateMediaState = NdisMediaStateConnected;
+                                               pAd->ExtraInfo = GENERAL_LINK_UP;
+                                               // need to enqueue cmd to thread
+                                               RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
+#endif // RT2870 //
+                                               // For Preventing ShardKey Table is cleared by remove key procedure.
+                                       pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
+                                               pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
+                                               NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
+                                                                          pAd->StaCfg.DesireSharedKey[idx].Key,
+                                                                          pAd->StaCfg.DesireSharedKey[idx].KeyLen);
+                               }
+                               }
+                       }
+
+                       Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
+                       return;
+               }
+       }
+       else
+#endif // WPA_SUPPLICANT_SUPPORT //
+       {
+               // Special DATA frame that has to pass to MLME
+               //       1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
+               //       2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
+               {
+                       pTmpBuf = pRxBlk->pData - LENGTH_802_11;
+                       NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
+                       REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
+                       DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
+               }
+       }
+
+       RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+       return;
+
+}
+
+VOID STARxDataFrameAnnounce(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MAC_TABLE_ENTRY *pEntry,
+       IN      RX_BLK                  *pRxBlk,
+       IN      UCHAR                   FromWhichBSSID)
+{
+
+       // non-EAP frame
+       if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
+       {
+               {
+                       // drop all non-EAP DATA frame before
+                       // this client's Port-Access-Control is secured
+                       if (pRxBlk->pHeader->FC.Wep)
+                       {
+                               // unsupported cipher suite
+                               if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
+                               {
+                                       // release packet
+                                       RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+                                       return;
+                               }
+                       }
+                       else
+                       {
+                               // encryption in-use but receive a non-EAPOL clear text frame, drop it
+                               if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
+                                       (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+                               {
+                                       // release packet
+                                       RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+                                       return;
+                               }
+                       }
+               }
+               RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
+               if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
+               {
+                       // Normal legacy, AMPDU or AMSDU
+                       CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
+
+               }
+               else
+               {
+                       // ARALINK
+                       CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
+               }
+#ifdef QOS_DLS_SUPPORT
+               RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS);
+#endif // QOS_DLS_SUPPORT //
+       }
+       else
+       {
+               RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
+#ifdef DOT11_N_SUPPORT
+               if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
+               {
+                       Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
+               }
+               else
+#endif // DOT11_N_SUPPORT //
+               {
+                       // Determin the destination of the EAP frame
+                       //  to WPA state machine or upper layer
+                       STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
+               }
+       }
+}
+
+
+// For TKIP frame, calculate the MIC value
+BOOLEAN STACheckTkipMICValue(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MAC_TABLE_ENTRY *pEntry,
+       IN      RX_BLK                  *pRxBlk)
+{
+       PHEADER_802_11  pHeader = pRxBlk->pHeader;
+       UCHAR                   *pData = pRxBlk->pData;
+       USHORT                  DataSize = pRxBlk->DataSize;
+       UCHAR                   UserPriority = pRxBlk->UserPriority;
+       PCIPHER_KEY             pWpaKey;
+       UCHAR                   *pDA, *pSA;
+
+       pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
+
+       pDA = pHeader->Addr1;
+       if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
+       {
+               pSA = pHeader->Addr3;
+       }
+       else
+       {
+               pSA = pHeader->Addr2;
+       }
+
+       if (RTMPTkipCompareMICValue(pAd,
+                                                               pData,
+                                                               pDA,
+                                                               pSA,
+                                                               pWpaKey->RxMic,
+                                                               UserPriority,
+                                                               DataSize) == FALSE)
+       {
+               DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+               if (pAd->StaCfg.WpaSupplicantUP)
+               {
+                       WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
+               }
+               else
+#endif // WPA_SUPPLICANT_SUPPORT //
+               {
+                       RTMPReportMicError(pAd, pWpaKey);
+               }
+
+               // release packet
+               RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+//
+// All Rx routines use RX_BLK structure to hande rx events
+// It is very important to build pRxBlk attributes
+//  1. pHeader pointer to 802.11 Header
+//  2. pData pointer to payload including LLC (just skip Header)
+//  3. set payload size including LLC to DataSize
+//  4. set some flags with RX_BLK_SET_FLAG()
+//
+VOID STAHandleRxDataFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk)
+{
+       PRT28XX_RXD_STRUC                               pRxD = &(pRxBlk->RxD);
+       PRXWI_STRUC                                             pRxWI = pRxBlk->pRxWI;
+       PHEADER_802_11                                  pHeader = pRxBlk->pHeader;
+       PNDIS_PACKET                                    pRxPacket = pRxBlk->pRxPacket;
+       BOOLEAN                                                 bFragment = FALSE;
+       MAC_TABLE_ENTRY                         *pEntry = NULL;
+       UCHAR                                                   FromWhichBSSID = BSS0;
+       UCHAR                           UserPriority = 0;
+
+       {
+               // before LINK UP, all DATA frames are rejected
+               if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+               {
+                       // release packet
+                       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+                       return;
+               }
+
+#ifdef QOS_DLS_SUPPORT
+               //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
+               if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD))
+               {
+                       return;
+               }
+#endif // QOS_DLS_SUPPORT //
+
+               // Drop not my BSS frames
+               if (pRxD->MyBss == 0)
+               {
+                       {
+                               // release packet
+                               RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+                               return;
+                       }
+               }
+
+               pAd->RalinkCounters.RxCountSinceLastNULL++;
+               if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
+               {
+                       UCHAR *pData;
+                       DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
+
+                       // Qos bit 4
+                       pData = (PUCHAR)pHeader + LENGTH_802_11;
+                       if ((*pData >> 4) & 0x01)
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
+                               pAd->CommonCfg.bInServicePeriod = FALSE;
+
+                               // Force driver to fall into sleep mode when rcv EOSP frame
+                               if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+                               {
+                                       USHORT  TbttNumToNextWakeUp;
+                                       USHORT  NextDtim = pAd->StaCfg.DtimPeriod;
+                                       ULONG   Now;
+
+                                       NdisGetSystemUpTime(&Now);
+                                       NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
+
+                                       TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
+                                       if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
+                                               TbttNumToNextWakeUp = NextDtim;
+
+                                       MlmeSetPsmBit(pAd, PWR_SAVE);
+                                       // if WMM-APSD is failed, try to disable following line
+                                       AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
+                               }
+                       }
+
+                       if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
+                       }
+               }
+
+               // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
+               if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
+               {
+                       // release packet
+                       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+                       return;
+               }
+
+           // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
+#ifdef QOS_DLS_SUPPORT
+           if (!pAd->CommonCfg.bDLSCapable)
+           {
+#endif // QOS_DLS_SUPPORT //
+               if (INFRA_ON(pAd))
+               {
+                       // Infrastructure mode, check address 2 for BSSID
+                       if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
+                       {
+                               // Receive frame not my BSSID
+                   // release packet
+                   RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+                               return;
+                       }
+               }
+               else    // Ad-Hoc mode or Not associated
+               {
+                       // Ad-Hoc mode, check address 3 for BSSID
+                       if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
+                       {
+                               // Receive frame not my BSSID
+                   // release packet
+                   RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+                               return;
+                       }
+               }
+#ifdef QOS_DLS_SUPPORT
+           }
+#endif // QOS_DLS_SUPPORT //
+
+               //
+               // find pEntry
+               //
+               if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
+               {
+                       pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
+               }
+               else
+               {
+                       // 1. release packet if infra mode
+                       // 2. new a pEntry if ad-hoc mode
+                       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+                       return;
+               }
+
+               // infra or ad-hoc
+               if (INFRA_ON(pAd))
+               {
+                       RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
+#ifdef QOS_DLS_SUPPORT
+                       if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
+                               RX_BLK_SET_FLAG(pRxBlk, fRX_DLS);
+                       else
+#endif // QOS_DLS_SUPPORT //
+                       ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
+               }
+
+               // check Atheros Client
+               if ((pEntry->bIAmBadAtheros == FALSE) &&  (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
+               {
+                       pEntry->bIAmBadAtheros = TRUE;
+                       pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
+                       pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
+                       if (!STA_AES_ON(pAd))
+                       {
+                               AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
+                       }
+               }
+       }
+
+       pRxBlk->pData = (UCHAR *)pHeader;
+
+       //
+       // update RxBlk->pData, DataSize
+       // 802.11 Header, QOS, HTC, Hw Padding
+       //
+
+       // 1. skip 802.11 HEADER
+       {
+               pRxBlk->pData += LENGTH_802_11;
+               pRxBlk->DataSize -= LENGTH_802_11;
+       }
+
+       // 2. QOS
+       if (pHeader->FC.SubType & 0x08)
+       {
+               RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
+               UserPriority = *(pRxBlk->pData) & 0x0f;
+               // bit 7 in QoS Control field signals the HT A-MSDU format
+               if ((*pRxBlk->pData) & 0x80)
+               {
+                       RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
+               }
+
+               // skip QOS contorl field
+               pRxBlk->pData += 2;
+               pRxBlk->DataSize -=2;
+       }
+       pRxBlk->UserPriority = UserPriority;
+
+       // 3. Order bit: A-Ralink or HTC+
+       if (pHeader->FC.Order)
+       {
+#ifdef AGGREGATION_SUPPORT
+               if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
+               {
+                       RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
+               }
+               else
+#endif
+               {
+#ifdef DOT11_N_SUPPORT
+                       RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
+                       // skip HTC contorl field
+                       pRxBlk->pData += 4;
+                       pRxBlk->DataSize -= 4;
+#endif // DOT11_N_SUPPORT //
+               }
+       }
+
+       // 4. skip HW padding
+       if (pRxD->L2PAD)
+       {
+               // just move pData pointer
+               // because DataSize excluding HW padding
+               RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
+               pRxBlk->pData += 2;
+       }
+
+#ifdef DOT11_N_SUPPORT
+       if (pRxD->BA)
+       {
+               RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
+       }
+#endif // DOT11_N_SUPPORT //
+
+
+       //
+       // Case I  Process Broadcast & Multicast data frame
+       //
+       if (pRxD->Bcast || pRxD->Mcast)
+       {
+               INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
+
+               // Drop Mcast/Bcast frame with fragment bit on
+               if (pHeader->FC.MoreFrag)
+               {
+                       // release packet
+                       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+                       return;
+               }
+
+               // Filter out Bcast frame which AP relayed for us
+               if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
+               {
+                       // release packet
+                       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+                       return;
+               }
+
+               Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
+               return;
+       }
+       else if (pRxD->U2M)
+       {
+               pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
+
+
+#ifdef QOS_DLS_SUPPORT
+        if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS))
+               {
+                       MAC_TABLE_ENTRY *pDlsEntry = NULL;
+
+                       pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE);
+                                                                                                       if(pDlsEntry)
+                       Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI);
+               }
+               else
+#endif // QOS_DLS_SUPPORT //
+               if (ADHOC_ON(pAd))
+               {
+                       pEntry = MacTableLookup(pAd, pHeader->Addr2);
+                       if (pEntry)
+                               Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
+               }
+
+
+               Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
+
+               pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
+               pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
+
+               pAd->RalinkCounters.OneSecRxOkDataCnt++;
+
+
+       if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
+       {
+               // re-assemble the fragmented packets
+               // return complete frame (pRxPacket) or NULL
+               bFragment = TRUE;
+               pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
+       }
+
+       if (pRxPacket)
+       {
+                       pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
+
+               // process complete frame
+               if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
+               {
+                               // Minus MIC length
+                               pRxBlk->DataSize -= 8;
+
+                       // For TKIP frame, calculate the MIC value
+                       if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
+                       {
+                               return;
+                       }
+               }
+
+               STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
+                       return;
+       }
+       else
+       {
+               // just return
+               // because RTMPDeFragmentDataFrame() will release rx packet,
+               // if packet is fragmented
+               return;
+       }
+       }
+
+       ASSERT(0);
+       // release packet
+       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+}
+
+VOID STAHandleRxMgmtFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk)
+{
+       PRT28XX_RXD_STRUC       pRxD = &(pRxBlk->RxD);
+       PRXWI_STRUC             pRxWI = pRxBlk->pRxWI;
+       PHEADER_802_11  pHeader = pRxBlk->pHeader;
+       PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
+
+       do
+       {
+
+               // We should collect RSSI not only U2M data but also my beacon
+               if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
+               {
+                       Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
+
+                       pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
+                       pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
+               }
+
+               // First check the size, it MUST not exceed the mlme queue size
+               if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
+               {
+                       DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
+                       break;
+               }
+
+               REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
+                                                                       pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
+       } while (FALSE);
+
+       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
+}
+
+VOID STAHandleRxControlFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      RX_BLK                  *pRxBlk)
+{
+#ifdef DOT11_N_SUPPORT
+       PRXWI_STRUC             pRxWI = pRxBlk->pRxWI;
+#endif // DOT11_N_SUPPORT //
+       PHEADER_802_11  pHeader = pRxBlk->pHeader;
+       PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
+
+       switch (pHeader->FC.SubType)
+       {
+               case SUBTYPE_BLOCK_ACK_REQ:
+#ifdef DOT11_N_SUPPORT
+                       {
+                               CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
+                       }
+                       break;
+#endif // DOT11_N_SUPPORT //
+               case SUBTYPE_BLOCK_ACK:
+               case SUBTYPE_ACK:
+               default:
+                       break;
+       }
+
+       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Process RxDone interrupt, running in DPC level
+
+       Arguments:
+               pAd Pointer to our adapter
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+               This routine has to maintain Rx ring read pointer.
+               Need to consider QOS DATA format when converting to 802.3
+       ========================================================================
+*/
+BOOLEAN STARxDoneInterruptHandle(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      BOOLEAN                 argc)
+{
+       NDIS_STATUS                     Status;
+       UINT32                  RxProcessed, RxPending;
+       BOOLEAN                 bReschedule = FALSE;
+       RT28XX_RXD_STRUC        *pRxD;
+       UCHAR                   *pData;
+       PRXWI_STRUC             pRxWI;
+       PNDIS_PACKET    pRxPacket;
+       PHEADER_802_11  pHeader;
+       RX_BLK                  RxCell;
+
+       RxProcessed = RxPending = 0;
+
+       // process whole rx ring
+       while (1)
+       {
+
+               if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
+                                                               fRTMP_ADAPTER_RESET_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_HALT_IN_PROGRESS |
+                                                               fRTMP_ADAPTER_NIC_NOT_EXIST) ||
+                       !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
+               {
+                       break;
+               }
+
+
+               RxProcessed ++; // test
+
+               // 1. allocate a new data packet into rx ring to replace received packet
+               //    then processing the received packet
+               // 2. the callee must take charge of release of packet
+               // 3. As far as driver is concerned ,
+               //    the rx packet must
+               //      a. be indicated to upper layer or
+               //      b. be released if it is discarded
+               pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
+               if (pRxPacket == NULL)
+               {
+                       // no more packet to process
+                       break;
+               }
+
+               // get rx ring descriptor
+               pRxD = &(RxCell.RxD);
+               // get rx data buffer
+               pData   = GET_OS_PKT_DATAPTR(pRxPacket);
+               pRxWI   = (PRXWI_STRUC) pData;
+               pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
+
+#ifdef RT_BIG_ENDIAN
+           RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE);
+               RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI);
+#endif
+
+               // build RxCell
+               RxCell.pRxWI = pRxWI;
+               RxCell.pHeader = pHeader;
+               RxCell.pRxPacket = pRxPacket;
+               RxCell.pData = (UCHAR *) pHeader;
+               RxCell.DataSize = pRxWI->MPDUtotalByteCount;
+               RxCell.Flags = 0;
+
+               // Increase Total receive byte counter after real data received no mater any error or not
+               pAd->RalinkCounters.ReceivedByteCount +=  pRxWI->MPDUtotalByteCount;
+               pAd->RalinkCounters.RxCount ++;
+
+               INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
+
+               if (pRxWI->MPDUtotalByteCount < 14)
+                       Status = NDIS_STATUS_FAILURE;
+
+        if (MONITOR_ON(pAd))
+               {
+            send_monitor_packets(pAd, &RxCell);
+                       break;
+               }
+               /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
+#ifdef RALINK_ATE
+               if (ATE_ON(pAd))
+               {
+                       pAd->ate.RxCntPerSec++;
+                       ATESampleRssi(pAd, pRxWI);
+#ifdef RALINK_28xx_QA
+                       if (pAd->ate.bQARxStart == TRUE)
+                       {
+                               /* (*pRxD) has been swapped in GetPacketFromRxRing() */
+                               ATE_QA_Statistics(pAd, pRxWI, pRxD,     pHeader);
+                       }
+#endif // RALINK_28xx_QA //
+                       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
+                       continue;
+               }
+#endif // RALINK_ATE //
+
+               // Check for all RxD errors
+               Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
+
+               // Handle the received frame
+               if (Status == NDIS_STATUS_SUCCESS)
+               {
+                       switch (pHeader->FC.Type)
+                       {
+                               // CASE I, receive a DATA frame
+                               case BTYPE_DATA:
+                               {
+                                       // process DATA frame
+                                       STAHandleRxDataFrame(pAd, &RxCell);
+                               }
+                               break;
+                               // CASE II, receive a MGMT frame
+                               case BTYPE_MGMT:
+                               {
+                                       STAHandleRxMgmtFrame(pAd, &RxCell);
+                               }
+                               break;
+                               // CASE III. receive a CNTL frame
+                               case BTYPE_CNTL:
+                               {
+                                       STAHandleRxControlFrame(pAd, &RxCell);
+                               }
+                               break;
+                               // discard other type
+                               default:
+                                       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+                                       break;
+                       }
+               }
+               else
+               {
+                       pAd->Counters8023.RxErrors++;
+                       // discard this frame
+                       RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+               }
+       }
+
+       return bReschedule;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+       Arguments:
+               pAd     Pointer to our adapter
+
+       IRQL = DISPATCH_LEVEL
+
+       ========================================================================
+*/
+VOID   RTMPHandleTwakeupInterrupt(
+       IN PRTMP_ADAPTER pAd)
+{
+       AsicForceWakeup(pAd, FALSE);
+}
+
+/*
+========================================================================
+Routine Description:
+    Early checking and OS-depened parsing for Tx packet send to our STA driver.
+
+Arguments:
+    NDIS_HANDLE        MiniportAdapterContext  Pointer refer to the device handle, i.e., the pAd.
+       PPNDIS_PACKET   ppPacketArray                   The packet array need to do transmission.
+       UINT                    NumberOfPackets                 Number of packet in packet array.
+
+Return Value:
+       NONE
+
+Note:
+       This function do early checking and classification for send-out packet.
+       You only can put OS-depened & STA related code in here.
+========================================================================
+*/
+VOID STASendPackets(
+       IN      NDIS_HANDLE             MiniportAdapterContext,
+       IN      PPNDIS_PACKET   ppPacketArray,
+       IN      UINT                    NumberOfPackets)
+{
+       UINT                    Index;
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
+       PNDIS_PACKET    pPacket;
+       BOOLEAN                 allowToSend = FALSE;
+
+
+       for (Index = 0; Index < NumberOfPackets; Index++)
+       {
+               pPacket = ppPacketArray[Index];
+
+               do
+               {
+                       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
+                               RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
+                               RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
+                       {
+                               // Drop send request since hardware is in reset state
+                                       break;
+                       }
+                       else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
+                       {
+                               // Drop send request since there are no physical connection yet
+                                       break;
+                       }
+                       else
+                       {
+                               // Record that orignal packet source is from NDIS layer,so that
+                               // later on driver knows how to release this NDIS PACKET
+#ifdef QOS_DLS_SUPPORT
+                               MAC_TABLE_ENTRY *pEntry;
+                               PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
+
+                               pEntry = MacTableLookup(pAd, pSrcBufVA);
+                               if (pEntry && (pEntry->ValidAsDls == TRUE))
+                               {
+                                       RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
+                               }
+                               else
+#endif // QOS_DLS_SUPPORT //
+                               RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
+                               RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
+                               NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
+                               pAd->RalinkCounters.PendingNdisPacketCount++;
+
+                               allowToSend = TRUE;
+                       }
+               } while(FALSE);
+
+               if (allowToSend == TRUE)
+                       STASendPacket(pAd, pPacket);
+               else
+                       RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+       }
+
+       // Dequeue outgoing frames from TxSwQueue[] and process it
+       RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+
+}
+
+
+/*
+========================================================================
+Routine Description:
+       This routine is used to do packet parsing and classification for Tx packet
+       to STA device, and it will en-queue packets to our TxSwQueue depends on AC
+       class.
+
+Arguments:
+       pAd             Pointer to our adapter
+       pPacket         Pointer to send packet
+
+Return Value:
+       NDIS_STATUS_SUCCESS                     If succes to queue the packet into TxSwQueue.
+       NDIS_STATUS_FAILURE                     If failed to do en-queue.
+
+Note:
+       You only can put OS-indepened & STA related code in here.
+========================================================================
+*/
+NDIS_STATUS STASendPacket(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket)
+{
+       PACKET_INFO     PacketInfo;
+       PUCHAR                  pSrcBufVA;
+       UINT                    SrcBufLen;
+       UINT                    AllowFragSize;
+       UCHAR                   NumberOfFrag;
+//     UCHAR                   RTSRequired;
+       UCHAR                   QueIdx, UserPriority;
+       MAC_TABLE_ENTRY *pEntry = NULL;
+       unsigned int    IrqFlags;
+       UCHAR                   FlgIsIP = 0;
+       UCHAR                   Rate;
+
+       // Prepare packet information structure for buffer descriptor
+       // chained within a single NDIS packet.
+       RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+
+       if (pSrcBufVA == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
+               // Resourece is low, system did not allocate virtual address
+               // return NDIS_STATUS_FAILURE directly to upper layer
+               RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+               return NDIS_STATUS_FAILURE;
+       }
+
+
+       if (SrcBufLen < 14)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
+               RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+               return (NDIS_STATUS_FAILURE);
+       }
+
+       // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
+       // Note multicast packets in adhoc also use BSSID_WCID index.
+       {
+               if(INFRA_ON(pAd))
+               {
+#ifdef QOS_DLS_SUPPORT
+                       USHORT  tmpWcid;
+
+                       tmpWcid = RTMP_GET_PACKET_WCID(pPacket);
+                       if (VALID_WCID(tmpWcid) &&
+                               (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE))
+                       {
+                               pEntry = &pAd->MacTab.Content[tmpWcid];
+                               Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate;
+                       }
+                       else
+#endif // QOS_DLS_SUPPORT //
+                       {
+                       pEntry = &pAd->MacTab.Content[BSSID_WCID];
+                       RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
+                       Rate = pAd->CommonCfg.TxRate;
+               }
+               }
+               else if (ADHOC_ON(pAd))
+               {
+                       if (*pSrcBufVA & 0x01)
+                       {
+                               RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
+                               pEntry = &pAd->MacTab.Content[MCAST_WCID];
+                       }
+                       else
+                       {
+                               pEntry = MacTableLookup(pAd, pSrcBufVA);
+                       }
+                       Rate = pAd->CommonCfg.TxRate;
+               }
+       }
+
+       if (!pEntry)
+       {
+               DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
+               // Resourece is low, system did not allocate virtual address
+               // return NDIS_STATUS_FAILURE directly to upper layer
+               RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+               return NDIS_STATUS_FAILURE;
+       }
+
+       if (ADHOC_ON(pAd)
+               )
+       {
+               RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
+       }
+
+       //
+       // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
+       //              Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
+       RTMPCheckEtherType(pAd, pPacket);
+
+
+
+       //
+       // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
+       //
+       if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+                (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+                (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
+                (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+#ifdef WPA_SUPPLICANT_SUPPORT
+                 || (pAd->StaCfg.IEEE8021X == TRUE)
+#endif // WPA_SUPPLICANT_SUPPORT //
+#ifdef LEAP_SUPPORT
+                 || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+#endif // LEAP_SUPPORT //
+                 )
+                 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
+                 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
+                 )
+       {
+               DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
+               RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+
+               return (NDIS_STATUS_FAILURE);
+       }
+
+
+       // STEP 1. Decide number of fragments required to deliver this MSDU.
+       //         The estimation here is not very accurate because difficult to
+       //         take encryption overhead into consideration here. The result
+       //         "NumberOfFrag" is then just used to pre-check if enough free
+       //         TXD are available to hold this MSDU.
+
+
+       if (*pSrcBufVA & 0x01)  // fragmentation not allowed on multicast & broadcast
+               NumberOfFrag = 1;
+       else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
+               NumberOfFrag = 1;       // Aggregation overwhelms fragmentation
+       else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
+               NumberOfFrag = 1;       // Aggregation overwhelms fragmentation
+#ifdef DOT11_N_SUPPORT
+       else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
+               NumberOfFrag = 1;       // MIMO RATE overwhelms fragmentation
+#endif // DOT11_N_SUPPORT //
+       else
+       {
+               // The calculated "NumberOfFrag" is a rough estimation because of various
+               // encryption/encapsulation overhead not taken into consideration. This number is just
+               // used to make sure enough free TXD are available before fragmentation takes place.
+               // In case the actual required number of fragments of an NDIS packet
+               // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
+               // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
+               // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
+               // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
+
+               AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
+               NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
+               // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
+               if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
+               {
+                       NumberOfFrag--;
+               }
+       }
+
+       // Save fragment number to Ndis packet reserved field
+       RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
+
+
+       // STEP 2. Check the requirement of RTS:
+       //         If multiple fragment required, RTS is required only for the first fragment
+       //         if the fragment size large than RTS threshold
+       //     For RT28xx, Let ASIC send RTS/CTS
+       RTMP_SET_PACKET_RTS(pPacket, 0);
+       RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
+
+       //
+       // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
+       //
+       UserPriority = 0;
+       QueIdx           = QID_AC_BE;
+       if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
+               CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
+       {
+               USHORT Protocol;
+               UCHAR  LlcSnapLen = 0, Byte0, Byte1;
+               do
+               {
+                       // get Ethernet protocol field
+                       Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
+                       if (Protocol <= 1500)
+                       {
+                               // get Ethernet protocol field from LLC/SNAP
+                               if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
+                                       break;
+
+                               Protocol = (USHORT)((Byte0 << 8) + Byte1);
+                               LlcSnapLen = 8;
+                       }
+
+                       // always AC_BE for non-IP packet
+                       if (Protocol != 0x0800)
+                               break;
+
+                       // get IP header
+                       if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
+                               break;
+
+                       // return AC_BE if packet is not IPv4
+                       if ((Byte0 & 0xf0) != 0x40)
+                               break;
+
+                       FlgIsIP = 1;
+                       UserPriority = (Byte1 & 0xe0) >> 5;
+                       QueIdx = MapUserPriorityToAccessCategory[UserPriority];
+
+                       // TODO: have to check ACM bit. apply TSPEC if ACM is ON
+                       // TODO: downgrade UP & QueIdx before passing ACM
+                       if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
+                       {
+                               UserPriority = 0;
+                               QueIdx           = QID_AC_BE;
+                       }
+               } while (FALSE);
+       }
+
+       RTMP_SET_PACKET_UP(pPacket, UserPriority);
+
+
+
+       // Make sure SendTxWait queue resource won't be used by other threads
+       RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+       if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
+       {
+               RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+#ifdef BLOCK_NET_IF
+               StopNetIfQueue(pAd, QueIdx, pPacket);
+#endif // BLOCK_NET_IF //
+               RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+
+               return NDIS_STATUS_FAILURE;
+       }
+       else
+       {
+               InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
+       }
+       RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+
+#ifdef DOT11_N_SUPPORT
+    if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
+        IS_HT_STA(pEntry))
+       {
+           //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID];
+               if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
+            ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
+            (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
+                        // For IOT compatibility, if
+                        // 1. It is Ralink chip or
+                        // 2. It is OPEN or AES mode,
+                        // then BA session can be bulit.
+                        && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
+                                (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
+                       )
+               {
+                       BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
+               }
+       }
+#endif // DOT11_N_SUPPORT //
+
+       pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
+       return NDIS_STATUS_SUCCESS;
+}
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               This subroutine will scan through releative ring descriptor to find
+               out avaliable free ring descriptor and compare with request size.
+
+       Arguments:
+               pAd Pointer to our adapter
+               QueIdx          Selected TX Ring
+
+       Return Value:
+               NDIS_STATUS_FAILURE     Not enough free descriptor
+               NDIS_STATUS_SUCCESS     Enough free descriptor
+
+       IRQL = PASSIVE_LEVEL
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+
+#ifdef RT2870
+/*
+       Actually, this function used to check if the TxHardware Queue still has frame need to send.
+       If no frame need to send, go to sleep, else, still wake up.
+*/
+NDIS_STATUS RTMPFreeTXDRequest(
+       IN              PRTMP_ADAPTER   pAd,
+       IN              UCHAR                   QueIdx,
+       IN              UCHAR                   NumberRequired,
+       IN              PUCHAR                  FreeNumberIs)
+{
+       //ULONG         FreeNumber = 0;
+       NDIS_STATUS     Status = NDIS_STATUS_FAILURE;
+       unsigned long   IrqFlags;
+       HT_TX_CONTEXT   *pHTTXContext;
+
+       switch (QueIdx)
+       {
+               case QID_AC_BK:
+               case QID_AC_BE:
+               case QID_AC_VI:
+               case QID_AC_VO:
+               case QID_HCCA:
+                       {
+                               pHTTXContext = &pAd->TxContext[QueIdx];
+                               RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+                               if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
+                                       (pHTTXContext->IRPPending == TRUE))
+                               {
+                                       Status = NDIS_STATUS_FAILURE;
+                               }
+                               else
+                               {
+                                       Status = NDIS_STATUS_SUCCESS;
+                               }
+                               RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+                       }
+                       break;
+
+               case QID_MGMT:
+                       if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
+                               Status = NDIS_STATUS_FAILURE;
+                       else
+                               Status = NDIS_STATUS_SUCCESS;
+                       break;
+
+               default:
+                       DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
+                       break;
+       }
+
+       return (Status);
+
+}
+#endif // RT2870 //
+
+
+VOID RTMPSendDisassociationFrame(
+       IN      PRTMP_ADAPTER   pAd)
+{
+}
+
+VOID   RTMPSendNullFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      UCHAR                   TxRate,
+       IN      BOOLEAN                 bQosNull)
+{
+       UCHAR   NullFrame[48];
+       ULONG   Length;
+       PHEADER_802_11  pHeader_802_11;
+
+
+#ifdef RALINK_ATE
+       if(ATE_ON(pAd))
+       {
+               return;
+       }
+#endif // RALINK_ATE //
+
+    // WPA 802.1x secured port control
+    if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+         (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+         (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
+         (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+#ifdef WPA_SUPPLICANT_SUPPORT
+                         || (pAd->StaCfg.IEEE8021X == TRUE)
+#endif
+        ) &&
+       (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+       {
+               return;
+       }
+
+       NdisZeroMemory(NullFrame, 48);
+       Length = sizeof(HEADER_802_11);
+
+       pHeader_802_11 = (PHEADER_802_11) NullFrame;
+
+       pHeader_802_11->FC.Type = BTYPE_DATA;
+       pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
+       pHeader_802_11->FC.ToDs = 1;
+       COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
+       COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
+       COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
+
+       if (pAd->CommonCfg.bAPSDForcePowerSave)
+       {
+               pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
+       }
+       else
+       {
+               pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
+       }
+       pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
+
+       pAd->Sequence++;
+       pHeader_802_11->Sequence = pAd->Sequence;
+
+       // Prepare QosNull function frame
+       if (bQosNull)
+       {
+               pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
+
+               // copy QOS control bytes
+               NullFrame[Length]       =  0;
+               NullFrame[Length+1] =  0;
+               Length += 2;// if pad with 2 bytes for alignment, APSD will fail
+       }
+
+       HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
+
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID   RTMPSendRTSFrame(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pDA,
+       IN      unsigned int    NextMpduSize,
+       IN      UCHAR                   TxRate,
+       IN      UCHAR                   RTSRate,
+       IN      USHORT                  AckDuration,
+       IN      UCHAR                   QueIdx,
+       IN      UCHAR                   FrameGap)
+{
+}
+
+
+
+// --------------------------------------------------------
+//  FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
+//             Find the WPA key, either Group or Pairwise Key
+//             LEAP + TKIP also use WPA key.
+// --------------------------------------------------------
+// Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
+// In Cisco CCX 2.0 Leap Authentication
+//                WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
+//                Instead of the SharedKey, SharedKey Length may be Zero.
+VOID STAFindCipherAlgorithm(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk)
+{
+       NDIS_802_11_ENCRYPTION_STATUS   Cipher;                         // To indicate cipher used for this packet
+       UCHAR                                                   CipherAlg = CIPHER_NONE;                // cipher alogrithm
+       UCHAR                                                   KeyIdx = 0xff;
+       PUCHAR                                                  pSrcBufVA;
+       PCIPHER_KEY                                             pKey = NULL;
+
+       pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
+
+       {
+           // Select Cipher
+           if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
+               Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
+           else
+               Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
+
+               if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
+               {
+                       ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
+
+                       // 4-way handshaking frame must be clear
+                       if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
+                               (pAd->SharedKey[BSS0][0].KeyLen))
+                       {
+                               CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
+                               KeyIdx = 0;
+                       }
+               }
+               else if (Cipher == Ndis802_11Encryption1Enabled)
+               {
+#ifdef LEAP_SUPPORT
+                       if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
+                       {
+                               if (LEAP_CCKM_ON(pAd))
+                               {
+                                       if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
+                                               KeyIdx = 1;
+                                       else
+                                               KeyIdx = 0;
+                               }
+                               else
+                                       KeyIdx = pAd->StaCfg.DefaultKeyId;
+                       }
+                       else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
+                               KeyIdx = pAd->StaCfg.DefaultKeyId;
+                       else if (LEAP_CCKM_ON(pAd))
+                       {
+                               if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
+                                       KeyIdx = 1;
+                               else
+                                       KeyIdx = 0;
+                       }
+                       else    // standard WEP64 or WEP128
+#endif // LEAP_SUPPORT //
+                               KeyIdx = pAd->StaCfg.DefaultKeyId;
+               }
+               else if ((Cipher == Ndis802_11Encryption2Enabled) ||
+                                (Cipher == Ndis802_11Encryption3Enabled))
+               {
+                       if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
+                               KeyIdx = pAd->StaCfg.DefaultKeyId;
+                       else if (pAd->SharedKey[BSS0][0].KeyLen)
+                               KeyIdx = 0;
+                       else
+                               KeyIdx = pAd->StaCfg.DefaultKeyId;
+               }
+
+               if (KeyIdx == 0xff)
+                       CipherAlg = CIPHER_NONE;
+               else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
+                       CipherAlg = CIPHER_NONE;
+#ifdef WPA_SUPPLICANT_SUPPORT
+           else if ( pAd->StaCfg.WpaSupplicantUP &&
+                    (Cipher == Ndis802_11Encryption1Enabled) &&
+                    (pAd->StaCfg.IEEE8021X == TRUE) &&
+                    (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+               CipherAlg = CIPHER_NONE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+               else
+               {
+                       //Header_802_11.FC.Wep = 1;
+                       CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
+                       pKey = &pAd->SharedKey[BSS0][KeyIdx];
+               }
+       }
+
+       pTxBlk->CipherAlg = CipherAlg;
+       pTxBlk->pKey = pKey;
+}
+
+
+VOID STABuildCommon802_11Header(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  TX_BLK          *pTxBlk)
+{
+
+       HEADER_802_11   *pHeader_802_11;
+#ifdef QOS_DLS_SUPPORT
+       BOOLEAN bDLSFrame = FALSE;
+       INT     DlsEntryIndex = 0;
+#endif // QOS_DLS_SUPPORT //
+
+       //
+       // MAKE A COMMON 802.11 HEADER
+       //
+
+       // normal wlan header size : 24 octets
+       pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
+
+       pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
+
+       NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
+
+       pHeader_802_11->FC.FrDs = 0;
+       pHeader_802_11->FC.Type = BTYPE_DATA;
+       pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
+
+#ifdef QOS_DLS_SUPPORT
+       if (INFRA_ON(pAd))
+       {
+               // Check if the frame can be sent through DLS direct link interface
+               // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
+               DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
+               if (DlsEntryIndex >= 0)
+                       bDLSFrame = TRUE;
+               else
+                       bDLSFrame = FALSE;
+       }
+#endif // QOS_DLS_SUPPORT //
+
+    if (pTxBlk->pMacEntry)
+       {
+               if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
+               {
+                       pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
+                       pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
+               }
+               else
+               {
+           pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
+           pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
+       }
+       }
+       else
+       {
+               pHeader_802_11->Sequence = pAd->Sequence;
+               pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
+       }
+
+       pHeader_802_11->Frag = 0;
+
+       pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
+
+       {
+               if (INFRA_ON(pAd))
+               {
+#ifdef QOS_DLS_SUPPORT
+                       if (bDLSFrame)
+                       {
+                               COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
+                               COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
+                               COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
+                               pHeader_802_11->FC.ToDs = 0;
+                       }
+                       else
+#endif // QOS_DLS_SUPPORT //
+                       {
+                       COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
+                       COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
+                       COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
+                       pHeader_802_11->FC.ToDs = 1;
+               }
+               }
+               else if (ADHOC_ON(pAd))
+               {
+                       COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
+                       COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
+                       COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
+                       pHeader_802_11->FC.ToDs = 0;
+               }
+       }
+
+       if (pTxBlk->CipherAlg != CIPHER_NONE)
+               pHeader_802_11->FC.Wep = 1;
+
+       // -----------------------------------------------------------------
+       // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
+       // -----------------------------------------------------------------
+       if (pAd->CommonCfg.bAPSDForcePowerSave)
+       pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
+       else
+       pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
+}
+
+#ifdef DOT11_N_SUPPORT
+VOID STABuildCache802_11Header(
+       IN RTMP_ADAPTER         *pAd,
+       IN TX_BLK                       *pTxBlk,
+       IN UCHAR                        *pHeader)
+{
+       MAC_TABLE_ENTRY *pMacEntry;
+       PHEADER_802_11  pHeader80211;
+
+       pHeader80211 = (PHEADER_802_11)pHeader;
+       pMacEntry = pTxBlk->pMacEntry;
+
+       //
+       // Update the cached 802.11 HEADER
+       //
+
+       // normal wlan header size : 24 octets
+       pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
+
+       // More Bit
+       pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
+
+       // Sequence
+       pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
+    pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
+
+       {
+               // Check if the frame can be sent through DLS direct link interface
+               // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
+#ifdef QOS_DLS_SUPPORT
+               BOOLEAN bDLSFrame = FALSE;
+               INT     DlsEntryIndex = 0;
+
+               DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
+               if (DlsEntryIndex >= 0)
+                       bDLSFrame = TRUE;
+               else
+                       bDLSFrame = FALSE;
+#endif // QOS_DLS_SUPPORT //
+
+               // The addr3 of normal packet send from DS is Dest Mac address.
+#ifdef QOS_DLS_SUPPORT
+               if (bDLSFrame)
+               {
+                       COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
+                       COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
+                       pHeader80211->FC.ToDs = 0;
+               }
+               else
+#endif // QOS_DLS_SUPPORT //
+               if (ADHOC_ON(pAd))
+                       COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
+               else
+                       COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
+       }
+
+       // -----------------------------------------------------------------
+       // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
+       // -----------------------------------------------------------------
+       if (pAd->CommonCfg.bAPSDForcePowerSave)
+       pHeader80211->FC.PwrMgmt = PWR_SAVE;
+       else
+       pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
+}
+#endif // DOT11_N_SUPPORT //
+
+static inline PUCHAR STA_Build_ARalink_Frame_Header(
+       IN RTMP_ADAPTER *pAd,
+       IN TX_BLK               *pTxBlk)
+{
+       PUCHAR                  pHeaderBufPtr;
+       HEADER_802_11   *pHeader_802_11;
+       PNDIS_PACKET    pNextPacket;
+       UINT32                  nextBufLen;
+       PQUEUE_ENTRY    pQEntry;
+
+       STAFindCipherAlgorithm(pAd, pTxBlk);
+       STABuildCommon802_11Header(pAd, pTxBlk);
+
+
+       pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
+       pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
+
+       // steal "order" bit to mark "aggregation"
+       pHeader_802_11->FC.Order = 1;
+
+       // skip common header
+       pHeaderBufPtr += pTxBlk->MpduHeaderLen;
+
+       if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
+       {
+               //
+               // build QOS Control bytes
+               //
+               *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
+
+               *(pHeaderBufPtr+1) = 0;
+               pHeaderBufPtr +=2;
+               pTxBlk->MpduHeaderLen += 2;
+       }
+
+       // padding at front of LLC header. LLC header should at 4-bytes aligment.
+       pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
+       pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
+       pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
+
+       // For RA Aggregation,
+       // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
+       pQEntry = pTxBlk->TxPacketList.Head;
+       pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
+       nextBufLen = GET_OS_PKT_LEN(pNextPacket);
+       if (RTMP_GET_PACKET_VLAN(pNextPacket))
+               nextBufLen -= LENGTH_802_1Q;
+
+       *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
+       *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
+
+       pHeaderBufPtr += 2;
+       pTxBlk->MpduHeaderLen += 2;
+
+       return pHeaderBufPtr;
+
+}
+
+#ifdef DOT11_N_SUPPORT
+static inline PUCHAR STA_Build_AMSDU_Frame_Header(
+       IN RTMP_ADAPTER *pAd,
+       IN TX_BLK               *pTxBlk)
+{
+       PUCHAR                  pHeaderBufPtr;//, pSaveBufPtr;
+       HEADER_802_11   *pHeader_802_11;
+
+
+       STAFindCipherAlgorithm(pAd, pTxBlk);
+       STABuildCommon802_11Header(pAd, pTxBlk);
+
+       pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
+       pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
+
+       // skip common header
+       pHeaderBufPtr += pTxBlk->MpduHeaderLen;
+
+       //
+       // build QOS Control bytes
+       //
+       *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
+
+       //
+       // A-MSDU packet
+       //
+       *pHeaderBufPtr |= 0x80;
+
+       *(pHeaderBufPtr+1) = 0;
+       pHeaderBufPtr +=2;
+       pTxBlk->MpduHeaderLen += 2;
+
+       //pSaveBufPtr = pHeaderBufPtr;
+
+       //
+       // padding at front of LLC header
+       // LLC header should locate at 4-octets aligment
+       //
+       // @@@ MpduHeaderLen excluding padding @@@
+       //
+       pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
+       pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
+       pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
+
+       return pHeaderBufPtr;
+
+}
+
+
+VOID STA_AMPDU_Frame_Tx(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk)
+{
+       HEADER_802_11   *pHeader_802_11;
+       PUCHAR                  pHeaderBufPtr;
+       USHORT                  FreeNumber;
+       MAC_TABLE_ENTRY *pMacEntry;
+       BOOLEAN                 bVLANPkt;
+       PQUEUE_ENTRY    pQEntry;
+
+       ASSERT(pTxBlk);
+
+       while(pTxBlk->TxPacketList.Head)
+       {
+               pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+               pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+               if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
+               {
+                       RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+                       continue;
+               }
+
+               bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
+
+               pMacEntry = pTxBlk->pMacEntry;
+               if (pMacEntry->isCached)
+               {
+                       // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
+                       NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
+                       pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
+                       STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
+               }
+               else
+               {
+                       STAFindCipherAlgorithm(pAd, pTxBlk);
+                       STABuildCommon802_11Header(pAd, pTxBlk);
+
+                       pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
+               }
+
+
+               pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
+
+               // skip common header
+               pHeaderBufPtr += pTxBlk->MpduHeaderLen;
+
+               //
+               // build QOS Control bytes
+               //
+               *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
+               *(pHeaderBufPtr+1) = 0;
+               pHeaderBufPtr +=2;
+               pTxBlk->MpduHeaderLen += 2;
+
+               //
+               // build HTC+
+               // HTC control filed following QoS field
+               //
+               if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
+               {
+                       if (pMacEntry->isCached == FALSE)
+                       {
+                               // mark HTC bit
+                               pHeader_802_11->FC.Order = 1;
+
+                               NdisZeroMemory(pHeaderBufPtr, 4);
+                               *(pHeaderBufPtr+3) |= 0x80;
+                       }
+                       pHeaderBufPtr += 4;
+                       pTxBlk->MpduHeaderLen += 4;
+               }
+
+               //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
+               ASSERT(pTxBlk->MpduHeaderLen >= 24);
+
+               // skip 802.3 header
+               pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
+               pTxBlk->SrcBufLen  -= LENGTH_802_3;
+
+               // skip vlan tag
+               if (bVLANPkt)
+               {
+                       pTxBlk->pSrcBufData     += LENGTH_802_1Q;
+                       pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
+               }
+
+               //
+               // padding at front of LLC header
+               // LLC header should locate at 4-octets aligment
+               //
+               // @@@ MpduHeaderLen excluding padding @@@
+               //
+               pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
+               pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
+               pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
+
+               {
+
+                       //
+                       // Insert LLC-SNAP encapsulation - 8 octets
+                       //
+                       EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
+                       if (pTxBlk->pExtraLlcSnapEncap)
+                       {
+                               NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
+                               pHeaderBufPtr += 6;
+                               // get 2 octets (TypeofLen)
+                               NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
+                               pHeaderBufPtr += 2;
+                               pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
+                       }
+
+               }
+
+               if (pMacEntry->isCached)
+               {
+            RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
+               }
+               else
+               {
+                       RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
+
+                       NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
+                       NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
+                       pMacEntry->isCached = TRUE;
+               }
+
+               // calculate Transmitted AMPDU count and ByteCount
+               {
+                       pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
+                       pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
+               }
+
+               //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
+
+               HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
+
+               //
+               // Kick out Tx
+               //
+               HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
+
+               pAd->RalinkCounters.KickTxCount++;
+               pAd->RalinkCounters.OneSecTxDoneCount++;
+       }
+
+}
+
+
+VOID STA_AMSDU_Frame_Tx(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk)
+{
+       PUCHAR                  pHeaderBufPtr;
+       USHORT                  FreeNumber;
+       USHORT                  subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
+       USHORT                  totalMPDUSize=0;
+       UCHAR                   *subFrameHeader;
+       UCHAR                   padding = 0;
+       USHORT                  FirstTx = 0, LastTxIdx = 0;
+       BOOLEAN                 bVLANPkt;
+       int                     frameNum = 0;
+       PQUEUE_ENTRY    pQEntry;
+
+
+       ASSERT(pTxBlk);
+
+       ASSERT((pTxBlk->TxPacketList.Number > 1));
+
+       while(pTxBlk->TxPacketList.Head)
+       {
+               pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+               pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+               if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
+               {
+                       RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+                       continue;
+               }
+
+               bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
+
+               // skip 802.3 header
+               pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
+               pTxBlk->SrcBufLen  -= LENGTH_802_3;
+
+               // skip vlan tag
+               if (bVLANPkt)
+               {
+                       pTxBlk->pSrcBufData     += LENGTH_802_1Q;
+                       pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
+               }
+
+               if (frameNum == 0)
+               {
+                       pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
+
+                       // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
+                       RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
+               }
+               else
+               {
+                       pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
+                       padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
+                       NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
+                       pHeaderBufPtr += padding;
+                       pTxBlk->MpduHeaderLen = padding;
+               }
+
+               //
+               // A-MSDU subframe
+               //   DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
+               //
+               subFrameHeader = pHeaderBufPtr;
+               subFramePayloadLen = pTxBlk->SrcBufLen;
+
+               NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
+
+
+               pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
+               pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
+
+
+               //
+               // Insert LLC-SNAP encapsulation - 8 octets
+               //
+               EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
+
+               subFramePayloadLen = pTxBlk->SrcBufLen;
+
+               if (pTxBlk->pExtraLlcSnapEncap)
+               {
+                       NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
+                       pHeaderBufPtr += 6;
+                       // get 2 octets (TypeofLen)
+                       NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
+                       pHeaderBufPtr += 2;
+                       pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
+                       subFramePayloadLen += LENGTH_802_1_H;
+               }
+
+               // update subFrame Length field
+               subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
+               subFrameHeader[13] = subFramePayloadLen & 0xFF;
+
+               totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
+
+               if (frameNum ==0)
+                       FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
+               else
+                       LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
+
+               frameNum++;
+
+               pAd->RalinkCounters.KickTxCount++;
+               pAd->RalinkCounters.OneSecTxDoneCount++;
+
+               // calculate Transmitted AMSDU Count and ByteCount
+               {
+                       pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
+                       pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
+               }
+
+       }
+
+       HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
+       HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
+
+       //
+       // Kick out Tx
+       //
+       HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
+}
+#endif // DOT11_N_SUPPORT //
+
+VOID STA_Legacy_Frame_Tx(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk)
+{
+       HEADER_802_11   *pHeader_802_11;
+       PUCHAR                  pHeaderBufPtr;
+       USHORT                  FreeNumber;
+       BOOLEAN                 bVLANPkt;
+       PQUEUE_ENTRY    pQEntry;
+
+       ASSERT(pTxBlk);
+
+
+       pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+       pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+       if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
+       {
+               RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+               return;
+       }
+
+       if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
+       {
+               INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
+       }
+
+       if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
+               TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
+       else
+               TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
+
+       bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
+
+       if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
+               pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
+
+       STAFindCipherAlgorithm(pAd, pTxBlk);
+       STABuildCommon802_11Header(pAd, pTxBlk);
+
+
+       // skip 802.3 header
+       pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
+       pTxBlk->SrcBufLen  -= LENGTH_802_3;
+
+       // skip vlan tag
+       if (bVLANPkt)
+       {
+               pTxBlk->pSrcBufData     += LENGTH_802_1Q;
+               pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
+       }
+
+       pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
+       pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
+
+       // skip common header
+       pHeaderBufPtr += pTxBlk->MpduHeaderLen;
+
+       if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
+       {
+               //
+               // build QOS Control bytes
+               //
+               *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
+               *(pHeaderBufPtr+1) = 0;
+               pHeaderBufPtr +=2;
+               pTxBlk->MpduHeaderLen += 2;
+       }
+
+       // The remaining content of MPDU header should locate at 4-octets aligment
+       pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
+       pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
+       pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
+
+       {
+
+               //
+               // Insert LLC-SNAP encapsulation - 8 octets
+               //
+               //
+               // if original Ethernet frame contains no LLC/SNAP,
+               // then an extra LLC/SNAP encap is required
+               //
+               EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
+               if (pTxBlk->pExtraLlcSnapEncap)
+               {
+                       UCHAR vlan_size;
+
+                       NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
+                       pHeaderBufPtr += 6;
+                       // skip vlan tag
+                       vlan_size =  (bVLANPkt) ? LENGTH_802_1Q : 0;
+                       // get 2 octets (TypeofLen)
+                       NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
+                       pHeaderBufPtr += 2;
+                       pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
+               }
+
+       }
+
+       //
+       // prepare for TXWI
+       // use Wcid as Key Index
+       //
+
+       RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
+
+       //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
+
+       HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
+
+       pAd->RalinkCounters.KickTxCount++;
+       pAd->RalinkCounters.OneSecTxDoneCount++;
+
+       //
+       // Kick out Tx
+       //
+       HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
+}
+
+
+VOID STA_ARalink_Frame_Tx(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      TX_BLK                  *pTxBlk)
+{
+       PUCHAR                  pHeaderBufPtr;
+       USHORT                  FreeNumber;
+       USHORT                  totalMPDUSize=0;
+       USHORT                  FirstTx, LastTxIdx;
+       int                     frameNum = 0;
+       BOOLEAN                 bVLANPkt;
+       PQUEUE_ENTRY    pQEntry;
+
+
+       ASSERT(pTxBlk);
+
+       ASSERT((pTxBlk->TxPacketList.Number== 2));
+
+
+       FirstTx = LastTxIdx = 0;  // Is it ok init they as 0?
+       while(pTxBlk->TxPacketList.Head)
+       {
+               pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+               pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+
+               if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
+               {
+                       RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+                       continue;
+               }
+
+               bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
+
+               // skip 802.3 header
+               pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
+               pTxBlk->SrcBufLen  -= LENGTH_802_3;
+
+               // skip vlan tag
+               if (bVLANPkt)
+               {
+                       pTxBlk->pSrcBufData     += LENGTH_802_1Q;
+                       pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
+               }
+
+               if (frameNum == 0)
+               {       // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
+
+                       pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
+
+                       // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
+                       //      will be updated after final frame was handled.
+                       RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
+
+
+                       //
+                       // Insert LLC-SNAP encapsulation - 8 octets
+                       //
+                       EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
+
+                       if (pTxBlk->pExtraLlcSnapEncap)
+                       {
+                               NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
+                               pHeaderBufPtr += 6;
+                               // get 2 octets (TypeofLen)
+                               NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
+                               pHeaderBufPtr += 2;
+                               pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
+                       }
+               }
+               else
+               {       // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
+
+                       pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
+                       pTxBlk->MpduHeaderLen = 0;
+
+                       // A-Ralink sub-sequent frame header is the same as 802.3 header.
+                       //   DA(6)+SA(6)+FrameType(2)
+                       NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
+                       pHeaderBufPtr += 12;
+                       // get 2 octets (TypeofLen)
+                       NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
+                       pHeaderBufPtr += 2;
+                       pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
+               }
+
+               totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
+
+               //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
+               if (frameNum ==0)
+                       FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
+               else
+                       LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
+
+               frameNum++;
+
+               pAd->RalinkCounters.OneSecTxAggregationCount++;
+               pAd->RalinkCounters.KickTxCount++;
+               pAd->RalinkCounters.OneSecTxDoneCount++;
+
+       }
+
+       HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
+       HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
+
+       //
+       // Kick out Tx
+       //
+       HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
+
+}
+
+
+VOID STA_Fragment_Frame_Tx(
+       IN RTMP_ADAPTER *pAd,
+       IN TX_BLK               *pTxBlk)
+{
+       HEADER_802_11   *pHeader_802_11;
+       PUCHAR                  pHeaderBufPtr;
+       USHORT                  FreeNumber;
+       UCHAR                   fragNum = 0;
+       PACKET_INFO             PacketInfo;
+       USHORT                  EncryptionOverhead = 0;
+       UINT32                  FreeMpduSize, SrcRemainingBytes;
+       USHORT                  AckDuration;
+       UINT                    NextMpduSize;
+       BOOLEAN                 bVLANPkt;
+       PQUEUE_ENTRY    pQEntry;
+
+
+       ASSERT(pTxBlk);
+
+       pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+       pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+       if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
+       {
+               RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+               return;
+       }
+
+       ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
+       bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
+
+       STAFindCipherAlgorithm(pAd, pTxBlk);
+       STABuildCommon802_11Header(pAd, pTxBlk);
+
+       if (pTxBlk->CipherAlg == CIPHER_TKIP)
+       {
+               pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
+               if (pTxBlk->pPacket == NULL)
+                       return;
+               RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
+       }
+
+       // skip 802.3 header
+       pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
+       pTxBlk->SrcBufLen  -= LENGTH_802_3;
+
+
+       // skip vlan tag
+       if (bVLANPkt)
+       {
+               pTxBlk->pSrcBufData     += LENGTH_802_1Q;
+               pTxBlk->SrcBufLen       -= LENGTH_802_1Q;
+       }
+
+       pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
+       pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
+
+
+       // skip common header
+       pHeaderBufPtr += pTxBlk->MpduHeaderLen;
+
+       if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
+       {
+               //
+               // build QOS Control bytes
+               //
+               *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
+
+               *(pHeaderBufPtr+1) = 0;
+               pHeaderBufPtr +=2;
+               pTxBlk->MpduHeaderLen += 2;
+       }
+
+       //
+       // padding at front of LLC header
+       // LLC header should locate at 4-octets aligment
+       //
+       pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
+       pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
+       pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
+
+
+
+       //
+       // Insert LLC-SNAP encapsulation - 8 octets
+       //
+       //
+       // if original Ethernet frame contains no LLC/SNAP,
+       // then an extra LLC/SNAP encap is required
+       //
+       EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
+       if (pTxBlk->pExtraLlcSnapEncap)
+       {
+               UCHAR vlan_size;
+
+               NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
+               pHeaderBufPtr += 6;
+               // skip vlan tag
+               vlan_size =  (bVLANPkt) ? LENGTH_802_1Q : 0;
+               // get 2 octets (TypeofLen)
+               NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
+               pHeaderBufPtr += 2;
+               pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
+       }
+
+
+       // If TKIP is used and fragmentation is required. Driver has to
+       //      append TKIP MIC at tail of the scatter buffer
+       //      MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
+       if (pTxBlk->CipherAlg == CIPHER_TKIP)
+       {
+
+               // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
+               //                      to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
+               NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
+               //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
+               pTxBlk->SrcBufLen += 8;
+               pTxBlk->TotalFrameLen += 8;
+               pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
+       }
+
+       //
+       // calcuate the overhead bytes that encryption algorithm may add. This
+       // affects the calculate of "duration" field
+       //
+       if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
+               EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
+       else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
+               EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
+       else if (pTxBlk->CipherAlg == CIPHER_TKIP)
+               EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
+       else if (pTxBlk->CipherAlg == CIPHER_AES)
+               EncryptionOverhead = 16;        // AES: IV[4] + EIV[4] + MIC[8]
+       else
+               EncryptionOverhead = 0;
+
+       // decide how much time an ACK/CTS frame will consume in the air
+       AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
+
+       // Init the total payload length of this frame.
+       SrcRemainingBytes = pTxBlk->SrcBufLen;
+
+       pTxBlk->TotalFragNum = 0xff;
+
+       do {
+
+               FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
+
+               FreeMpduSize -= pTxBlk->MpduHeaderLen;
+
+               if (SrcRemainingBytes <= FreeMpduSize)
+               {       // this is the last or only fragment
+
+                       pTxBlk->SrcBufLen = SrcRemainingBytes;
+
+                       pHeader_802_11->FC.MoreFrag = 0;
+                       pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
+
+                       // Indicate the lower layer that this's the last fragment.
+                       pTxBlk->TotalFragNum = fragNum;
+               }
+               else
+               {       // more fragment is required
+
+                       pTxBlk->SrcBufLen = FreeMpduSize;
+
+                       NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
+                       pHeader_802_11->FC.MoreFrag = 1;
+                       pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
+               }
+
+               if (fragNum == 0)
+                       pTxBlk->FrameGap = IFS_HTTXOP;
+               else
+                       pTxBlk->FrameGap = IFS_SIFS;
+
+               RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
+
+               HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
+
+               pAd->RalinkCounters.KickTxCount++;
+               pAd->RalinkCounters.OneSecTxDoneCount++;
+
+               // Update the frame number, remaining size of the NDIS packet payload.
+
+               // space for 802.11 header.
+               if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
+                       pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
+
+               fragNum++;
+               SrcRemainingBytes -= pTxBlk->SrcBufLen;
+               pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
+
+               pHeader_802_11->Frag++;  // increase Frag #
+
+       }while(SrcRemainingBytes > 0);
+
+       //
+       // Kick out Tx
+       //
+       HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
+}
+
+
+#define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status)                                                                              \
+               while(_pTxBlk->TxPacketList.Head)                                                                                                               \
+               {                                                                                                                                                                               \
+                       _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList);                                                                     \
+                       RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status);    \
+               }
+
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Copy frame from waiting queue into relative ring buffer and set
+       appropriate ASIC register to kick hardware encryption before really
+       sent out to air.
+
+       Arguments:
+               pAd     Pointer to our adapter
+               PNDIS_PACKET    Pointer to outgoing Ndis frame
+               NumberOfFrag    Number of fragment required
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+NDIS_STATUS STAHardTransmit(
+       IN PRTMP_ADAPTER        pAd,
+       IN TX_BLK                       *pTxBlk,
+       IN      UCHAR                   QueIdx)
+{
+       NDIS_PACKET             *pPacket;
+       PQUEUE_ENTRY    pQEntry;
+
+       // ---------------------------------------------
+       // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
+       // ---------------------------------------------
+       //
+       ASSERT(pTxBlk->TxPacketList.Number);
+       if (pTxBlk->TxPacketList.Head == NULL)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
+               return NDIS_STATUS_FAILURE;
+       }
+
+       pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
+
+#if 0 //def CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+               if ((pAd->CommonCfg.CarrierDetect.Enable == TRUE) && (isCarrierDetectExist(pAd) == TRUE))
+       {
+               DBGPRINT(RT_DEBUG_INFO,("STAHardTransmit --> radar detect not in normal mode !!!\n"));
+               RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+               return (NDIS_STATUS_FAILURE);
+       }
+#endif // CARRIER_DETECTION_SUPPORT //
+
+       // ------------------------------------------------------------------
+       // STEP 1. WAKE UP PHY
+       //              outgoing frame always wakeup PHY to prevent frame lost and
+       //              turn off PSM bit to improve performance
+       // ------------------------------------------------------------------
+       // not to change PSM bit, just send this frame out?
+       if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+       {
+           DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
+               AsicForceWakeup(pAd, TRUE);
+       }
+
+       // It should not change PSM bit, when APSD turn on.
+       if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
+               || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
+               || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
+       {
+               if ((pAd->StaCfg.Psm == PWR_SAVE) &&
+            (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
+                       MlmeSetPsmBit(pAd, PWR_ACTIVE);
+       }
+
+       switch (pTxBlk->TxFrameType)
+       {
+#ifdef DOT11_N_SUPPORT
+               case TX_AMPDU_FRAME:
+                               STA_AMPDU_Frame_Tx(pAd, pTxBlk);
+                       break;
+               case TX_AMSDU_FRAME:
+                               STA_AMSDU_Frame_Tx(pAd, pTxBlk);
+                       break;
+#endif // DOT11_N_SUPPORT //
+               case TX_LEGACY_FRAME:
+                               STA_Legacy_Frame_Tx(pAd, pTxBlk);
+                       break;
+               case TX_MCAST_FRAME:
+                               STA_Legacy_Frame_Tx(pAd, pTxBlk);
+                       break;
+               case TX_RALINK_FRAME:
+                               STA_ARalink_Frame_Tx(pAd, pTxBlk);
+                       break;
+               case TX_FRAG_FRAME:
+                               STA_Fragment_Frame_Tx(pAd, pTxBlk);
+                       break;
+               default:
+                       {
+                               // It should not happened!
+                               DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
+                               while(pTxBlk->TxPacketList.Number)
+                               {
+                                       pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+                                       pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+                                       if (pPacket)
+                                               RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+                               }
+                       }
+                       break;
+       }
+
+       return (NDIS_STATUS_SUCCESS);
+
+}
+
+ULONG  HashBytesPolynomial(UCHAR *value, unsigned int len)
+{
+   unsigned char *word = value;
+   unsigned int ret = 0;
+   unsigned int i;
+
+   for(i=0; i < len; i++)
+   {
+         int mod = i % 32;
+         ret ^=(unsigned int) (word[i]) << mod;
+         ret ^=(unsigned int) (word[i]) >> (32 - mod);
+   }
+   return ret;
+}
+
+VOID Sta_Announce_or_Forward_802_3_Packet(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PNDIS_PACKET    pPacket,
+       IN      UCHAR                   FromWhichBSSID)
+{
+       if (TRUE
+               )
+       {
+               announce_802_3_packet(pAd, pPacket);
+       }
+       else
+       {
+               // release packet
+               RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+       }
+}
+
diff --git a/drivers/staging/rt2870/sta/sanity.c b/drivers/staging/rt2870/sta/sanity.c
new file mode 100644 (file)
index 0000000..2398724
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       sanity.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       John Chang  2004-09-01      add WMM support
+*/
+#include "../rt_config.h"
+
+extern UCHAR   CISCO_OUI[];
+
+extern UCHAR   WPA_OUI[];
+extern UCHAR   RSN_OUI[];
+extern UCHAR   WME_INFO_ELEM[];
+extern UCHAR   WME_PARM_ELEM[];
+extern UCHAR   Ccx2QosInfo[];
+extern UCHAR   RALINK_OUI[];
+extern UCHAR   BROADCOM_OUI[];
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+ */
+BOOLEAN MlmeStartReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT CHAR Ssid[],
+    OUT UCHAR *pSsidLen)
+{
+    MLME_START_REQ_STRUCT *Info;
+
+    Info = (MLME_START_REQ_STRUCT *)(Msg);
+
+    if (Info->SsidLen > MAX_LEN_OF_SSID)
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqSanity fail - wrong SSID length\n"));
+        return FALSE;
+    }
+
+    *pSsidLen = Info->SsidLen;
+    NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen);
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+
+    IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+BOOLEAN PeerAssocRspSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *pMsg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr2,
+    OUT USHORT *pCapabilityInfo,
+    OUT USHORT *pStatus,
+    OUT USHORT *pAid,
+    OUT UCHAR SupRate[],
+    OUT UCHAR *pSupRateLen,
+    OUT UCHAR ExtRate[],
+    OUT UCHAR *pExtRateLen,
+    OUT HT_CAPABILITY_IE               *pHtCapability,
+    OUT ADD_HT_INFO_IE         *pAddHtInfo,    // AP might use this additional ht info IE
+    OUT UCHAR                  *pHtCapabilityLen,
+    OUT UCHAR                  *pAddHtInfoLen,
+    OUT UCHAR                  *pNewExtChannelOffset,
+    OUT PEDCA_PARM pEdcaParm,
+    OUT UCHAR *pCkipFlag)
+{
+    CHAR          IeType, *Ptr;
+    PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;
+    PEID_STRUCT   pEid;
+    ULONG         Length = 0;
+
+       *pNewExtChannelOffset = 0xff;
+       *pHtCapabilityLen = 0;
+       *pAddHtInfoLen = 0;
+    COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+    Ptr = pFrame->Octet;
+    Length += LENGTH_802_11;
+
+    NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2);
+    Length += 2;
+    NdisMoveMemory(pStatus,         &pFrame->Octet[2], 2);
+    Length += 2;
+    *pCkipFlag = 0;
+    *pExtRateLen = 0;
+    pEdcaParm->bValid = FALSE;
+
+    if (*pStatus != MLME_SUCCESS)
+        return TRUE;
+
+    NdisMoveMemory(pAid, &pFrame->Octet[4], 2);
+    Length += 2;
+
+    // Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform
+    *pAid = (*pAid) & 0x3fff; // AID is low 14-bit
+
+    // -- get supported rates from payload and advance the pointer
+    IeType = pFrame->Octet[6];
+    *pSupRateLen = pFrame->Octet[7];
+    if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity fail - wrong SupportedRates IE\n"));
+        return FALSE;
+    }
+    else
+        NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen);
+
+    Length = Length + 2 + *pSupRateLen;
+
+    // many AP implement proprietary IEs in non-standard order, we'd better
+    // tolerate mis-ordered IEs to get best compatibility
+    pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)];
+
+    // get variable fields from payload and advance the pointer
+    while ((Length + 2 + pEid->Len) <= MsgLen)
+    {
+        switch (pEid->Eid)
+        {
+            case IE_EXT_SUPP_RATES:
+                if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
+                {
+                    NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len);
+                    *pExtRateLen = pEid->Len;
+                }
+                break;
+
+             case IE_HT_CAP:
+            case IE_HT_CAP2:
+                       if (pEid->Len >= SIZE_HT_CAP_IE)  //Note: allow extension.!!
+                       {
+                               NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE);
+
+                               *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
+                               *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
+
+                               *pHtCapabilityLen = SIZE_HT_CAP_IE;
+                       }
+                       else
+                       {
+                               DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_HT_CAP. \n"));
+                       }
+
+               break;
+#ifdef DOT11_N_SUPPORT
+            case IE_ADD_HT:
+            case IE_ADD_HT2:
+                       if (pEid->Len >= sizeof(ADD_HT_INFO_IE))
+                       {
+                               // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only
+                               // copy first sizeof(ADD_HT_INFO_IE)
+                               NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE));
+
+                               *(USHORT *)(&pAddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo2));
+                               *(USHORT *)(&pAddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo3));
+
+                               *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE;
+                       }
+                       else
+                       {
+                               DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_ADD_HT. \n"));
+                       }
+
+               break;
+            case IE_SECONDARY_CH_OFFSET:
+                       if (pEid->Len == 1)
+                       {
+                               *pNewExtChannelOffset = pEid->Octet[0];
+                       }
+                       else
+                       {
+                               DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n"));
+                       }
+#endif // DOT11_N_SUPPORT //
+               break;
+            case IE_AIRONET_CKIP:
+                // 0. Check Aironet IE length, it must be larger or equal to 28
+                //    Cisco's AP VxWork version(will not be supported) used this IE length as 28
+                //    Cisco's AP IOS version used this IE length as 30
+                if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2))
+                break;
+
+                // 1. Copy CKIP flag byte to buffer for process
+                *pCkipFlag = *(pEid->Octet + 8);
+                break;
+
+            case IE_AIRONET_IPADDRESS:
+                if (pEid->Len != 0x0A)
+                break;
+
+                // Get Cisco Aironet IP information
+                if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1)
+                    NdisMoveMemory(pAd->StaCfg.AironetIPAddress, pEid->Octet + 4, 4);
+                break;
+
+            // CCX2, WMM use the same IE value
+            // case IE_CCX_V2:
+            case IE_VENDOR_SPECIFIC:
+                // handle WME PARAMTER ELEMENT
+                if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24))
+                {
+                    PUCHAR ptr;
+                    int i;
+
+                    // parsing EDCA parameters
+                    pEdcaParm->bValid          = TRUE;
+                    pEdcaParm->bQAck           = FALSE; // pEid->Octet[0] & 0x10;
+                    pEdcaParm->bQueueRequest   = FALSE; // pEid->Octet[0] & 0x20;
+                    pEdcaParm->bTxopRequest    = FALSE; // pEid->Octet[0] & 0x40;
+                    //pEdcaParm->bMoreDataAck    = FALSE; // pEid->Octet[0] & 0x80;
+                    pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f;
+                    pEdcaParm->bAPSDCapable    = (pEid->Octet[6] & 0x80) ? 1 : 0;
+                    ptr = &pEid->Octet[8];
+                    for (i=0; i<4; i++)
+                    {
+                        UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX
+                        pEdcaParm->bACM[aci]  = (((*ptr) & 0x10) == 0x10);   // b5 is ACM
+                        pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f;               // b0~3 is AIFSN
+                        pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f;             // b0~4 is Cwmin
+                        pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4;               // b5~8 is Cwmax
+                        pEdcaParm->Txop[aci]  = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us
+                        ptr += 4; // point to next AC
+                    }
+                }
+
+                // handle CCX IE
+                else
+                {
+                    // 0. Check the size and CCX admin control
+                    if (pAd->StaCfg.CCXControl.field.Enable == 0)
+                        break;
+                    if (pEid->Len != 5)
+                        break;
+
+                    // Turn CCX2 if matched
+                    if (NdisEqualMemory(pEid->Octet, Ccx2IeInfo, 5) == 1)
+                        pAd->StaCfg.CCXEnable = TRUE;
+                    break;
+                }
+                break;
+
+            default:
+                DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", pEid->Eid));
+                break;
+        }
+
+        Length = Length + 2 + pEid->Len;
+        pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+    }
+
+    // Force CCX2 enable to TRUE for those AP didn't replay CCX v2 IE, we still force it to be on
+    if (pAd->StaCfg.CCXControl.field.Enable == 1)
+        pAd->StaCfg.CCXEnable = TRUE;
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        MLME message sanity check
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+BOOLEAN PeerProbeReqSanity(
+    IN PRTMP_ADAPTER pAd,
+    IN VOID *Msg,
+    IN ULONG MsgLen,
+    OUT PUCHAR pAddr2,
+    OUT CHAR Ssid[],
+    OUT UCHAR *pSsidLen)
+{
+    UCHAR         Idx;
+    UCHAR            RateLen;
+    CHAR          IeType;
+    PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+
+    COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+
+    if ((pFrame->Octet[0] != IE_SSID) || (pFrame->Octet[1] > MAX_LEN_OF_SSID))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SSID IE(Type=%d,Len=%d)\n",pFrame->Octet[0],pFrame->Octet[1]));
+        return FALSE;
+    }
+
+    *pSsidLen = pFrame->Octet[1];
+    NdisMoveMemory(Ssid, &pFrame->Octet[2], *pSsidLen);
+
+    Idx = *pSsidLen + 2;
+
+    // -- get supported rates from payload and advance the pointer
+    IeType = pFrame->Octet[Idx];
+    RateLen = pFrame->Octet[Idx + 1];
+    if (IeType != IE_SUPP_RATES)
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SupportRates IE(Type=%d,Len=%d)\n",pFrame->Octet[Idx],pFrame->Octet[Idx+1]));
+        return FALSE;
+    }
+    else
+    {
+        if ((pAd->CommonCfg.PhyMode == PHY_11G) && (RateLen < 8))
+            return (FALSE);
+    }
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+
+       IRQL = DISPATCH_LEVEL
+
+    ==========================================================================
+ */
+BOOLEAN GetTimBit(
+    IN CHAR *Ptr,
+    IN USHORT Aid,
+    OUT UCHAR *TimLen,
+    OUT UCHAR *BcastFlag,
+    OUT UCHAR *DtimCount,
+    OUT UCHAR *DtimPeriod,
+    OUT UCHAR *MessageToMe)
+{
+    UCHAR          BitCntl, N1, N2, MyByte, MyBit;
+    CHAR          *IdxPtr;
+
+    IdxPtr = Ptr;
+
+    IdxPtr ++;
+    *TimLen = *IdxPtr;
+
+    // get DTIM Count from TIM element
+    IdxPtr ++;
+    *DtimCount = *IdxPtr;
+
+    // get DTIM Period from TIM element
+    IdxPtr++;
+    *DtimPeriod = *IdxPtr;
+
+    // get Bitmap Control from TIM element
+    IdxPtr++;
+    BitCntl = *IdxPtr;
+
+    if ((*DtimCount == 0) && (BitCntl & 0x01))
+        *BcastFlag = TRUE;
+    else
+        *BcastFlag = FALSE;
+
+    // Parse Partial Virtual Bitmap from TIM element
+    N1 = BitCntl & 0xfe;    // N1 is the first bitmap byte#
+    N2 = *TimLen - 4 + N1;  // N2 is the last bitmap byte#
+
+    if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3)))
+        *MessageToMe = FALSE;
+    else
+    {
+        MyByte = (Aid >> 3) - N1;                       // my byte position in the bitmap byte-stream
+        MyBit = Aid % 16 - ((MyByte & 0x01)? 8:0);
+
+        IdxPtr += (MyByte + 1);
+
+        //if (*IdxPtr)
+        //    DBGPRINT(RT_DEBUG_WARN, ("TIM bitmap = 0x%02x\n", *IdxPtr));
+
+        if (*IdxPtr & (0x01 << MyBit))
+            *MessageToMe = TRUE;
+        else
+            *MessageToMe = FALSE;
+    }
+
+    return TRUE;
+}
+
diff --git a/drivers/staging/rt2870/sta/sync.c b/drivers/staging/rt2870/sta/sync.c
new file mode 100644 (file)
index 0000000..a489755
--- /dev/null
@@ -0,0 +1,1753 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       sync.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       John Chang      2004-09-01      modified for rt2561/2661
+       Jan Lee         2006-08-01      modified for rt2860 for 802.11n
+*/
+#include "../rt_config.h"
+
+#define ADHOC_ENTRY_BEACON_LOST_TIME   (2*OS_HZ)       // 2 sec
+
+/*
+       ==========================================================================
+       Description:
+               The sync state machine,
+       Parameters:
+               Sm - pointer to the state machine
+       Note:
+               the state machine looks like the following
+
+       ==========================================================================
+ */
+VOID SyncStateMachineInit(
+       IN PRTMP_ADAPTER pAd,
+       IN STATE_MACHINE *Sm,
+       OUT STATE_MACHINE_FUNC Trans[])
+{
+       StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE);
+
+       // column 1
+       StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction);
+       StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction);
+       StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction);
+       StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon);
+       StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction);
+
+       //column 2
+       StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
+       StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
+       StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
+       StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction);
+       StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction);
+
+       // column 3
+       StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
+       StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
+       StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
+       StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
+       StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
+       StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction);
+
+       // timer init
+       RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE);
+       RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE);
+}
+
+/*
+       ==========================================================================
+       Description:
+               Beacon timeout handler, executed in timer thread
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID BeaconTimeout(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3)
+{
+       RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+       DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n"));
+
+       // Do nothing if the driver is starting halt state.
+       // This might happen when timer already been fired before cancel timer with mlmehalt
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
+               return;
+
+#ifdef DOT11_N_SUPPORT
+       if ((pAd->CommonCfg.BBPCurrentBW == BW_40)
+               )
+       {
+               UCHAR        BBPValue = 0;
+               AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+               AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+               BBPValue &= (~0x18);
+               BBPValue |= 0x10;
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+               DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr));
+       }
+#endif // DOT11_N_SUPPORT //
+
+       MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL);
+       RT28XX_MLME_HANDLER(pAd);
+}
+
+/*
+       ==========================================================================
+       Description:
+               Scan timeout handler, executed in timer thread
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID ScanTimeout(
+       IN PVOID SystemSpecific1,
+       IN PVOID FunctionContext,
+       IN PVOID SystemSpecific2,
+       IN PVOID SystemSpecific3)
+{
+       RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+
+       // Do nothing if the driver is starting halt state.
+       // This might happen when timer already been fired before cancel timer with mlmehalt
+       if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
+               return;
+
+       if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL))
+       {
+               RT28XX_MLME_HANDLER(pAd);
+       }
+       else
+       {
+               // To prevent SyncMachine.CurrState is SCAN_LISTEN forever.
+               pAd->MlmeAux.Channel = 0;
+               ScanNextChannel(pAd);
+               if (pAd->CommonCfg.bWirelessEvent)
+               {
+                       RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+               }
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+               MLME SCAN req state machine procedure
+       ==========================================================================
+ */
+VOID MlmeScanReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR          Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0;
+       BOOLEAN        TimerCancelled;
+       ULONG              Now;
+       USHORT         Status;
+       PHEADER_802_11 pHdr80211;
+       PUCHAR         pOutBuffer = NULL;
+       NDIS_STATUS    NStatus;
+
+       // Check the total scan tries for one single OID command
+       // If this is the CCX 2.0 Case, skip that!
+       if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n"));
+               return;
+       }
+
+       // Increase the scan retry counters.
+       pAd->StaCfg.ScanCnt++;
+
+
+       // first check the parameter sanity
+       if (MlmeScanReqSanity(pAd,
+                                                 Elem->Msg,
+                                                 Elem->MsgLen,
+                                                 &BssType,
+                                                 Ssid,
+                                                 &SsidLen,
+                                                 &ScanType))
+       {
+
+               // Check for channel load and noise hist request
+               // Suspend MSDU only at scan request, not the last two mentioned
+               if ((ScanType == SCAN_CISCO_NOISE) || (ScanType == SCAN_CISCO_CHANNEL_LOAD))
+               {
+                       if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
+                               RTMPSuspendMsduTransmission(pAd);                       // Suspend MSDU transmission here
+               }
+               else
+               {
+                       // Suspend MSDU transmission here
+                       RTMPSuspendMsduTransmission(pAd);
+               }
+
+               //
+               // To prevent data lost.
+               // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress.
+               // And should send an NULL data with turned PSM bit off to AP, when scan progress done
+               //
+               if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)))
+               {
+                       NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);
+                       if (NStatus     == NDIS_STATUS_SUCCESS)
+                       {
+                               pHdr80211 = (PHEADER_802_11) pOutBuffer;
+                               MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
+                               pHdr80211->Duration = 0;
+                               pHdr80211->FC.Type = BTYPE_DATA;
+                               pHdr80211->FC.PwrMgmt = PWR_SAVE;
+
+                               // Send using priority queue
+                               MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
+                               DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n"));
+                               MlmeFreeMemory(pAd, pOutBuffer);
+                               RTMPusecDelay(5000);
+                       }
+               }
+
+               NdisGetSystemUpTime(&Now);
+               pAd->StaCfg.LastScanTime = Now;
+               // reset all the timers
+               RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
+
+               // record desired BSS parameters
+               pAd->MlmeAux.BssType = BssType;
+               pAd->MlmeAux.ScanType = ScanType;
+               pAd->MlmeAux.SsidLen = SsidLen;
+        NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
+               NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
+
+               // start from the first channel
+               pAd->MlmeAux.Channel = FirstChannel(pAd);
+
+               // Change the scan channel when dealing with CCX beacon report
+               if ((ScanType == SCAN_CISCO_PASSIVE) || (ScanType == SCAN_CISCO_ACTIVE) ||
+                       (ScanType == SCAN_CISCO_CHANNEL_LOAD) || (ScanType == SCAN_CISCO_NOISE))
+                       pAd->MlmeAux.Channel = pAd->StaCfg.CCXScanChannel;
+
+               // Let BBP register at 20MHz to do scan
+               RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+               BBPValue &= (~0x18);
+               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+               DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
+               ScanNextChannel(pAd);
+       }
+       else
+       {
+               DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n"));
+               pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+               Status = MLME_INVALID_FORMAT;
+               MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+               MLME JOIN req state machine procedure
+       ==========================================================================
+ */
+VOID MlmeJoinReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR        BBPValue = 0;
+       BSS_ENTRY    *pBss;
+       BOOLEAN       TimerCancelled;
+       HEADER_802_11 Hdr80211;
+       NDIS_STATUS   NStatus;
+       ULONG         FrameLen = 0;
+       PUCHAR        pOutBuffer = NULL;
+       PUCHAR        pSupRate = NULL;
+       UCHAR         SupRateLen;
+       PUCHAR        pExtRate = NULL;
+       UCHAR         ExtRateLen;
+       UCHAR         ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C};
+       UCHAR         ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR);
+       MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx));
+
+
+       // reset all the timers
+       RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
+       RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
+
+       pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx];
+
+       // record the desired SSID & BSSID we're waiting for
+       COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid);
+
+       // If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again.
+       if (pBss->Hidden == 0)
+       {
+               NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen);
+               pAd->MlmeAux.SsidLen = pBss->SsidLen;
+       }
+
+       pAd->MlmeAux.BssType = pBss->BssType;
+       pAd->MlmeAux.Channel = pBss->Channel;
+       pAd->MlmeAux.CentralChannel = pBss->CentralChannel;
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+       // Country IE of the AP will be evaluated and will be used.
+       if ((pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) &&
+               (pBss->bHasCountryIE == TRUE))
+       {
+               NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pBss->CountryString[0], 2);
+               if (pBss->CountryString[2] == 'I')
+                       pAd->CommonCfg.Geography = IDOR;
+               else if (pBss->CountryString[2] == 'O')
+                       pAd->CommonCfg.Geography = ODOR;
+               else
+                       pAd->CommonCfg.Geography = BOTH;
+               BuildChannelListEx(pAd);
+       }
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+       // Let BBP register at 20MHz to do scan
+       RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+       BBPValue &= (~0x18);
+       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
+
+       // switch channel and waiting for beacon timer
+       AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
+       AsicLockChannel(pAd, pAd->MlmeAux.Channel);
+       RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT);
+
+    do
+       {
+               if (((pAd->CommonCfg.bIEEE80211H == 1) &&
+            (pAd->MlmeAux.Channel > 14) &&
+             RadarChannelCheck(pAd, pAd->MlmeAux.Channel))
+#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+             || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+#endif // CARRIER_DETECTION_SUPPORT //
+            )
+               {
+                       //
+                       // We can't send any Probe request frame to meet 802.11h.
+                       //
+                       if (pBss->Hidden == 0)
+                               break;
+               }
+
+               //
+               // send probe request
+               //
+               NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+               if (NStatus == NDIS_STATUS_SUCCESS)
+               {
+                       if (pAd->MlmeAux.Channel <= 14)
+                       {
+                               pSupRate = pAd->CommonCfg.SupRate;
+                               SupRateLen = pAd->CommonCfg.SupRateLen;
+                               pExtRate = pAd->CommonCfg.ExtRate;
+                               ExtRateLen = pAd->CommonCfg.ExtRateLen;
+                       }
+                       else
+                       {
+                               //
+                               // Overwrite Support Rate, CCK rate are not allowed
+                               //
+                               pSupRate = ASupRate;
+                               SupRateLen = ASupRateLen;
+                               ExtRateLen = 0;
+                       }
+
+                       if (pAd->MlmeAux.BssType == BSS_INFRA)
+                               MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid);
+                       else
+                               MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
+
+                       MakeOutgoingFrame(pOutBuffer,               &FrameLen,
+                                                         sizeof(HEADER_802_11),    &Hdr80211,
+                                                         1,                        &SsidIe,
+                                                         1,                        &pAd->MlmeAux.SsidLen,
+                                                         pAd->MlmeAux.SsidLen,     pAd->MlmeAux.Ssid,
+                                                         1,                        &SupRateIe,
+                                                         1,                        &SupRateLen,
+                                                         SupRateLen,               pSupRate,
+                                                         END_OF_ARGS);
+
+                       if (ExtRateLen)
+                       {
+                               ULONG Tmp;
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,            &Tmp,
+                                                                 1,                                &ExtRateIe,
+                                                                 1,                                &ExtRateLen,
+                                                                 ExtRateLen,                       pExtRate,
+                                                                 END_OF_ARGS);
+                               FrameLen += Tmp;
+                       }
+
+
+                       MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+                       MlmeFreeMemory(pAd, pOutBuffer);
+               }
+    } while (FALSE);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n",
+               pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
+
+       pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON;
+}
+
+/*
+       ==========================================================================
+       Description:
+               MLME START Request state machine procedure, starting an IBSS
+       ==========================================================================
+ */
+VOID MlmeStartReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR         Ssid[MAX_LEN_OF_SSID], SsidLen;
+       BOOLEAN       TimerCancelled;
+
+       // New for WPA security suites
+       UCHAR                                           VarIE[MAX_VIE_LEN];     // Total VIE length = MAX_VIE_LEN - -5
+       NDIS_802_11_VARIABLE_IEs        *pVIE = NULL;
+       LARGE_INTEGER                           TimeStamp;
+       BOOLEAN Privacy;
+       USHORT Status;
+
+       // Init Variable IE structure
+       pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
+       pVIE->Length = 0;
+       TimeStamp.u.LowPart  = 0;
+       TimeStamp.u.HighPart = 0;
+
+       if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, Ssid, &SsidLen))
+       {
+               // reset all the timers
+               RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
+               RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
+
+               //
+               // Start a new IBSS. All IBSS parameters are decided now....
+               //
+               DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n"));
+               pAd->MlmeAux.BssType           = BSS_ADHOC;
+               NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
+               pAd->MlmeAux.SsidLen           = SsidLen;
+
+               // generate a radom number as BSSID
+               MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid);
+               DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n"));
+
+               Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
+                                 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
+                                 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
+               pAd->MlmeAux.CapabilityInfo    = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0);
+               pAd->MlmeAux.BeaconPeriod      = pAd->CommonCfg.BeaconPeriod;
+               pAd->MlmeAux.AtimWin           = pAd->StaCfg.AtimWin;
+               pAd->MlmeAux.Channel           = pAd->CommonCfg.Channel;
+
+               pAd->CommonCfg.CentralChannel  = pAd->CommonCfg.Channel;
+               pAd->MlmeAux.CentralChannel    = pAd->CommonCfg.CentralChannel;
+
+               pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen;
+               NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
+               RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
+               pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen;
+               NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
+               RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
+#ifdef DOT11_N_SUPPORT
+               if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+               {
+                       RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo);
+                       pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE);
+                       // Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here.
+                       DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n"));
+               }
+               else
+#endif // DOT11_N_SUPPORT //
+               {
+                       pAd->MlmeAux.HtCapabilityLen = 0;
+                       pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
+               }
+               // temporarily not support QOS in IBSS
+               NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
+               NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
+               NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
+
+               AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
+               AsicLockChannel(pAd, pAd->MlmeAux.Channel);
+
+               DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n",
+                       pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
+
+               pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+               Status = MLME_SUCCESS;
+               MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
+       }
+       else
+       {
+               DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n"));
+               pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+               Status = MLME_INVALID_FORMAT;
+               MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
+       }
+}
+
+/*
+       ==========================================================================
+       Description:
+               peer sends beacon back when scanning
+       ==========================================================================
+ */
+VOID PeerBeaconAtScanAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR           Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
+       UCHAR           Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel,
+                                       SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe;
+       CF_PARM         CfParm;
+       USHORT          BeaconPeriod, AtimWin, CapabilityInfo;
+       PFRAME_802_11   pFrame;
+       LARGE_INTEGER   TimeStamp;
+       UCHAR           Erp;
+       UCHAR           SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR                   SupRateLen, ExtRateLen;
+       USHORT                  LenVIE;
+       UCHAR                   CkipFlag;
+       UCHAR                   AironetCellPowerLimit;
+       EDCA_PARM       EdcaParm;
+       QBSS_LOAD_PARM  QbssLoad;
+       QOS_CAPABILITY_PARM QosCapability;
+       ULONG                                           RalinkIe;
+       UCHAR                                           VarIE[MAX_VIE_LEN];             // Total VIE length = MAX_VIE_LEN - -5
+       NDIS_802_11_VARIABLE_IEs        *pVIE = NULL;
+       HT_CAPABILITY_IE                HtCapability;
+       ADD_HT_INFO_IE          AddHtInfo;      // AP might use this additional ht info IE
+       UCHAR                   HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
+       UCHAR                   AddHtInfoLen;
+       UCHAR                   NewExtChannelOffset = 0xff;
+
+
+       // NdisFillMemory(Ssid, MAX_LEN_OF_SSID, 0x00);
+       pFrame = (PFRAME_802_11) Elem->Msg;
+       // Init Variable IE structure
+       pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
+       pVIE->Length = 0;
+#ifdef DOT11_N_SUPPORT
+    RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
+       RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
+#endif // DOT11_N_SUPPORT //
+
+       if (PeerBeaconAndProbeRspSanity(pAd,
+                                                               Elem->Msg,
+                                                               Elem->MsgLen,
+                                                               Elem->Channel,
+                                                               Addr2,
+                                                               Bssid,
+                                                               Ssid,
+                                                               &SsidLen,
+                                                               &BssType,
+                                                               &BeaconPeriod,
+                                                               &Channel,
+                                                               &NewChannel,
+                                                               &TimeStamp,
+                                                               &CfParm,
+                                                               &AtimWin,
+                                                               &CapabilityInfo,
+                                                               &Erp,
+                                                               &DtimCount,
+                                                               &DtimPeriod,
+                                                               &BcastFlag,
+                                                               &MessageToMe,
+                                                               SupRate,
+                                                               &SupRateLen,
+                                                               ExtRate,
+                                                               &ExtRateLen,
+                                                               &CkipFlag,
+                                                               &AironetCellPowerLimit,
+                                                               &EdcaParm,
+                                                               &QbssLoad,
+                                                               &QosCapability,
+                                                               &RalinkIe,
+                                                               &HtCapabilityLen,
+                                                               &PreNHtCapabilityLen,
+                                                               &HtCapability,
+                                                               &AddHtInfoLen,
+                                                               &AddHtInfo,
+                                                               &NewExtChannelOffset,
+                                                               &LenVIE,
+                                                               pVIE))
+       {
+               ULONG Idx;
+               CHAR Rssi = 0;
+
+               Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
+               if (Idx != BSS_NOT_FOUND)
+                       Rssi = pAd->ScanTab.BssEntry[Idx].Rssi;
+
+               Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
+
+
+#ifdef DOT11_N_SUPPORT
+               if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
+                       HtCapabilityLen = SIZE_HT_CAP_IE;
+#endif // DOT11_N_SUPPORT //
+               if ((pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) && (Channel == pAd->StaCfg.CCXScanChannel))
+               {
+                       Idx = BssTableSetEntry(pAd, &pAd->StaCfg.CCXBssTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
+                                                &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen,ExtRate, ExtRateLen, &HtCapability,
+                                                &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
+                                                &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
+                       if (Idx != BSS_NOT_FOUND)
+                       {
+                               NdisMoveMemory(pAd->StaCfg.CCXBssTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
+                               NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
+                               NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
+                               if (pAd->StaCfg.CCXReqType == MSRN_TYPE_BEACON_REQ)
+                                       AironetAddBeaconReport(pAd, Idx, Elem);
+                       }
+               }
+               else
+               {
+                       Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
+                                                 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,  &HtCapability,
+                                                &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
+                                                &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+                       if (pAd->ChannelList[pAd->CommonCfg.ChannelListIdx].bEffectedChannel == TRUE)
+                       {
+                               UCHAR           RegClass;
+                               PeerBeaconAndProbeRspSanity2(pAd, Elem->Msg, Elem->MsgLen, &RegClass);
+                               TriEventTableSetEntry(pAd, &pAd->CommonCfg.TriggerEventTab, Bssid, &HtCapability, HtCapabilityLen, RegClass, Channel);
+                       }
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+                       if (Idx != BSS_NOT_FOUND)
+                       {
+                               NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
+                               NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
+                               NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
+                       }
+               }
+       }
+       // sanity check fail, ignored
+}
+
+/*
+       ==========================================================================
+       Description:
+               When waiting joining the (I)BSS, beacon received from external
+       ==========================================================================
+ */
+VOID PeerBeaconAtJoinAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR         Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
+       UCHAR         Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe,
+                                 DtimCount, DtimPeriod, BcastFlag, NewChannel;
+       LARGE_INTEGER TimeStamp;
+       USHORT        BeaconPeriod, AtimWin, CapabilityInfo;
+       CF_PARM       Cf;
+       BOOLEAN       TimerCancelled;
+       UCHAR         Erp;
+       UCHAR         SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR             SupRateLen, ExtRateLen;
+       UCHAR         CkipFlag;
+       USHORT            LenVIE;
+       UCHAR             AironetCellPowerLimit;
+       EDCA_PARM       EdcaParm;
+       QBSS_LOAD_PARM  QbssLoad;
+       QOS_CAPABILITY_PARM QosCapability;
+       USHORT        Status;
+       UCHAR                                           VarIE[MAX_VIE_LEN];             // Total VIE length = MAX_VIE_LEN - -5
+       NDIS_802_11_VARIABLE_IEs        *pVIE = NULL;
+       ULONG           RalinkIe;
+       ULONG         Idx;
+       HT_CAPABILITY_IE                HtCapability;
+       ADD_HT_INFO_IE          AddHtInfo;      // AP might use this additional ht info IE
+       UCHAR                           HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
+       UCHAR                   AddHtInfoLen;
+       UCHAR                   NewExtChannelOffset = 0xff;
+#ifdef DOT11_N_SUPPORT
+       UCHAR                   CentralChannel;
+#endif // DOT11_N_SUPPORT //
+
+       // Init Variable IE structure
+       pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
+       pVIE->Length = 0;
+    RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
+       RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
+
+
+       if (PeerBeaconAndProbeRspSanity(pAd,
+                                                               Elem->Msg,
+                                                               Elem->MsgLen,
+                                                               Elem->Channel,
+                                                               Addr2,
+                                                               Bssid,
+                                                               Ssid,
+                                                               &SsidLen,
+                                                               &BssType,
+                                                               &BeaconPeriod,
+                                                               &Channel,
+                                                               &NewChannel,
+                                                               &TimeStamp,
+                                                               &Cf,
+                                                               &AtimWin,
+                                                               &CapabilityInfo,
+                                                               &Erp,
+                                                               &DtimCount,
+                                                               &DtimPeriod,
+                                                               &BcastFlag,
+                                                               &MessageToMe,
+                                                               SupRate,
+                                                               &SupRateLen,
+                                                               ExtRate,
+                                                               &ExtRateLen,
+                                                               &CkipFlag,
+                                                               &AironetCellPowerLimit,
+                                                               &EdcaParm,
+                                                               &QbssLoad,
+                                                               &QosCapability,
+                                                               &RalinkIe,
+                                                               &HtCapabilityLen,
+                                                               &PreNHtCapabilityLen,
+                                                               &HtCapability,
+                                                               &AddHtInfoLen,
+                                                               &AddHtInfo,
+                                                               &NewExtChannelOffset,
+                                                               &LenVIE,
+                                                               pVIE))
+       {
+               // Disqualify 11b only adhoc when we are in 11g only adhoc mode
+               if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12))
+                       return;
+
+               // BEACON from desired BSS/IBSS found. We should be able to decide most
+               // BSS parameters here.
+               // Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION?
+               //    Do we need to receover back all parameters belonging to previous BSS?
+               // A. Should be not. There's no back-door recover to previous AP. It still need
+               //    a new JOIN-AUTH-ASSOC sequence.
+               if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel));
+                       RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
+
+                       // Update RSSI to prevent No signal display when cards first initialized
+                       pAd->StaCfg.RssiSample.LastRssi0        = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0);
+                       pAd->StaCfg.RssiSample.LastRssi1        = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1);
+                       pAd->StaCfg.RssiSample.LastRssi2        = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2);
+                       pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0;
+                       pAd->StaCfg.RssiSample.AvgRssi0X8       = pAd->StaCfg.RssiSample.AvgRssi0 << 3;
+                       pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1;
+                       pAd->StaCfg.RssiSample.AvgRssi1X8       = pAd->StaCfg.RssiSample.AvgRssi1 << 3;
+                       pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2;
+                       pAd->StaCfg.RssiSample.AvgRssi2X8       = pAd->StaCfg.RssiSample.AvgRssi2 << 3;
+
+                       //
+                       // We need to check if SSID only set to any, then we can record the current SSID.
+                       // Otherwise will cause hidden SSID association failed.
+                       //
+                       if (pAd->MlmeAux.SsidLen == 0)
+                       {
+                               NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
+                               pAd->MlmeAux.SsidLen = SsidLen;
+                       }
+                       else
+                       {
+                               Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel);
+
+                               if (Idx != BSS_NOT_FOUND)
+                               {
+                                       //
+                                       // Multiple SSID case, used correct CapabilityInfo
+                                       //
+                                       CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo;
+                               }
+                       }
+                       NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN);
+                       pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
+                       pAd->MlmeAux.BssType = BssType;
+                       pAd->MlmeAux.BeaconPeriod = BeaconPeriod;
+                       pAd->MlmeAux.Channel = Channel;
+                       pAd->MlmeAux.AtimWin = AtimWin;
+                       pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod;
+                       pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration;
+                       pAd->MlmeAux.APRalinkIe = RalinkIe;
+
+                       // Copy AP's supported rate to MlmeAux for creating assoication request
+                       // Also filter out not supported rate
+                       pAd->MlmeAux.SupRateLen = SupRateLen;
+                       NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
+                       RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
+                       pAd->MlmeAux.ExtRateLen = ExtRateLen;
+                       NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
+                       RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
+
+            NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16);
+#ifdef DOT11_N_SUPPORT
+                       pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
+                       pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen;
+
+                       // filter out un-supported ht rates
+                       if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+                       {
+                               RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
+                               RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE);
+
+                               // StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability
+                               NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16);
+                               pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
+                               pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE;
+                               pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
+                               if (PreNHtCapabilityLen > 0)
+                                       pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE;
+                               RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo);
+                               // Copy AP Parameter to StaActive.  This is also in LinkUp.
+                               DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n",
+                                       pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth));
+
+                               if (AddHtInfoLen > 0)
+                               {
+                                       CentralChannel = AddHtInfo.ControlChan;
+                                       // Check again the Bandwidth capability of this AP.
+                                       if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
+                                       {
+                                               CentralChannel = AddHtInfo.ControlChan - 2;
+                                       }
+                                       else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
+                                       {
+                                               CentralChannel = AddHtInfo.ControlChan + 2;
+                                       }
+
+                                       // Check Error .
+                                       if (pAd->MlmeAux.CentralChannel != CentralChannel)
+                                               DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel));
+
+                                       DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d,  .\n", CentralChannel, AddHtInfo.ControlChan));
+
+                               }
+
+                       }
+                       else
+#endif // DOT11_N_SUPPORT //
+                       {
+                               // To prevent error, let legacy AP must have same CentralChannel and Channel.
+                               if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0))
+                                       pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel;
+
+                               pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
+                               RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
+                               RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE);
+                       }
+
+                       RTMPUpdateMlmeRate(pAd);
+
+                       // copy QOS related information
+                       if ((pAd->CommonCfg.bWmmCapable)
+#ifdef DOT11_N_SUPPORT
+                                || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+#endif // DOT11_N_SUPPORT //
+                               )
+                       {
+                               NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM));
+                               NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
+                               NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
+                       }
+                       else
+                       {
+                               NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
+                               NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
+                               NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
+                       }
+
+                       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n",
+                                                                               pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
+
+#ifdef LEAP_SUPPORT
+                       // Update CkipFlag
+                       pAd->StaCfg.CkipFlag = CkipFlag;
+
+                       // Keep TimeStamp for Re-Association used.
+                       if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE))
+                               pAd->StaCfg.CCKMBeaconAtJoinTimeStamp = TimeStamp;
+#endif // LEAP_SUPPORT //
+
+                       if (AironetCellPowerLimit != 0xFF)
+                       {
+                               //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power
+                               ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
+                       }
+                       else  //Used the default TX Power Percentage.
+                               pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
+
+                       pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+                       Status = MLME_SUCCESS;
+                       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
+               }
+               // not to me BEACON, ignored
+       }
+       // sanity check fail, ignore this frame
+}
+
+/*
+       ==========================================================================
+       Description:
+               receive BEACON from peer
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID PeerBeacon(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR         Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
+       CHAR          Ssid[MAX_LEN_OF_SSID];
+       CF_PARM       CfParm;
+       UCHAR         SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0;
+       UCHAR         DtimCount=0, DtimPeriod=0, BcastFlag=0;
+       USHORT        CapabilityInfo, AtimWin, BeaconPeriod;
+       LARGE_INTEGER TimeStamp;
+       USHORT        TbttNumToNextWakeUp;
+       UCHAR         Erp;
+       UCHAR         SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+       UCHAR             SupRateLen, ExtRateLen;
+       UCHAR             CkipFlag;
+       USHORT        LenVIE;
+       UCHAR             AironetCellPowerLimit;
+       EDCA_PARM       EdcaParm;
+       QBSS_LOAD_PARM  QbssLoad;
+       QOS_CAPABILITY_PARM QosCapability;
+       ULONG           RalinkIe;
+       // New for WPA security suites
+       UCHAR                                           VarIE[MAX_VIE_LEN];             // Total VIE length = MAX_VIE_LEN - -5
+       NDIS_802_11_VARIABLE_IEs        *pVIE = NULL;
+       HT_CAPABILITY_IE                HtCapability;
+       ADD_HT_INFO_IE          AddHtInfo;      // AP might use this additional ht info IE
+       UCHAR                   HtCapabilityLen, PreNHtCapabilityLen;
+       UCHAR                   AddHtInfoLen;
+       UCHAR                   NewExtChannelOffset = 0xff;
+
+
+#ifdef RALINK_ATE
+    if (ATE_ON(pAd))
+    {
+               return;
+    }
+#endif // RALINK_ATE //
+
+       if (!(INFRA_ON(pAd) || ADHOC_ON(pAd)
+               ))
+               return;
+
+       // Init Variable IE structure
+       pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
+       pVIE->Length = 0;
+    RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
+       RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
+
+       if (PeerBeaconAndProbeRspSanity(pAd,
+                                                               Elem->Msg,
+                                                               Elem->MsgLen,
+                                                               Elem->Channel,
+                                                               Addr2,
+                                                               Bssid,
+                                                               Ssid,
+                                                               &SsidLen,
+                                                               &BssType,
+                                                               &BeaconPeriod,
+                                                               &Channel,
+                                                               &NewChannel,
+                                                               &TimeStamp,
+                                                               &CfParm,
+                                                               &AtimWin,
+                                                               &CapabilityInfo,
+                                                               &Erp,
+                                                               &DtimCount,
+                                                               &DtimPeriod,
+                                                               &BcastFlag,
+                                                               &MessageToMe,
+                                                               SupRate,
+                                                               &SupRateLen,
+                                                               ExtRate,
+                                                               &ExtRateLen,
+                                                               &CkipFlag,
+                                                               &AironetCellPowerLimit,
+                                                               &EdcaParm,
+                                                               &QbssLoad,
+                                                               &QosCapability,
+                                                               &RalinkIe,
+                                                               &HtCapabilityLen,
+                                                               &PreNHtCapabilityLen,
+                                                               &HtCapability,
+                                                               &AddHtInfoLen,
+                                                               &AddHtInfo,
+                                                               &NewExtChannelOffset,
+                                                               &LenVIE,
+                                                               pVIE))
+       {
+               BOOLEAN is_my_bssid, is_my_ssid;
+               ULONG   Bssidx, Now;
+               BSS_ENTRY *pBss;
+               CHAR            RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
+
+               is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE;
+               is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE;
+
+
+               // ignore BEACON not for my SSID
+               if ((! is_my_ssid) && (! is_my_bssid))
+                       return;
+
+               // It means STA waits disassoc completely from this AP, ignores this beacon.
+               if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC)
+                       return;
+
+#ifdef DOT11_N_SUPPORT
+               // Copy Control channel for this BSSID.
+               if (AddHtInfoLen != 0)
+                       Channel = AddHtInfo.ControlChan;
+
+               if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
+                       HtCapabilityLen = SIZE_HT_CAP_IE;
+#endif // DOT11_N_SUPPORT //
+
+               //
+               // Housekeeping "SsidBssTab" table for later-on ROAMing usage.
+               //
+               Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
+               if (Bssidx == BSS_NOT_FOUND)
+               {
+                       // discover new AP of this network, create BSS entry
+                       Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
+                                                &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,
+                                               &HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel,
+                                               RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability,
+                                               &QbssLoad, LenVIE, pVIE);
+                       if (Bssidx == BSS_NOT_FOUND) // return if BSS table full
+                               return;
+
+                       NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4);
+                       NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
+                       NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
+
+
+
+               }
+
+               if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
+               {
+                       // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
+                       // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
+                       AsicSwitchChannel(pAd, 1, FALSE);
+                       AsicLockChannel(pAd, 1);
+                   LinkDown(pAd, FALSE);
+                       MlmeQueueInit(&pAd->Mlme.Queue);
+                       BssTableInit(&pAd->ScanTab);
+                   RTMPusecDelay(1000000);             // use delay to prevent STA do reassoc
+
+                       // channel sanity check
+                       for (index = 0 ; index < pAd->ChannelListNum; index++)
+                       {
+                               if (pAd->ChannelList[index].Channel == NewChannel)
+                               {
+                                       pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
+                                       pAd->CommonCfg.Channel = NewChannel;
+                                       AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+                                       AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
+                                       break;
+                               }
+                       }
+
+                       if (index >= pAd->ChannelListNum)
+                       {
+                               DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
+                       }
+               }
+
+               // if the ssid matched & bssid unmatched, we should select the bssid with large value.
+               // This might happened when two STA start at the same time
+               if ((! is_my_bssid) && ADHOC_ON(pAd))
+               {
+                       INT     i;
+
+                       // Add the safeguard against the mismatch of adhoc wep status
+                       if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus)
+                       {
+                               return;
+                       }
+
+                       // collapse into the ADHOC network which has bigger BSSID value.
+                       for (i = 0; i < 6; i++)
+                       {
+                               if (Bssid[i] > pAd->CommonCfg.Bssid[i])
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n",
+                                               Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
+                                       AsicDisableSync(pAd);
+                                       COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid);
+                                       AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
+                                       MakeIbssBeacon(pAd);        // re-build BEACON frame
+                                       AsicEnableIbssSync(pAd);    // copy BEACON frame to on-chip memory
+                                       is_my_bssid = TRUE;
+                                       break;
+                               }
+                               else if (Bssid[i] < pAd->CommonCfg.Bssid[i])
+                                       break;
+                       }
+               }
+
+
+               NdisGetSystemUpTime(&Now);
+               pBss = &pAd->ScanTab.BssEntry[Bssidx];
+               pBss->Rssi = RealRssi;       // lastest RSSI
+               pBss->LastBeaconRxTime = Now;   // last RX timestamp
+
+               //
+               // BEACON from my BSSID - either IBSS or INFRA network
+               //
+               if (is_my_bssid)
+               {
+                       RXWI_STRUC      RxWI;
+
+                       pAd->StaCfg.DtimCount = DtimCount;
+                       pAd->StaCfg.DtimPeriod = DtimPeriod;
+                       pAd->StaCfg.LastBeaconRxTime = Now;
+
+
+                       RxWI.RSSI0 = Elem->Rssi0;
+                       RxWI.RSSI1 = Elem->Rssi1;
+                       RxWI.RSSI2 = Elem->Rssi2;
+
+                       Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI);
+                       if (AironetCellPowerLimit != 0xFF)
+                       {
+                               //
+                               // We get the Cisco (ccx) "TxPower Limit" required
+                               // Changed to appropriate TxPower Limit for Ciso Compatible Extensions
+                               //
+                               ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
+                       }
+                       else
+                       {
+                               //
+                               // AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist.
+                               // Used the default TX Power Percentage, that set from UI.
+                               //
+                               pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
+                       }
+
+                       if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo)))
+                       {
+                               UCHAR                   MaxSupportedRateIn500Kbps = 0;
+                               UCHAR                   idx;
+                               MAC_TABLE_ENTRY *pEntry;
+
+                               // supported rates array may not be sorted. sort it and find the maximum rate
+                           for (idx=0; idx<SupRateLen; idx++)
+                           {
+                               if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f))
+                                   MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f;
+                           }
+
+                               for (idx=0; idx<ExtRateLen; idx++)
+                           {
+                               if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f))
+                                   MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f;
+                           }
+
+                               // look up the existing table
+                               pEntry = MacTableLookup(pAd, Addr2);
+
+                               // Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon.
+                               // To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station.
+                               if ((ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID)) ||
+                                       (pEntry && ((pEntry->LastBeaconRxTime + ADHOC_ENTRY_BEACON_LOST_TIME) < Now)))
+                               {
+                                       if (pEntry == NULL)
+                                               // Another adhoc joining, add to our MAC table.
+                                               pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE);
+
+                                       if (StaAddMacTableEntry(pAd, pEntry, MaxSupportedRateIn500Kbps, &HtCapability, HtCapabilityLen, CapabilityInfo) == FALSE)
+                                       {
+                                               DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n"));
+                                               return;
+                                       }
+
+                                       if (pEntry &&
+                                               (Elem->Wcid == RESERVED_WCID))
+                                       {
+                                               idx = pAd->StaCfg.DefaultKeyId;
+                                               RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry);
+                                       }
+                               }
+
+                               if (pEntry && pEntry->ValidAsCLI)
+                                       pEntry->LastBeaconRxTime = Now;
+
+                               // At least another peer in this IBSS, declare MediaState as CONNECTED
+                               if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+                               {
+                                       OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+
+                                       pAd->IndicateMediaState = NdisMediaStateConnected;
+                                       RTMP_IndicateMediaState(pAd);
+                       pAd->ExtraInfo = GENERAL_LINK_UP;
+                                       AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
+
+                                       // 2003/03/12 - john
+                                       // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that
+                                       // "site survey" result should always include the current connected network.
+                                       //
+                                       Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
+                                       if (Bssidx == BSS_NOT_FOUND)
+                                       {
+                                               Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
+                                                                       &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
+                                                                       &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0,
+                                                                       &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
+                                       }
+                                       DBGPRINT(RT_DEBUG_TRACE, ("ADHOC  fOP_STATUS_MEDIA_STATE_CONNECTED.\n"));
+                               }
+                       }
+
+                       if (INFRA_ON(pAd))
+                       {
+                               BOOLEAN bUseShortSlot, bUseBGProtection;
+
+                               // decide to use/change to -
+                               //      1. long slot (20 us) or short slot (9 us) time
+                               //      2. turn on/off RTS/CTS and/or CTS-to-self protection
+                               //      3. short preamble
+
+                               //bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo);
+                               bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo);
+                               if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))
+                                       AsicSetSlotTime(pAd, bUseShortSlot);
+
+                               bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) ||    // always use
+                                                                  ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp));
+
+                               if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP
+                                       bUseBGProtection = FALSE;
+
+                               if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
+                               {
+                                       if (bUseBGProtection)
+                                       {
+                                               OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
+                                               AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
+                                       }
+                                       else
+                                       {
+                                               OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
+                                               AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
+                                       }
+
+                                       DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection));
+                               }
+
+#ifdef DOT11_N_SUPPORT
+                               // check Ht protection mode. and adhere to the Non-GF device indication by AP.
+                               if ((AddHtInfoLen != 0) &&
+                                       ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) ||
+                                       (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent)))
+                               {
+                                       pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent;
+                                       pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode;
+                                       if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)
+                               {
+                                               AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE);
+                                       }
+                                       else
+                                               AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
+
+                                       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode));
+                               }
+#endif // DOT11_N_SUPPORT //
+
+                               if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) &&
+                                       ERP_IS_USE_BARKER_PREAMBLE(Erp))
+                               {
+                                       MlmeSetTxPreamble(pAd, Rt802_11PreambleLong);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n"));
+                               }
+
+                               if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)    &&
+                                       (EdcaParm.bValid == TRUE)                          &&
+                                       (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount))
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n",
+                                               pAd->CommonCfg.APEdcaParm.EdcaUpdateCount,
+                                               EdcaParm.EdcaUpdateCount));
+                                       AsicSetEdcaParm(pAd, &EdcaParm);
+                               }
+
+                               // copy QOS related information
+                               NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
+                               NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
+                       }
+
+                       // only INFRASTRUCTURE mode support power-saving feature
+                       if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave))
+                       {
+                               UCHAR FreeNumber;
+                               //  1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL
+                               //  2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE
+                               //  3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE
+                               //  4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE
+                               //  5. otherwise, put PHY back to sleep to save battery.
+                               if (MessageToMe)
+                               {
+                                       if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable &&
+                                               pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO)
+                                       {
+                                               pAd->CommonCfg.bNeedSendTriggerFrame = TRUE;
+                                       }
+                                       else
+                                               RT28XX_PS_POLL_ENQUEUE(pAd);
+                               }
+                               else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM))
+                               {
+                               }
+                               else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0)                                                                                                        ||
+                                               (pAd->TxSwQueue[QID_AC_BE].Number != 0)                                                                                                         ||
+                                               (pAd->TxSwQueue[QID_AC_VI].Number != 0)                                                                                                         ||
+                                               (pAd->TxSwQueue[QID_AC_VO].Number != 0)                                                                                                         ||
+                                               (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)      ||
+                                               (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)      ||
+                                               (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)      ||
+                                               (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)      ||
+                                               (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS))
+                               {
+                                       // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme
+                                       // can we cheat here (i.e. just check MGMT & AC_BE) for better performance?
+                               }
+                               else
+                               {
+                                       USHORT NextDtim = DtimCount;
+
+                                       if (NextDtim == 0)
+                                               NextDtim = DtimPeriod;
+
+                                       TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
+                                       if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
+                                               TbttNumToNextWakeUp = NextDtim;
+
+                                       if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+                                       {
+                                               AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
+                                       }
+                               }
+                       }
+               }
+               // not my BSSID, ignore it
+       }
+       // sanity check fail, ignore this frame
+}
+
+/*
+       ==========================================================================
+       Description:
+               Receive PROBE REQ from remote peer when operating in IBSS mode
+       ==========================================================================
+ */
+VOID PeerProbeReqAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       UCHAR         Addr2[MAC_ADDR_LEN];
+       CHAR          Ssid[MAX_LEN_OF_SSID];
+       UCHAR         SsidLen;
+#ifdef DOT11_N_SUPPORT
+       UCHAR             HtLen, AddHtLen, NewExtLen;
+#endif // DOT11_N_SUPPORT //
+       HEADER_802_11 ProbeRspHdr;
+       NDIS_STATUS   NStatus;
+       PUCHAR        pOutBuffer = NULL;
+       ULONG         FrameLen = 0;
+       LARGE_INTEGER FakeTimestamp;
+       UCHAR         DsLen = 1, IbssLen = 2;
+       UCHAR         LocalErpIe[3] = {IE_ERP, 1, 0};
+       BOOLEAN       Privacy;
+       USHORT        CapabilityInfo;
+       UCHAR             RSNIe = IE_WPA;
+
+       if (! ADHOC_ON(pAd))
+               return;
+
+       if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen))
+       {
+               if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
+               {
+                       // allocate and send out ProbeRsp frame
+                       NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+                       if (NStatus != NDIS_STATUS_SUCCESS)
+                               return;
+
+                       //pAd->StaCfg.AtimWin = 0;  // ??????
+
+                       Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
+                                         (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
+                                         (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
+                       CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0);
+
+                       MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
+                                                         sizeof(HEADER_802_11),        &ProbeRspHdr,
+                                                         TIMESTAMP_LEN,                &FakeTimestamp,
+                                                         2,                            &pAd->CommonCfg.BeaconPeriod,
+                                                         2,                            &CapabilityInfo,
+                                                         1,                            &SsidIe,
+                                                         1,                            &pAd->CommonCfg.SsidLen,
+                                                         pAd->CommonCfg.SsidLen,       pAd->CommonCfg.Ssid,
+                                                         1,                            &SupRateIe,
+                                                         1,                            &pAd->StaActive.SupRateLen,
+                                                         pAd->StaActive.SupRateLen,    pAd->StaActive.SupRate,
+                                                         1,                            &DsIe,
+                                                         1,                            &DsLen,
+                                                         1,                            &pAd->CommonCfg.Channel,
+                                                         1,                            &IbssIe,
+                                                         1,                            &IbssLen,
+                                                         2,                            &pAd->StaActive.AtimWin,
+                                                         END_OF_ARGS);
+
+                       if (pAd->StaActive.ExtRateLen)
+                       {
+                               ULONG tmp;
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
+                                                                 3,                            LocalErpIe,
+                                                                 1,                            &ExtRateIe,
+                                                                 1,                            &pAd->StaActive.ExtRateLen,
+                                                                 pAd->StaActive.ExtRateLen,    &pAd->StaActive.ExtRate,
+                                                                 END_OF_ARGS);
+                               FrameLen += tmp;
+                       }
+
+                       // If adhoc secruity is set for WPA-None, append the cipher suite IE
+                       if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+                       {
+                               ULONG tmp;
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,                &tmp,
+                                                                       1,                              &RSNIe,
+                                                                       1,                              &pAd->StaCfg.RSNIE_Len,
+                                                                       pAd->StaCfg.RSNIE_Len,          pAd->StaCfg.RSN_IE,
+                                                                       END_OF_ARGS);
+                               FrameLen += tmp;
+                       }
+#ifdef DOT11_N_SUPPORT
+                       if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+                       {
+                               ULONG TmpLen;
+                               UCHAR   BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
+                               HtLen = sizeof(pAd->CommonCfg.HtCapability);
+                               AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo);
+                               NewExtLen = 1;
+                               //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame
+                               if (pAd->bBroadComHT == TRUE)
+                               {
+                                       MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
+                                                                 1,                                &WpaIe,
+                                                                 4,                                &BROADCOM[0],
+                                                                pAd->MlmeAux.HtCapabilityLen,          &pAd->MlmeAux.HtCapability,
+                                                                 END_OF_ARGS);
+                               }
+                               else
+                               {
+                               MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
+                                                                 1,                                &HtCapIe,
+                                                                 1,                                &HtLen,
+                                                                sizeof(HT_CAPABILITY_IE),          &pAd->CommonCfg.HtCapability,
+                                                                 1,                                &AddHtInfoIe,
+                                                                 1,                                &AddHtLen,
+                                                                sizeof(ADD_HT_INFO_IE),          &pAd->CommonCfg.AddHTInfo,
+                                                                 1,                                &NewExtChanIe,
+                                                                 1,                                &NewExtLen,
+                                                                sizeof(NEW_EXT_CHAN_IE),          &pAd->CommonCfg.NewExtChanOffset,
+                                                                 END_OF_ARGS);
+                               }
+                               FrameLen += TmpLen;
+                       }
+#endif // DOT11_N_SUPPORT //
+                       MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+                       MlmeFreeMemory(pAd, pOutBuffer);
+               }
+       }
+}
+
+VOID BeaconTimeoutAtJoinAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT Status;
+       DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n"));
+       pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+       Status = MLME_REJ_TIMEOUT;
+       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
+}
+
+/*
+       ==========================================================================
+       Description:
+               Scan timeout procedure. basically add channel index by 1 and rescan
+       ==========================================================================
+ */
+VOID ScanTimeoutAction(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel);
+
+       // Only one channel scanned for CISCO beacon request
+       if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) ||
+               (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) ||
+               (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) ||
+               (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD))
+               pAd->MlmeAux.Channel = 0;
+
+       // this routine will stop if pAd->MlmeAux.Channel == 0
+       ScanNextChannel(pAd);
+}
+
+/*
+       ==========================================================================
+       Description:
+       ==========================================================================
+ */
+VOID InvalidStateWhenScan(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT Status;
+       DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
+       pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+       Status = MLME_STATE_MACHINE_REJECT;
+       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
+}
+
+/*
+       ==========================================================================
+       Description:
+       ==========================================================================
+ */
+VOID InvalidStateWhenJoin(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT Status;
+       DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
+       pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+       Status = MLME_STATE_MACHINE_REJECT;
+       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
+}
+
+/*
+       ==========================================================================
+       Description:
+       ==========================================================================
+ */
+VOID InvalidStateWhenStart(
+       IN PRTMP_ADAPTER pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       USHORT Status;
+       DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
+       pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+       Status = MLME_STATE_MACHINE_REJECT;
+       MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
+}
+
+/*
+       ==========================================================================
+       Description:
+
+       IRQL = DISPATCH_LEVEL
+
+       ==========================================================================
+ */
+VOID EnqueuePsPoll(
+       IN PRTMP_ADAPTER pAd)
+{
+#ifdef RALINK_ATE
+    if (ATE_ON(pAd))
+    {
+               return;
+    }
+#endif // RALINK_ATE //
+
+
+       if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP)
+       pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE;
+       MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
+}
+
+
+/*
+       ==========================================================================
+       Description:
+       ==========================================================================
+ */
+VOID EnqueueProbeRequest(
+       IN PRTMP_ADAPTER pAd)
+{
+       NDIS_STATUS     NState;
+       PUCHAR          pOutBuffer;
+       ULONG           FrameLen = 0;
+       HEADER_802_11   Hdr80211;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n"));
+
+       NState = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
+       if (NState == NDIS_STATUS_SUCCESS)
+       {
+               MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
+
+               // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse
+               MakeOutgoingFrame(pOutBuffer,                     &FrameLen,
+                                                 sizeof(HEADER_802_11),          &Hdr80211,
+                                                 1,                              &SsidIe,
+                                                 1,                              &pAd->CommonCfg.SsidLen,
+                                                 pAd->CommonCfg.SsidLen,                 pAd->CommonCfg.Ssid,
+                                                 1,                              &SupRateIe,
+                                                 1,                              &pAd->StaActive.SupRateLen,
+                                                 pAd->StaActive.SupRateLen,      pAd->StaActive.SupRate,
+                                                 END_OF_ARGS);
+               MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+               MlmeFreeMemory(pAd, pOutBuffer);
+       }
+
+}
+
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+VOID BuildEffectedChannelList(
+       IN PRTMP_ADAPTER pAd)
+{
+       UCHAR           EChannel[11];
+       UCHAR           i, j, k;
+       UCHAR           UpperChannel = 0, LowerChannel = 0;
+
+       RTMPZeroMemory(EChannel, 11);
+       i = 0;
+       // Find upper channel and lower channel.
+       if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
+       {
+               UpperChannel = pAd->CommonCfg.Channel;
+               LowerChannel = pAd->CommonCfg.CentralChannel;
+       }
+       else if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
+       {
+               UpperChannel = pAd->CommonCfg.CentralChannel;
+               LowerChannel = pAd->CommonCfg.Channel;
+       }
+       else
+       {
+               return;
+       }
+
+       // Record channels that is below lower channel..
+       if (LowerChannel > 1)
+       {
+               EChannel[0] = LowerChannel - 1;
+               i = 1;
+               if (LowerChannel > 2)
+               {
+                       EChannel[1] = LowerChannel - 2;
+                       i = 2;
+                       if (LowerChannel > 3)
+                       {
+                               EChannel[2] = LowerChannel - 3;
+                               i = 3;
+                       }
+               }
+       }
+       // Record channels that is between  lower channel and upper channel.
+       for (k = LowerChannel;k < UpperChannel;k++)
+       {
+               EChannel[i] = k;
+               i++;
+       }
+       // Record channels that is above upper channel..
+       if (LowerChannel < 11)
+       {
+               EChannel[i] = UpperChannel + 1;
+               i++;
+               if (LowerChannel < 10)
+               {
+                       EChannel[i] = LowerChannel + 2;
+                       i++;
+                       if (LowerChannel < 9)
+                       {
+                               EChannel[i] = LowerChannel + 3;
+                               i++;
+                       }
+               }
+       }
+       //
+       for (j = 0;j < i;j++)
+       {
+               for (k = 0;k < pAd->ChannelListNum;k++)
+               {
+                       if (pAd->ChannelList[k].Channel == EChannel[j])
+                       {
+                               pAd->ChannelList[k].bEffectedChannel = TRUE;
+                               DBGPRINT(RT_DEBUG_TRACE,(" EffectedChannel( =%d)\n", EChannel[j]));
+                               break;
+                       }
+               }
+       }
+}
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+BOOLEAN ScanRunning(
+               IN PRTMP_ADAPTER pAd)
+{
+       return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE;
+}
+
diff --git a/drivers/staging/rt2870/sta/wpa.c b/drivers/staging/rt2870/sta/wpa.c
new file mode 100644 (file)
index 0000000..8626dcd
--- /dev/null
@@ -0,0 +1,2107 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       wpa.c
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Jan     Lee             03-07-22                Initial
+       Paul Lin        03-11-28                Modify for supplicant
+*/
+#include "../rt_config.h"
+
+#define                WPARSNIE        0xdd
+#define                WPA2RSNIE       0x30
+
+//extern UCHAR BIT8[];
+UCHAR  CipherWpaPskTkip[] = {
+               0xDD, 0x16,                             // RSN IE
+               0x00, 0x50, 0xf2, 0x01, // oui
+               0x01, 0x00,                             // Version
+               0x00, 0x50, 0xf2, 0x02, // Multicast
+               0x01, 0x00,                             // Number of unicast
+               0x00, 0x50, 0xf2, 0x02, // unicast
+               0x01, 0x00,                             // number of authentication method
+               0x00, 0x50, 0xf2, 0x02  // authentication
+               };
+UCHAR  CipherWpaPskTkipLen = (sizeof(CipherWpaPskTkip) / sizeof(UCHAR));
+
+UCHAR  CipherWpaPskAes[] = {
+               0xDD, 0x16,                     // RSN IE
+               0x00, 0x50, 0xf2, 0x01, // oui
+               0x01, 0x00,                             // Version
+               0x00, 0x50, 0xf2, 0x04, // Multicast
+               0x01, 0x00,                             // Number of unicast
+               0x00, 0x50, 0xf2, 0x04, // unicast
+               0x01, 0x00,                             // number of authentication method
+               0x00, 0x50, 0xf2, 0x02  // authentication
+               };
+UCHAR  CipherWpaPskAesLen = (sizeof(CipherWpaPskAes) / sizeof(UCHAR));
+
+UCHAR  CipherSuiteCiscoCCKM[] = {
+               0xDD, 0x16,                             // RSN IE
+               0x00, 0x50, 0xf2, 0x01, // oui
+               0x01, 0x00,                             // Version
+               0x00, 0x40, 0x96, 0x01, // Multicast
+               0x01, 0x00,                             // Number of uicast
+               0x00, 0x40, 0x96, 0x01, // unicast
+               0x01, 0x00,                             // number of authentication method
+               0x00, 0x40, 0x96, 0x00  // Authentication
+               };
+UCHAR  CipherSuiteCiscoCCKMLen = (sizeof(CipherSuiteCiscoCCKM) / sizeof(UCHAR));
+
+UCHAR  CipherSuiteCiscoCCKM24[] = {
+               0xDD, 0x18,                             // RSN IE
+               0x00, 0x50, 0xf2, 0x01, // oui
+               0x01, 0x00,                             // Version
+               0x00, 0x40, 0x96, 0x01, // Multicast
+               0x01, 0x00,                             // Number of uicast
+               0x00, 0x40, 0x96, 0x01, // unicast
+               0x01, 0x00,                             // number of authentication method
+               0x00, 0x40, 0x96, 0x00,
+               0x28, 0x00// Authentication
+               };
+
+UCHAR  CipherSuiteCiscoCCKM24Len = (sizeof(CipherSuiteCiscoCCKM24) / sizeof(UCHAR));
+
+UCHAR  CipherSuiteCCXTkip[] = {
+               0xDD, 0x16,                             // RSN IE
+               0x00, 0x50, 0xf2, 0x01, // oui
+               0x01, 0x00,                             // Version
+               0x00, 0x50, 0xf2, 0x02, // Multicast
+               0x01, 0x00,                             // Number of unicast
+               0x00, 0x50, 0xf2, 0x02, // unicast
+               0x01, 0x00,                             // number of authentication method
+               0x00, 0x50, 0xf2, 0x01  // authentication
+               };
+UCHAR  CipherSuiteCCXTkipLen = (sizeof(CipherSuiteCCXTkip) / sizeof(UCHAR));
+
+UCHAR  CCX_LLC_HDR[] = {0xAA, 0xAA, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
+UCHAR  LLC_NORMAL[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
+
+UCHAR  EAPOL_FRAME[] = {0x88, 0x8E};
+
+BOOLEAN CheckRSNIE(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pData,
+       IN  UCHAR           DataLen,
+       OUT     UCHAR                   *Offset);
+
+void inc_byte_array(UCHAR *counter, int len);
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Classify WPA EAP message type
+
+       Arguments:
+               EAPType         Value of EAP message type
+               MsgType         Internal Message definition for MLME state machine
+
+       Return Value:
+               TRUE            Found appropriate message type
+               FALSE           No appropriate message type
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+               All these constants are defined in wpa.h
+               For supplicant, there is only EAPOL Key message avaliable
+
+       ========================================================================
+*/
+BOOLEAN        WpaMsgTypeSubst(
+       IN      UCHAR   EAPType,
+       OUT     INT             *MsgType)
+{
+       switch (EAPType)
+       {
+               case EAPPacket:
+                       *MsgType = MT2_EAPPacket;
+                       break;
+               case EAPOLStart:
+                       *MsgType = MT2_EAPOLStart;
+                       break;
+               case EAPOLLogoff:
+                       *MsgType = MT2_EAPOLLogoff;
+                       break;
+               case EAPOLKey:
+                       *MsgType = MT2_EAPOLKey;
+                       break;
+               case EAPOLASFAlert:
+                       *MsgType = MT2_EAPOLASFAlert;
+                       break;
+               default:
+                       return FALSE;
+       }
+       return TRUE;
+}
+
+/*
+       ==========================================================================
+       Description:
+               association     state machine init,     including state transition and timer init
+       Parameters:
+               S -     pointer to the association state machine
+       ==========================================================================
+ */
+VOID WpaPskStateMachineInit(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      STATE_MACHINE *S,
+       OUT     STATE_MACHINE_FUNC Trans[])
+{
+       StateMachineInit(S,     Trans, MAX_WPA_PSK_STATE, MAX_WPA_PSK_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PSK_IDLE, WPA_MACHINE_BASE);
+       StateMachineSetAction(S, WPA_PSK_IDLE, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction);
+}
+
+/*
+       ==========================================================================
+       Description:
+               This is state machine function.
+               When receiving EAPOL packets which is  for 802.1x key management.
+               Use     both in WPA, and WPAPSK case.
+               In this function, further dispatch to different functions according     to the received packet.  3 categories are :
+                 1.  normal 4-way pairwisekey and 2-way groupkey handshake
+                 2.  MIC error (Countermeasures attack)  report packet from STA.
+                 3.  Request for pairwise/group key update     from STA
+       Return:
+       ==========================================================================
+*/
+VOID WpaEAPOLKeyAction(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MLME_QUEUE_ELEM *Elem)
+
+{
+       INT             MsgType = EAPOL_MSG_INVALID;
+       PKEY_DESCRIPTER pKeyDesc;
+       PHEADER_802_11  pHeader; //red
+       UCHAR           ZeroReplay[LEN_KEY_DESC_REPLAY];
+       UCHAR EapolVr;
+       KEY_INFO                peerKeyInfo;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("-----> WpaEAPOLKeyAction\n"));
+
+       // Get 802.11 header first
+       pHeader = (PHEADER_802_11) Elem->Msg;
+
+       // Get EAPoL-Key Descriptor
+       pKeyDesc = (PKEY_DESCRIPTER) &Elem->Msg[(LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H)];
+
+       NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
+       NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pKeyDesc->KeyInfo, sizeof(KEY_INFO));
+
+       *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo));
+
+
+       // 1. Check EAPOL frame version and type
+       EapolVr = (UCHAR) Elem->Msg[LENGTH_802_11+LENGTH_802_1_H];
+
+    if (((EapolVr != EAPOL_VER) && (EapolVr != EAPOL_VER2)) || ((pKeyDesc->Type != WPA1_KEY_DESC) && (pKeyDesc->Type != WPA2_KEY_DESC)))
+       {
+        DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n"));
+                       return;
+       }
+
+       // First validate replay counter, only accept message with larger replay counter
+       // Let equal pass, some AP start with all zero replay counter
+       NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
+
+       if((RTMPCompareMemory(pKeyDesc->ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
+               (RTMPCompareMemory(pKeyDesc->ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("   ReplayCounter not match   \n"));
+               return;
+       }
+
+       // Process WPA2PSK frame
+       if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+       {
+               if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
+                       (peerKeyInfo.EKD_DL == 0) &&
+                       (peerKeyInfo.KeyAck == 1) &&
+                       (peerKeyInfo.KeyMic == 0) &&
+                       (peerKeyInfo.Secure == 0) &&
+                       (peerKeyInfo.Error == 0) &&
+                       (peerKeyInfo.Request == 0))
+               {
+                       MsgType = EAPOL_PAIR_MSG_1;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n"));
+               } else if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
+                       (peerKeyInfo.EKD_DL  == 1) &&
+                       (peerKeyInfo.KeyAck == 1) &&
+                       (peerKeyInfo.KeyMic == 1) &&
+                       (peerKeyInfo.Secure == 1) &&
+                       (peerKeyInfo.Error == 0) &&
+                       (peerKeyInfo.Request == 0))
+               {
+                       MsgType = EAPOL_PAIR_MSG_3;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n"));
+               } else if((peerKeyInfo.KeyType == GROUPKEY) &&
+                       (peerKeyInfo.EKD_DL == 1) &&
+                       (peerKeyInfo.KeyAck == 1) &&
+                       (peerKeyInfo.KeyMic == 1) &&
+                       (peerKeyInfo.Secure == 1) &&
+                       (peerKeyInfo.Error == 0) &&
+                       (peerKeyInfo.Request == 0))
+               {
+                       MsgType = EAPOL_GROUP_MSG_1;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n"));
+               }
+
+               // We will assume link is up (assoc suceess and port not secured).
+               // All state has to be able to process message from previous state
+               switch(pAd->StaCfg.WpaState)
+               {
+               case SS_START:
+                       if(MsgType == EAPOL_PAIR_MSG_1)
+                       {
+                               Wpa2PairMsg1Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
+                       }
+                       break;
+
+               case SS_WAIT_MSG_3:
+                       if(MsgType == EAPOL_PAIR_MSG_1)
+                       {
+                               Wpa2PairMsg1Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
+                       }
+                       else if(MsgType == EAPOL_PAIR_MSG_3)
+                       {
+                               Wpa2PairMsg3Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_WAIT_GROUP;
+                       }
+                       break;
+
+               case SS_WAIT_GROUP:             // When doing group key exchange
+               case SS_FINISH:                 // This happened when update group key
+                       if(MsgType == EAPOL_PAIR_MSG_1)
+                       {
+                           // Reset port secured variable
+                               pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                               Wpa2PairMsg1Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
+                       }
+                       else if(MsgType == EAPOL_PAIR_MSG_3)
+                       {
+                           // Reset port secured variable
+                               pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                               Wpa2PairMsg3Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_WAIT_GROUP;
+                       }
+                       else if(MsgType == EAPOL_GROUP_MSG_1)
+                       {
+                               WpaGroupMsg1Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_FINISH;
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       }
+       // Process WPAPSK Frame
+       // Classify message Type, either pairwise message 1, 3, or group message 1 for supplicant
+       else if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
+       {
+               if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
+                       (peerKeyInfo.KeyIndex == 0) &&
+                       (peerKeyInfo.KeyAck == 1) &&
+                       (peerKeyInfo.KeyMic == 0) &&
+                       (peerKeyInfo.Secure == 0) &&
+                       (peerKeyInfo.Error == 0) &&
+                       (peerKeyInfo.Request == 0))
+               {
+                       MsgType = EAPOL_PAIR_MSG_1;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n"));
+               }
+               else if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
+                       (peerKeyInfo.KeyIndex == 0) &&
+                       (peerKeyInfo.KeyAck == 1) &&
+                       (peerKeyInfo.KeyMic == 1) &&
+                       (peerKeyInfo.Secure == 0) &&
+                       (peerKeyInfo.Error == 0) &&
+                       (peerKeyInfo.Request == 0))
+               {
+                       MsgType = EAPOL_PAIR_MSG_3;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n"));
+               }
+               else if((peerKeyInfo.KeyType == GROUPKEY) &&
+                       (peerKeyInfo.KeyIndex != 0) &&
+                       (peerKeyInfo.KeyAck == 1) &&
+                       (peerKeyInfo.KeyMic == 1) &&
+                       (peerKeyInfo.Secure == 1) &&
+                       (peerKeyInfo.Error == 0) &&
+                       (peerKeyInfo.Request == 0))
+               {
+                       MsgType = EAPOL_GROUP_MSG_1;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n"));
+               }
+
+               // We will assume link is up (assoc suceess and port not secured).
+               // All state has to be able to process message from previous state
+               switch(pAd->StaCfg.WpaState)
+               {
+               case SS_START:
+                       if(MsgType == EAPOL_PAIR_MSG_1)
+                       {
+                               WpaPairMsg1Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
+                       }
+                       break;
+
+               case SS_WAIT_MSG_3:
+                       if(MsgType == EAPOL_PAIR_MSG_1)
+                       {
+                               WpaPairMsg1Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
+                       }
+                       else if(MsgType == EAPOL_PAIR_MSG_3)
+                       {
+                               WpaPairMsg3Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_WAIT_GROUP;
+                       }
+                       break;
+
+               case SS_WAIT_GROUP:             // When doing group key exchange
+               case SS_FINISH:                 // This happened when update group key
+                       if(MsgType == EAPOL_PAIR_MSG_1)
+                       {
+                               WpaPairMsg1Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
+                               // Reset port secured variable
+                               pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                       }
+                       else if(MsgType == EAPOL_PAIR_MSG_3)
+                       {
+                               WpaPairMsg3Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_WAIT_GROUP;
+                               // Reset port secured variable
+                               pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                       }
+                       else if(MsgType == EAPOL_GROUP_MSG_1)
+                       {
+                               WpaGroupMsg1Action(pAd, Elem);
+                               pAd->StaCfg.WpaState = SS_FINISH;
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<----- WpaEAPOLKeyAction\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Process Pairwise key 4-way handshaking
+
+       Arguments:
+               pAd     Pointer to our adapter
+               Elem            Message body
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   WpaPairMsg1Action(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem)
+{
+       PHEADER_802_11      pHeader;
+       UCHAR                           *mpool, *PTK, *digest;
+       PUCHAR              pOutBuffer = NULL;
+       UCHAR               Header802_3[14];
+       ULONG               FrameLen = 0;
+       PEAPOL_PACKET       pMsg1;
+       EAPOL_PACKET        Packet;
+       UCHAR               Mic[16];
+
+       DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action ----->\n"));
+
+       // allocate memory pool
+       os_alloc_mem(pAd, (PUCHAR *)&mpool, 256);
+
+       if (mpool == NULL)
+               return;
+
+       // PTK Len = 80.
+       PTK = (UCHAR *) ROUND_UP(mpool, 4);
+       // digest Len = 80.
+       digest = (UCHAR *) ROUND_UP(PTK + 80, 4);
+
+       pHeader = (PHEADER_802_11) Elem->Msg;
+
+       // Process message 1 from authenticator
+       pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+
+       // 1. Save Replay counter, it will use to verify message 3 and construct message 2
+       NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // 2. Save ANonce
+       NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
+
+       // Generate random SNonce
+       GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce);
+
+       // Calc PTK(ANonce, SNonce)
+       WpaCountPTK(pAd,
+               pAd->StaCfg.PMK,
+               pAd->StaCfg.ANonce,
+               pAd->CommonCfg.Bssid,
+               pAd->StaCfg.SNonce,
+               pAd->CurrentAddress,
+               PTK,
+               LEN_PTK);
+
+       // Save key to PTK entry
+       NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK);
+
+       // init 802.3 header and Fill Packet
+       MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
+
+       // Zero Message 2 body
+       NdisZeroMemory(&Packet, sizeof(Packet));
+       Packet.ProVer   = EAPOL_VER;
+       Packet.ProType  = EAPOLKey;
+       //
+       // Message 2 as  EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE)
+       //
+       Packet.KeyDesc.Type = WPA1_KEY_DESC;
+       // 1. Key descriptor version and appropriate RSN IE
+       if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
+       {
+               Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
+       }
+       else      // TKIP
+       {
+               Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
+       }
+
+       // fill in Data Material and its length
+       Packet.KeyDesc.KeyData[0] = IE_WPA;
+       Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len;
+       Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2;
+       NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len);
+
+       // Update packet length after decide Key data payload
+       Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1];
+
+       // Update Key length
+       Packet.KeyDesc.KeyLength[0] = pMsg1->KeyDesc.KeyLength[0];
+       Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1];
+       // 2. Key Type PeerKey
+       Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
+
+       // 3. KeyMic field presented
+       Packet.KeyDesc.KeyInfo.KeyMic  = 1;
+
+       //Convert to little-endian format.
+       *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
+
+
+       // 4. Fill SNonce
+       NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE);
+
+       // 5. Key Replay Count
+       NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // Send EAPOL(0, 1, 0, 0, 0, P, 0, SNonce, MIC, RSN_IE)
+       // Out buffer for transmitting message 2
+       MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  // allocate memory
+       if(pOutBuffer == NULL)
+       {
+               os_free_mem(pAd, mpool);
+               return;
+       }
+       // Prepare EAPOL frame for MIC calculation
+       // Be careful, only EAPOL frame is counted for MIC calculation
+       MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+               Packet.Body_Len[1] + 4,    &Packet,
+               END_OF_ARGS);
+
+       // 6. Prepare and Fill MIC value
+       NdisZeroMemory(Mic, sizeof(Mic));
+       if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
+       {       // AES
+
+               HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
+       }
+       else
+       {       // TKIP
+               hmac_md5(PTK,  LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
+       }
+       NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
+
+       //hex_dump("MIC", Mic, LEN_KEY_DESC_MIC);
+
+               MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
+                                               LENGTH_802_3,                           &Header802_3,
+                                               Packet.Body_Len[1] + 4,    &Packet,
+                                               END_OF_ARGS);
+
+
+       // 5. Copy frame to Tx ring and send Msg 2 to authenticator
+       RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
+
+       MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
+       os_free_mem(pAd, (PUCHAR)mpool);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action <-----\n"));
+}
+
+VOID Wpa2PairMsg1Action(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem)
+{
+       PHEADER_802_11      pHeader;
+       UCHAR                           *mpool, *PTK, *digest;
+       PUCHAR              pOutBuffer = NULL;
+       UCHAR               Header802_3[14];
+       ULONG               FrameLen = 0;
+       PEAPOL_PACKET       pMsg1;
+       EAPOL_PACKET        Packet;
+       UCHAR               Mic[16];
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action ----->\n"));
+
+       // allocate memory pool
+       os_alloc_mem(pAd, (PUCHAR *)&mpool, 256);
+
+       if (mpool == NULL)
+               return;
+
+       // PTK Len = 80.
+       PTK = (UCHAR *) ROUND_UP(mpool, 4);
+       // digest Len = 80.
+       digest = (UCHAR *) ROUND_UP(PTK + 80, 4);
+
+       pHeader = (PHEADER_802_11) Elem->Msg;
+
+       // Process message 1 from authenticator
+               pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+
+       // 1. Save Replay counter, it will use to verify message 3 and construct message 2
+       NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // 2. Save ANonce
+       NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
+
+       // Generate random SNonce
+       GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce);
+
+       if(pMsg1->KeyDesc.KeyDataLen[1] > 0 )
+       {
+               // cached PMKID
+       }
+
+       // Calc PTK(ANonce, SNonce)
+       WpaCountPTK(pAd,
+               pAd->StaCfg.PMK,
+               pAd->StaCfg.ANonce,
+               pAd->CommonCfg.Bssid,
+               pAd->StaCfg.SNonce,
+               pAd->CurrentAddress,
+               PTK,
+               LEN_PTK);
+
+       // Save key to PTK entry
+       NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK);
+
+       // init 802.3 header and Fill Packet
+       MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
+
+       // Zero message 2 body
+       NdisZeroMemory(&Packet, sizeof(Packet));
+       Packet.ProVer   = EAPOL_VER;
+       Packet.ProType  = EAPOLKey;
+       //
+       // Message 2 as  EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE)
+       //
+       Packet.KeyDesc.Type = WPA2_KEY_DESC;
+
+       // 1. Key descriptor version and appropriate RSN IE
+       if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+       {
+               Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
+       }
+       else      // TKIP
+       {
+               Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
+       }
+
+       // fill in Data Material and its length
+       Packet.KeyDesc.KeyData[0] = IE_WPA2;
+       Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len;
+       Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2;
+       NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len);
+
+       // Update packet length after decide Key data payload
+       Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1];
+
+       // 2. Key Type PeerKey
+       Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
+
+       // 3. KeyMic field presented
+       Packet.KeyDesc.KeyInfo.KeyMic  = 1;
+
+       // Update Key Length
+       Packet.KeyDesc.KeyLength[0] = 0;
+       Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1];
+
+       // 4. Fill SNonce
+       NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE);
+
+       // 5. Key Replay Count
+       NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // Convert to little-endian format.
+       *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
+
+       // Send EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE)
+       // Out buffer for transmitting message 2
+       MlmeAllocateMemory(pAd,  (PUCHAR *)&pOutBuffer);  // allocate memory
+       if(pOutBuffer == NULL)
+       {
+               os_free_mem(pAd, mpool);
+               return;
+       }
+
+       // Prepare EAPOL frame for MIC calculation
+       // Be careful, only EAPOL frame is counted for MIC calculation
+       MakeOutgoingFrame(pOutBuffer,        &FrameLen,
+               Packet.Body_Len[1] + 4, &Packet,
+               END_OF_ARGS);
+
+       // 6. Prepare and Fill MIC value
+       NdisZeroMemory(Mic, sizeof(Mic));
+       if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+       {
+               // AES
+               HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
+       }
+       else
+       {
+               hmac_md5(PTK,  LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
+       }
+       NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
+
+
+       // Make  Transmitting frame
+       MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
+                                               LENGTH_802_3,                   &Header802_3,
+                                               Packet.Body_Len[1] + 4, &Packet,
+                                               END_OF_ARGS);
+
+
+       // 5. Copy frame to Tx ring
+       RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
+
+       MlmeFreeMemory(pAd, pOutBuffer);
+       os_free_mem(pAd, mpool);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action <-----\n"));
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Process Pairwise key 4-way handshaking
+
+       Arguments:
+               pAd     Pointer to our adapter
+               Elem            Message body
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   WpaPairMsg3Action(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MLME_QUEUE_ELEM *Elem)
+
+{
+       PHEADER_802_11      pHeader;
+       PUCHAR                  pOutBuffer = NULL;
+       UCHAR               Header802_3[14];
+       ULONG                   FrameLen = 0;
+       EAPOL_PACKET        Packet;
+       PEAPOL_PACKET       pMsg3;
+       UCHAR                   Mic[16], OldMic[16];
+       MAC_TABLE_ENTRY         *pEntry = NULL;
+       UCHAR                           skip_offset;
+       KEY_INFO                        peerKeyInfo;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action ----->\n"));
+
+       // Record 802.11 header & the received EAPOL packet Msg3
+       pHeader = (PHEADER_802_11) Elem->Msg;
+       pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+
+       NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
+       NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO));
+
+       *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo));
+
+
+       // 1. Verify cipher type match
+       if (pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2))
+       {
+               return;
+       }
+       else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1))
+       {
+               return;
+       }
+
+       // Verify RSN IE
+       //if (!RTMPEqualMemory(pMsg3->KeyDesc.KeyData, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len))
+       if (!CheckRSNIE(pAd, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1], &skip_offset))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in Msg 3 of WPA1 4-way handshake!! \n"));
+               hex_dump("The original RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len);
+               hex_dump("The received RSN_IE", pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]);
+               return;
+       }
+       else
+               DBGPRINT(RT_DEBUG_TRACE, ("RSN_IE VALID in Msg 3 of WPA1 4-way handshake!! \n"));
+
+
+       // 2. Check MIC value
+       // Save the MIC and replace with zero
+       NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+       NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+       if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
+       {
+               // AES
+               UCHAR digest[80];
+
+               HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
+       }
+       else    // TKIP
+       {
+               hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic);
+       }
+
+       if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n"));
+               return;
+       }
+       else
+               DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n"));
+
+       // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger
+       if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
+               return;
+
+       // Update new replay counter
+       NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // 4. Double check ANonce
+       if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
+               return;
+
+       // init 802.3 header and Fill Packet
+       MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
+
+       // Zero Message 4 body
+       NdisZeroMemory(&Packet, sizeof(Packet));
+       Packet.ProVer   = EAPOL_VER;
+       Packet.ProType  = EAPOLKey;
+       Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE;                // No data field
+
+       //
+       // Message 4 as  EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0)
+       //
+       Packet.KeyDesc.Type = WPA1_KEY_DESC;
+
+       // Key descriptor version and appropriate RSN IE
+       Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer;
+
+       // Update Key Length
+       Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0];
+       Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1];
+
+       // Key Type PeerKey
+       Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
+
+       // KeyMic field presented
+       Packet.KeyDesc.KeyInfo.KeyMic  = 1;
+
+       // In Msg3,  KeyInfo.secure =0 if Group Key HS to come. 1 if no group key HS
+       // Station sends Msg4  KeyInfo.secure should be the same as that in Msg.3
+       Packet.KeyDesc.KeyInfo.Secure= peerKeyInfo.Secure;
+
+       // Convert to little-endian format.
+       *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
+
+       // Key Replay count
+       NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // Out buffer for transmitting message 4
+       MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  // allocate memory
+       if(pOutBuffer == NULL)
+               return;
+
+       // Prepare EAPOL frame for MIC calculation
+       // Be careful, only EAPOL frame is counted for MIC calculation
+       MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+               Packet.Body_Len[1] + 4,    &Packet,
+               END_OF_ARGS);
+
+       // Prepare and Fill MIC value
+       NdisZeroMemory(Mic, sizeof(Mic));
+       if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
+       {
+               // AES
+               UCHAR digest[80];
+
+               HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
+       }
+       else
+       {
+               hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
+       }
+       NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
+
+       // Update PTK
+       // Prepare pair-wise key information into shared key table
+       NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
+       pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
+    NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
+       NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
+       NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
+
+       // Decide its ChiperAlg
+       if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
+       else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
+               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
+       else
+               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE;
+
+       // Update these related information to MAC_TABLE_ENTRY
+       pEntry = &pAd->MacTab.Content[BSSID_WCID];
+       NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
+       NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
+       NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
+       pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
+
+       // Update pairwise key information to ASIC Shared Key Table
+       AsicAddSharedKeyEntry(pAd,
+                                                 BSS0,
+                                                 0,
+                                                 pAd->SharedKey[BSS0][0].CipherAlg,
+                                                 pAd->SharedKey[BSS0][0].Key,
+                                                 pAd->SharedKey[BSS0][0].TxMic,
+                                                 pAd->SharedKey[BSS0][0].RxMic);
+
+       // Update ASIC WCID attribute table and IVEIV table
+       RTMPAddWcidAttributeEntry(pAd,
+                                                         BSS0,
+                                                         0,
+                                                         pAd->SharedKey[BSS0][0].CipherAlg,
+                                                         pEntry);
+
+       // Make transmitting frame
+       MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
+                                               LENGTH_802_3,                   &Header802_3,
+                                               Packet.Body_Len[1] + 4, &Packet,
+                                               END_OF_ARGS);
+
+
+       // Copy frame to Tx ring and Send Message 4 to authenticator
+       RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
+
+       MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action <-----\n"));
+}
+
+VOID    Wpa2PairMsg3Action(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  MLME_QUEUE_ELEM *Elem)
+
+{
+       PHEADER_802_11      pHeader;
+       PUCHAR              pOutBuffer = NULL;
+       UCHAR               Header802_3[14];
+       ULONG               FrameLen = 0;
+       EAPOL_PACKET        Packet;
+       PEAPOL_PACKET       pMsg3;
+       UCHAR               Mic[16], OldMic[16];
+       UCHAR               *mpool, *KEYDATA, *digest;
+       UCHAR               Key[32];
+       MAC_TABLE_ENTRY         *pEntry = NULL;
+       KEY_INFO                        peerKeyInfo;
+
+       // allocate memory
+       os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024);
+
+       if(mpool == NULL)
+               return;
+
+       // KEYDATA Len = 512.
+       KEYDATA = (UCHAR *) ROUND_UP(mpool, 4);
+       // digest Len = 80.
+       digest = (UCHAR *) ROUND_UP(KEYDATA + 512, 4);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg3Action ----->\n"));
+
+       pHeader = (PHEADER_802_11) Elem->Msg;
+
+       // Process message 3 frame.
+       pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+
+       NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
+       NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO));
+
+       *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo));
+
+       // 1. Verify cipher type match
+       if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer!= 2))
+       {
+               os_free_mem(pAd, (PUCHAR)mpool);
+               return;
+       }
+       else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1))
+       {
+               os_free_mem(pAd, (PUCHAR)mpool);
+               return;
+       }
+
+       // 2. Check MIC value
+       // Save the MIC and replace with zero
+       NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+       NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+       if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+       {
+               // AES
+               HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
+       }
+       else
+       {
+               hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic);
+       }
+
+       if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n"));
+               os_free_mem(pAd, (PUCHAR)mpool);
+               return;
+       }
+       else
+               DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n"));
+
+       // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger
+       if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
+       {
+               os_free_mem(pAd, (PUCHAR)mpool);
+               return;
+       }
+
+       // Update new replay counter
+       NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // 4. Double check ANonce
+       if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
+       {
+               os_free_mem(pAd, (PUCHAR)mpool);
+               return;
+       }
+
+       // Obtain GTK
+       // 5. Decrypt GTK from Key Data
+       DBGPRINT_RAW(RT_DEBUG_TRACE, ("EKD = %d\n", peerKeyInfo.EKD_DL));
+       if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+       {
+               // Decrypt AES GTK
+               AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA, pMsg3->KeyDesc.KeyDataLen[1],pMsg3->KeyDesc.KeyData);
+       }
+       else      // TKIP
+       {
+               INT i;
+               // Decrypt TKIP GTK
+               // Construct 32 bytes RC4 Key
+               NdisMoveMemory(Key, pMsg3->KeyDesc.KeyIv, 16);
+               NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16);
+               ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32);
+               //discard first 256 bytes
+               for(i = 0; i < 256; i++)
+                       ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT);
+               // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not
+               ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]);
+       }
+
+       if (!ParseKeyData(pAd, KEYDATA, pMsg3->KeyDesc.KeyDataLen[1], 1))
+       {
+               os_free_mem(pAd, (PUCHAR)mpool);
+               return;
+       }
+
+       // Update GTK to ASIC
+       // Update group key information to ASIC Shared Key Table
+       AsicAddSharedKeyEntry(pAd,
+                                                 BSS0,
+                                                 pAd->StaCfg.DefaultKeyId,
+                                                 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+                                                 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
+                                                 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic,
+                                                 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic);
+
+       // Update ASIC WCID attribute table and IVEIV table
+       RTMPAddWcidAttributeEntry(pAd,
+                                                         BSS0,
+                                                         pAd->StaCfg.DefaultKeyId,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+                                                         NULL);
+
+       // init 802.3 header and Fill Packet
+       MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
+
+       // Zero message 4 body
+       NdisZeroMemory(&Packet, sizeof(Packet));
+       Packet.ProVer   = EAPOL_VER;
+       Packet.ProType  = EAPOLKey;
+       Packet.Body_Len[1]      = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE;            // No data field
+
+       //
+       // Message 4 as  EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0)
+       //
+       Packet.KeyDesc.Type = WPA2_KEY_DESC;
+
+       // Key descriptor version and appropriate RSN IE
+       Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer;
+
+       // Update Key Length
+       Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0];
+       Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1];
+
+       // Key Type PeerKey
+       Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
+
+       // KeyMic field presented
+       Packet.KeyDesc.KeyInfo.KeyMic  = 1;
+       Packet.KeyDesc.KeyInfo.Secure = 1;
+
+       // Convert to little-endian format.
+       *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
+
+       // Key Replay count
+       NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // Out buffer for transmitting message 4
+       MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  // allocate memory
+       if(pOutBuffer == NULL)
+       {
+               os_free_mem(pAd, (PUCHAR)mpool);
+               return;
+       }
+
+       // Prepare EAPOL frame for MIC calculation
+       // Be careful, only EAPOL frame is counted for MIC calculation
+       MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+               Packet.Body_Len[1] + 4,    &Packet,
+               END_OF_ARGS);
+
+       // Prepare and Fill MIC value
+       NdisZeroMemory(Mic, sizeof(Mic));
+       if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+       {
+               // AES
+               HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
+       }
+       else
+       {
+               hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
+       }
+       NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
+
+       // Update PTK
+       // Prepare pair-wise key information into shared key table
+       NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
+       pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
+    NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
+       NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
+       NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
+
+       // Decide its ChiperAlg
+       if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
+       else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
+               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
+       else
+               pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE;
+
+       // Update these related information to MAC_TABLE_ENTRY
+       pEntry = &pAd->MacTab.Content[BSSID_WCID];
+       NdisMoveMemory(&pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
+       NdisMoveMemory(&pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
+       NdisMoveMemory(&pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
+       pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
+
+       // Update pairwise key information to ASIC Shared Key Table
+       AsicAddSharedKeyEntry(pAd,
+                                                 BSS0,
+                                                 0,
+                                                 pAd->SharedKey[BSS0][0].CipherAlg,
+                                                 pAd->SharedKey[BSS0][0].Key,
+                                                 pAd->SharedKey[BSS0][0].TxMic,
+                                                 pAd->SharedKey[BSS0][0].RxMic);
+
+       // Update ASIC WCID attribute table and IVEIV table
+       RTMPAddWcidAttributeEntry(pAd,
+                                                         BSS0,
+                                                         0,
+                                                         pAd->SharedKey[BSS0][0].CipherAlg,
+                                                         pEntry);
+
+       // Make  Transmitting frame
+       MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
+                                               LENGTH_802_3,                   &Header802_3,
+                                               Packet.Body_Len[1] + 4, &Packet,
+                                               END_OF_ARGS);
+
+
+       // Copy frame to Tx ring and Send Message 4 to authenticator
+       RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
+
+       // set 802.1x port control
+       //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+       STA_PORT_SECURED(pAd);
+
+    // Indicate Connected for GUI
+    pAd->IndicateMediaState = NdisMediaStateConnected;
+
+       MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
+       os_free_mem(pAd, (PUCHAR)mpool);
+
+
+       // send wireless event - for set key done WPA2
+       if (pAd->CommonCfg.bWirelessEvent)
+               RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, BSS0, 0);
+
+       DBGPRINT(RT_DEBUG_ERROR, ("Wpa2PairMsg3Action <-----\n"));
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Process Group key 2-way handshaking
+
+       Arguments:
+               pAd     Pointer to our adapter
+               Elem            Message body
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   WpaGroupMsg1Action(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      MLME_QUEUE_ELEM *Elem)
+
+{
+       PUCHAR              pOutBuffer = NULL;
+       UCHAR               Header802_3[14];
+       ULONG               FrameLen = 0;
+       EAPOL_PACKET        Packet;
+       PEAPOL_PACKET       pGroup;
+       UCHAR               *mpool, *digest, *KEYDATA;
+       UCHAR               Mic[16], OldMic[16];
+       UCHAR               GTK[32], Key[32];
+       KEY_INFO                        peerKeyInfo;
+
+       // allocate memory
+       os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024);
+
+       if(mpool == NULL)
+               return;
+
+       // digest Len = 80.
+       digest = (UCHAR *) ROUND_UP(mpool, 4);
+       // KEYDATA Len = 512.
+       KEYDATA = (UCHAR *) ROUND_UP(digest + 80, 4);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action ----->\n"));
+
+       // Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8)
+       pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+
+       NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
+       NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pGroup->KeyDesc.KeyInfo, sizeof(KEY_INFO));
+
+       *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo));
+
+       // 0. Check cipher type match
+       if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2))
+       {
+               os_free_mem(pAd, (PUCHAR)mpool);
+               return;
+       }
+       else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1))
+       {
+               os_free_mem(pAd, (PUCHAR)mpool);
+               return;
+       }
+
+       // 1. Verify Replay counter
+       //    Check Replay Counter, it has to be larger than last one. No need to be exact one larger
+       if(RTMPCompareMemory(pGroup->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
+       {
+               os_free_mem(pAd, (PUCHAR)mpool);
+               return;
+       }
+
+       // Update new replay counter
+       NdisMoveMemory(pAd->StaCfg.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // 2. Verify MIC is valid
+       // Save the MIC and replace with zero
+       NdisMoveMemory(OldMic, pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+       NdisZeroMemory(pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+
+       if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
+       {       // AES
+               HMAC_SHA1((PUCHAR) pGroup, pGroup->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
+       }
+       else
+       {       // TKIP
+               hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pGroup, pGroup->Body_Len[1] + 4, Mic);
+       }
+
+       if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
+       {
+               DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in group msg 1 of 2-way handshake!!!!!!!!!! \n"));
+               MlmeFreeMemory(pAd, (PUCHAR)mpool);
+               return;
+       }
+       else
+               DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in group msg 1 of 2-way handshake!!!!!!!!!! \n"));
+
+
+       // 3. Decrypt GTK from Key Data
+       if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+       {
+               // Decrypt AES GTK
+               AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA,  pGroup->KeyDesc.KeyDataLen[1], pGroup->KeyDesc.KeyData);
+       }
+       else    // TKIP
+       {
+               INT i;
+
+               // Decrypt TKIP GTK
+               // Construct 32 bytes RC4 Key
+               NdisMoveMemory(Key, pGroup->KeyDesc.KeyIv, 16);
+               NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16);
+               ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32);
+               //discard first 256 bytes
+               for(i = 0; i < 256; i++)
+                       ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT);
+               // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not
+               ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pGroup->KeyDesc.KeyData, pGroup->KeyDesc.KeyDataLen[1]);
+       }
+
+       // Process decrypted key data material
+       // Parse keyData to handle KDE format for WPA2PSK
+       if (peerKeyInfo.EKD_DL)
+       {
+               if (!ParseKeyData(pAd, KEYDATA, pGroup->KeyDesc.KeyDataLen[1], 0))
+               {
+                       os_free_mem(pAd, (PUCHAR)mpool);
+                       return;
+               }
+       }
+       else    // WPAPSK
+       {
+               // set key material, TxMic and RxMic for WPAPSK
+               NdisMoveMemory(GTK, KEYDATA, 32);
+               NdisMoveMemory(pAd->StaCfg.GTK, GTK, 32);
+               pAd->StaCfg.DefaultKeyId = peerKeyInfo.KeyIndex;
+
+               // Prepare pair-wise key information into shared key table
+               NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY));
+               pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK;
+               NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, GTK, LEN_TKIP_EK);
+               NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, &GTK[16], LEN_TKIP_RXMICK);
+               NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, &GTK[24], LEN_TKIP_TXMICK);
+
+               // Update Shared Key CipherAlg
+               pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE;
+               if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP;
+               else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES;
+               else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP64;
+               else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP128;
+
+       //hex_dump("Group Key :", pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, LEN_TKIP_EK);
+       }
+
+       // Update group key information to ASIC Shared Key Table
+       AsicAddSharedKeyEntry(pAd,
+                                                 BSS0,
+                                                 pAd->StaCfg.DefaultKeyId,
+                                                 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+                                                 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
+                                                 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic,
+                                                 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic);
+
+       // Update ASIC WCID attribute table and IVEIV table
+       RTMPAddWcidAttributeEntry(pAd,
+                                                         BSS0,
+                                                         pAd->StaCfg.DefaultKeyId,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+                                                         NULL);
+
+       // set 802.1x port control
+       //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+       STA_PORT_SECURED(pAd);
+
+    // Indicate Connected for GUI
+    pAd->IndicateMediaState = NdisMediaStateConnected;
+
+       // init header and Fill Packet
+       MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
+
+       // Zero Group message 1 body
+       NdisZeroMemory(&Packet, sizeof(Packet));
+       Packet.ProVer   = EAPOL_VER;
+       Packet.ProType  = EAPOLKey;
+       Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE;                // No data field
+
+       //
+       // Group Message 2 as  EAPOL-Key(1,0,0,0,G,0,0,MIC,0)
+       //
+       if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+       {
+               Packet.KeyDesc.Type = WPA2_KEY_DESC;
+       }
+       else
+       {
+               Packet.KeyDesc.Type = WPA1_KEY_DESC;
+       }
+
+       // Key descriptor version and appropriate RSN IE
+       Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer;
+
+       // Update Key Length
+       Packet.KeyDesc.KeyLength[0] = pGroup->KeyDesc.KeyLength[0];
+       Packet.KeyDesc.KeyLength[1] = pGroup->KeyDesc.KeyLength[1];
+
+       // Key Index as G-Msg 1
+       if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
+               Packet.KeyDesc.KeyInfo.KeyIndex = peerKeyInfo.KeyIndex;
+
+       // Key Type Group key
+       Packet.KeyDesc.KeyInfo.KeyType = GROUPKEY;
+
+       // KeyMic field presented
+       Packet.KeyDesc.KeyInfo.KeyMic  = 1;
+
+       // Secure bit
+       Packet.KeyDesc.KeyInfo.Secure  = 1;
+
+       // Convert to little-endian format.
+       *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
+
+       // Key Replay count
+       NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+       // Out buffer for transmitting group message 2
+       MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  // allocate memory
+       if(pOutBuffer == NULL)
+       {
+               MlmeFreeMemory(pAd, (PUCHAR)mpool);
+               return;
+       }
+
+       // Prepare EAPOL frame for MIC calculation
+       // Be careful, only EAPOL frame is counted for MIC calculation
+       MakeOutgoingFrame(pOutBuffer,           &FrameLen,
+               Packet.Body_Len[1] + 4,    &Packet,
+               END_OF_ARGS);
+
+       // Prepare and Fill MIC value
+       NdisZeroMemory(Mic, sizeof(Mic));
+       if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
+       {
+               // AES
+               HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
+       }
+       else
+       {
+               hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
+       }
+       NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
+
+
+       MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
+                                               LENGTH_802_3,                   &Header802_3,
+                                               Packet.Body_Len[1] + 4, &Packet,
+                                               END_OF_ARGS);
+
+
+       // 5. Copy frame to Tx ring and prepare for encryption
+       RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE);
+
+       // 6 Free allocated memory
+       MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
+       os_free_mem(pAd, (PUCHAR)mpool);
+
+       // send wireless event - for set key done WPA2
+       if (pAd->CommonCfg.bWirelessEvent)
+               RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action <-----\n"));
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Init WPA MAC header
+
+       Arguments:
+               pAd     Pointer to our adapter
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID   WpaMacHeaderInit(
+       IN              PRTMP_ADAPTER   pAd,
+       IN OUT  PHEADER_802_11  pHdr80211,
+       IN              UCHAR                   wep,
+       IN              PUCHAR              pAddr1)
+{
+       NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
+       pHdr80211->FC.Type      = BTYPE_DATA;
+       pHdr80211->FC.ToDs      = 1;
+       if (wep == 1)
+               pHdr80211->FC.Wep = 1;
+
+        //     Addr1: BSSID, Addr2: SA, Addr3: DA
+       COPY_MAC_ADDR(pHdr80211->Addr1, pAddr1);
+       COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
+       COPY_MAC_ADDR(pHdr80211->Addr3, pAd->CommonCfg.Bssid);
+       pHdr80211->Sequence =   pAd->Sequence;
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Copy frame from waiting queue into relative ring buffer and set
+       appropriate ASIC register to kick hardware encryption before really
+       sent out to air.
+
+       Arguments:
+               pAd             Pointer to our adapter
+               PNDIS_PACKET    Pointer to outgoing Ndis frame
+               NumberOfFrag    Number of fragment required
+
+       Return Value:
+               None
+
+       Note:
+
+       ========================================================================
+*/
+VOID    RTMPToWirelessSta(
+       IN      PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pHeader802_3,
+    IN  UINT            HdrLen,
+       IN  PUCHAR          pData,
+    IN  UINT            DataLen,
+    IN BOOLEAN                 is4wayFrame)
+
+{
+       NDIS_STATUS     Status;
+       PNDIS_PACKET    pPacket;
+       UCHAR   Index;
+
+       do
+       {
+               // 1. build a NDIS packet and call RTMPSendPacket();
+               //    be careful about how/when to release this internal allocated NDIS PACKET buffer
+               Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen);
+               if (Status != NDIS_STATUS_SUCCESS)
+                       break;
+
+               if (is4wayFrame)
+                       RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
+               else
+                       RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
+
+               // 2. send out the packet
+               Status = STASendPacket(pAd, pPacket);
+               if(Status == NDIS_STATUS_SUCCESS)
+               {
+                       // Dequeue one frame from TxSwQueue0..3 queue and process it
+                       // There are three place calling dequeue for TX ring.
+                       // 1. Here, right after queueing the frame.
+                       // 2. At the end of TxRingTxDone service routine.
+                       // 3. Upon NDIS call RTMPSendPackets
+                       if((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
+                               (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)))
+                       {
+                               for(Index = 0; Index < 5; Index ++)
+                                       if(pAd->TxSwQueue[Index].Number > 0)
+                                               RTMPDeQueuePacket(pAd, FALSE, Index, MAX_TX_PROCESS);
+                       }
+               }
+       } while(FALSE);
+
+}
+
+/*
+    ========================================================================
+
+    Routine Description:
+    Check Sanity RSN IE form AP
+
+    Arguments:
+
+    Return Value:
+
+
+    ========================================================================
+*/
+BOOLEAN CheckRSNIE(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pData,
+       IN  UCHAR           DataLen,
+       OUT     UCHAR                   *Offset)
+{
+       PUCHAR              pVIE;
+       UCHAR               len;
+       PEID_STRUCT         pEid;
+       BOOLEAN                         result = FALSE;
+
+       pVIE = pData;
+       len      = DataLen;
+       *Offset = 0;
+
+       while (len > sizeof(RSNIE2))
+       {
+               pEid = (PEID_STRUCT) pVIE;
+               // WPA RSN IE
+               if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
+               {
+                       if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) &&
+                               (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) &&
+                               (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2)))
+                       {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA/WPAPSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2)));
+                                       result = TRUE;
+                       }
+
+                       *Offset += (pEid->Len + 2);
+               }
+               // WPA2 RSN IE
+               else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
+               {
+                       if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) &&
+                               (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) &&
+                               (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2)))
+                       {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2)));
+                                       result = TRUE;
+                       }
+
+                       *Offset += (pEid->Len + 2);
+               }
+               else
+               {
+                       break;
+               }
+
+               pVIE += (pEid->Len + 2);
+               len  -= (pEid->Len + 2);
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> skip_offset(%d) \n", *Offset));
+
+       return result;
+
+}
+
+
+/*
+    ========================================================================
+
+    Routine Description:
+    Parse KEYDATA field.  KEYDATA[] May contain 2 RSN IE and optionally GTK.
+    GTK  is encaptulated in KDE format at  p.83 802.11i D10
+
+    Arguments:
+
+    Return Value:
+
+    Note:
+        802.11i D10
+
+    ========================================================================
+*/
+BOOLEAN ParseKeyData(
+       IN  PRTMP_ADAPTER   pAd,
+       IN  PUCHAR          pKeyData,
+       IN  UCHAR           KeyDataLen,
+       IN      UCHAR                   bPairewise)
+{
+    PKDE_ENCAP          pKDE = NULL;
+    PUCHAR              pMyKeyData = pKeyData;
+    UCHAR               KeyDataLength = KeyDataLen;
+    UCHAR               GTKLEN;
+       UCHAR                           skip_offset;
+
+       // Verify The RSN IE contained in Pairewise-Msg 3 and skip it
+       if (bPairewise)
+    {
+               // Check RSN IE whether it is WPA2/WPA2PSK
+               if (!CheckRSNIE(pAd, pKeyData, KeyDataLen, &skip_offset))
+               {
+                       DBGPRINT(RT_DEBUG_ERROR, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE mismatched \n"));
+                       hex_dump("Get KEYDATA :", pKeyData, KeyDataLen);
+                       return FALSE;
+       }
+       else
+               {
+                       // skip RSN IE
+                       pMyKeyData += skip_offset;
+                       KeyDataLength -= skip_offset;
+
+                       //DBGPRINT(RT_DEBUG_TRACE, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
+               }
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE,("ParseKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
+
+       // Parse EKD format
+       if (KeyDataLength >= 8)
+    {
+        pKDE = (PKDE_ENCAP) pMyKeyData;
+    }
+       else
+    {
+               DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KeyDataLength is too short \n"));
+        return FALSE;
+    }
+
+
+       // Sanity check - shared key index should not be 0
+       if (pKDE->GTKEncap.Kid == 0)
+    {
+        DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index zero \n"));
+        return FALSE;
+    }
+
+       // Sanity check - KED length
+       if (KeyDataLength < (pKDE->Len + 2))
+    {
+        DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
+        return FALSE;
+    }
+
+       // Get GTK length - refer to IEEE 802.11i-2004 p.82
+       GTKLEN = pKDE->Len -6;
+
+       if (GTKLEN < MIN_LEN_OF_GTK)
+       {
+               DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
+        return FALSE;
+       }
+       else
+               DBGPRINT(RT_DEBUG_TRACE, ("GTK Key with KDE formet got index=%d, len=%d \n", pKDE->GTKEncap.Kid, GTKLEN));
+
+       // Update GTK
+       // set key material, TxMic and RxMic for WPAPSK
+       NdisMoveMemory(pAd->StaCfg.GTK, pKDE->GTKEncap.GTK, 32);
+       pAd->StaCfg.DefaultKeyId = pKDE->GTKEncap.Kid;
+
+       // Update shared key table
+       NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY));
+       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK;
+       NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKDE->GTKEncap.GTK, LEN_TKIP_EK);
+       NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, &pKDE->GTKEncap.GTK[16], LEN_TKIP_RXMICK);
+       NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, &pKDE->GTKEncap.GTK[24], LEN_TKIP_TXMICK);
+
+       // Update Shared Key CipherAlg
+       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE;
+       if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
+               pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP;
+       else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
+               pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES;
+       else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
+               pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP64;
+       else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
+               pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP128;
+
+       return TRUE;
+
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Cisco CCKM PRF function
+
+       Arguments:
+               key                             Cisco Base Transient Key (BTK)
+               key_len                 The key length of the BTK
+               data                    Ruquest Number(RN) + BSSID
+               data_len                The length of the data
+               output                  Store for PTK(Pairwise transient keys)
+               len                             The length of the output
+       Return Value:
+               None
+
+       Note:
+               802.1i  Annex F.9
+
+       ========================================================================
+*/
+VOID CCKMPRF(
+       IN      UCHAR   *key,
+       IN      INT             key_len,
+       IN      UCHAR   *data,
+       IN      INT             data_len,
+       OUT     UCHAR   *output,
+       IN      INT             len)
+{
+       INT             i;
+       UCHAR   input[1024];
+       INT             currentindex = 0;
+       INT             total_len;
+
+       NdisMoveMemory(input, data, data_len);
+       total_len = data_len;
+       input[total_len] = 0;
+       total_len++;
+       for     (i = 0; i <     (len + 19) / 20; i++)
+       {
+               HMAC_SHA1(input, total_len,     key, key_len, &output[currentindex]);
+               currentindex += 20;
+               input[total_len - 1]++;
+       }
+}
+
+/*
+       ========================================================================
+
+       Routine Description:
+               Process MIC error indication and record MIC error timer.
+
+       Arguments:
+               pAd     Pointer to our adapter
+               pWpaKey                 Pointer to the WPA key structure
+
+       Return Value:
+               None
+
+       IRQL = DISPATCH_LEVEL
+
+       Note:
+
+       ========================================================================
+*/
+VOID   RTMPReportMicError(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PCIPHER_KEY     pWpaKey)
+{
+       ULONG   Now;
+    UCHAR   unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0);
+
+       // Record Last MIC error time and count
+       Now = jiffies;
+       if (pAd->StaCfg.MicErrCnt == 0)
+       {
+               pAd->StaCfg.MicErrCnt++;
+               pAd->StaCfg.LastMicErrorTime = Now;
+        NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8);
+       }
+       else if (pAd->StaCfg.MicErrCnt == 1)
+       {
+               if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now)
+               {
+                       // Update Last MIC error time, this did not violate two MIC errors within 60 seconds
+                       pAd->StaCfg.LastMicErrorTime = Now;
+               }
+               else
+               {
+
+                       if (pAd->CommonCfg.bWirelessEvent)
+                               RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+
+                       pAd->StaCfg.LastMicErrorTime = Now;
+                       // Violate MIC error counts, MIC countermeasures kicks in
+                       pAd->StaCfg.MicErrCnt++;
+                       // We shall block all reception
+                       // We shall clean all Tx ring and disassoicate from AP after next EAPOL frame
+                       //
+                       // No necessary to clean all Tx ring, on RTMPHardTransmit will stop sending non-802.1X EAPOL packets
+                       // if pAd->StaCfg.MicErrCnt greater than 2.
+                       //
+                       // RTMPRingCleanUp(pAd, QID_AC_BK);
+                       // RTMPRingCleanUp(pAd, QID_AC_BE);
+                       // RTMPRingCleanUp(pAd, QID_AC_VI);
+                       // RTMPRingCleanUp(pAd, QID_AC_VO);
+                       // RTMPRingCleanUp(pAd, QID_HCCA);
+               }
+       }
+       else
+       {
+               // MIC error count >= 2
+               // This should not happen
+               ;
+       }
+    MlmeEnqueue(pAd,
+                               MLME_CNTL_STATE_MACHINE,
+                               OID_802_11_MIC_FAILURE_REPORT_FRAME,
+                               1,
+                               &unicastKey);
+
+    if (pAd->StaCfg.MicErrCnt == 2)
+    {
+        RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100);
+    }
+}
+
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#define        LENGTH_EAP_H    4
+// If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)).
+INT        WpaCheckEapCode(
+       IN  PRTMP_ADAPTER               pAd,
+       IN  PUCHAR                              pFrame,
+       IN  USHORT                              FrameLen,
+       IN  USHORT                              OffSet)
+{
+
+       PUCHAR  pData;
+       INT     result = 0;
+
+       if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H )
+               return result;
+
+       pData = pFrame + OffSet; // skip offset bytes
+
+       if(*(pData+1) == EAPPacket)     // 802.1x header - Packet Type
+       {
+                result = *(pData+4);           // EAP header - Code
+       }
+
+       return result;
+}
+
+VOID    WpaSendMicFailureToWpaSupplicant(
+    IN  PRTMP_ADAPTER    pAd,
+    IN  BOOLEAN          bUnicast)
+{
+    union iwreq_data    wrqu;
+    char custom[IW_CUSTOM_MAX] = {0};
+
+    sprintf(custom, "MLME-MICHAELMICFAILURE.indication");
+    if (bUnicast)
+        sprintf(custom, "%s unicast", custom);
+    wrqu.data.length = strlen(custom);
+    wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom);
+
+    return;
+}
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+VOID   WpaMicFailureReportFrame(
+       IN  PRTMP_ADAPTER   pAd,
+       IN MLME_QUEUE_ELEM *Elem)
+{
+       PUCHAR              pOutBuffer = NULL;
+       UCHAR               Header802_3[14];
+       ULONG               FrameLen = 0;
+       EAPOL_PACKET        Packet;
+       UCHAR               Mic[16];
+    BOOLEAN             bUnicast;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n"));
+
+    bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE);
+       pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);
+
+       // init 802.3 header and Fill Packet
+       MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
+
+       NdisZeroMemory(&Packet, sizeof(Packet));
+       Packet.ProVer   = EAPOL_VER;
+       Packet.ProType  = EAPOLKey;
+
+       Packet.KeyDesc.Type = WPA1_KEY_DESC;
+
+    // Request field presented
+    Packet.KeyDesc.KeyInfo.Request = 1;
+
+       if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
+       {
+               Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
+       }
+       else      // TKIP
+       {
+               Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
+       }
+
+    Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY);
+
+       // KeyMic field presented
+       Packet.KeyDesc.KeyInfo.KeyMic  = 1;
+
+    // Error field presented
+       Packet.KeyDesc.KeyInfo.Error  = 1;
+
+       // Update packet length after decide Key data payload
+       Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE;
+
+       // Key Replay Count
+       NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
+    inc_byte_array(pAd->StaCfg.ReplayCounter, 8);
+
+       // Convert to little-endian format.
+       *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
+
+
+       MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  // allocate memory
+       if(pOutBuffer == NULL)
+       {
+               return;
+       }
+
+       // Prepare EAPOL frame for MIC calculation
+       // Be careful, only EAPOL frame is counted for MIC calculation
+       MakeOutgoingFrame(pOutBuffer,               &FrameLen,
+                             Packet.Body_Len[1] + 4,   &Packet,
+                             END_OF_ARGS);
+
+       // Prepare and Fill MIC value
+       NdisZeroMemory(Mic, sizeof(Mic));
+       if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
+       {       // AES
+        UCHAR digest[20] = {0};
+               HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
+               NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
+       }
+       else
+       {       // TKIP
+               hmac_md5(pAd->StaCfg.PTK,  LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
+       }
+       NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
+
+    MakeOutgoingFrame(pOutBuffer,              &FrameLen,
+                               LENGTH_802_3,                           &Header802_3,
+                               Packet.Body_Len[1] + 4,     &Packet,
+                               END_OF_ARGS);
+
+       // opy frame to Tx ring and send MIC failure report frame to authenticator
+       RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE);
+
+       MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n"));
+}
+
+/** from wpa_supplicant
+ * inc_byte_array - Increment arbitrary length byte array by one
+ * @counter: Pointer to byte array
+ * @len: Length of the counter in bytes
+ *
+ * This function increments the last byte of the counter by one and continues
+ * rolling over to more significant bytes if the byte was incremented from
+ * 0xff to 0x00.
+ */
+void inc_byte_array(UCHAR *counter, int len)
+{
+       int pos = len - 1;
+       while (pos >= 0) {
+               counter[pos]++;
+               if (counter[pos] != 0)
+                       break;
+               pos--;
+       }
+}
+
+VOID WpaDisassocApAndBlockAssoc(
+    IN PVOID SystemSpecific1,
+    IN PVOID FunctionContext,
+    IN PVOID SystemSpecific2,
+    IN PVOID SystemSpecific3)
+{
+    RTMP_ADAPTER                *pAd = (PRTMP_ADAPTER)FunctionContext;
+    MLME_DISASSOC_REQ_STRUCT    DisassocReq;
+
+       // disassoc from current AP first
+       DBGPRINT(RT_DEBUG_TRACE, ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n"));
+       DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_MIC_FAILURE);
+       MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
+
+       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
+       pAd->StaCfg.bBlockAssoc = TRUE;
+}
+
diff --git a/drivers/staging/rt2870/sta_ioctl.c b/drivers/staging/rt2870/sta_ioctl.c
new file mode 100644 (file)
index 0000000..bb386ab
--- /dev/null
@@ -0,0 +1,7068 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    sta_ioctl.c
+
+    Abstract:
+    IOCTL related subroutines
+
+    Revision History:
+    Who         When          What
+    --------    ----------    ----------------------------------------------
+    Rory Chen   01-03-2003    created
+       Rory Chen   02-14-2005    modify to support RT61
+*/
+
+#include       "rt_config.h"
+
+#ifdef DBG
+extern ULONG    RTDebugLevel;
+#endif
+
+#define NR_WEP_KEYS                            4
+#define WEP_SMALL_KEY_LEN                      (40/8)
+#define WEP_LARGE_KEY_LEN                      (104/8)
+
+#define GROUP_KEY_NO                4
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E)               iwe_stream_add_event(_A, _B, _C, _D, _E)
+#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E)               iwe_stream_add_point(_A, _B, _C, _D, _E)
+#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F)   iwe_stream_add_value(_A, _B, _C, _D, _E, _F)
+#else
+#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E)               iwe_stream_add_event(_B, _C, _D, _E)
+#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E)               iwe_stream_add_point(_B, _C, _D, _E)
+#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F)   iwe_stream_add_value(_B, _C, _D, _E, _F)
+#endif
+
+extern UCHAR    CipherWpa2Template[];
+extern UCHAR    CipherWpaPskTkip[];
+extern UCHAR    CipherWpaPskTkipLen;
+
+typedef struct PACKED _RT_VERSION_INFO{
+    UCHAR       DriverVersionW;
+    UCHAR       DriverVersionX;
+    UCHAR       DriverVersionY;
+    UCHAR       DriverVersionZ;
+    UINT        DriverBuildYear;
+    UINT        DriverBuildMonth;
+    UINT        DriverBuildDay;
+} RT_VERSION_INFO, *PRT_VERSION_INFO;
+
+struct iw_priv_args privtab[] = {
+{ RTPRIV_IOCTL_SET,
+  IW_PRIV_TYPE_CHAR | 1024, 0,
+  "set"},
+
+{ RTPRIV_IOCTL_SHOW, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  ""},
+{ RTPRIV_IOCTL_SHOW, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  ""},
+/* --- sub-ioctls definitions --- */
+    { SHOW_CONN_STATUS,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "connStatus" },
+       { SHOW_DRVIER_VERION,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "driverVer" },
+    { SHOW_BA_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "bainfo" },
+       { SHOW_DESC_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "descinfo" },
+    { RAIO_OFF,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_off" },
+       { RAIO_ON,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_on" },
+#ifdef QOS_DLS_SUPPORT
+       { SHOW_DLS_ENTRY_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "dlsentryinfo" },
+#endif // QOS_DLS_SUPPORT //
+       { SHOW_CFG_VALUE,
+         IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "show" },
+       { SHOW_ADHOC_ENTRY_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "adhocEntry" },
+
+/* --- sub-ioctls relations --- */
+
+#ifdef DBG
+{ RTPRIV_IOCTL_BBP,
+  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  "bbp"},
+{ RTPRIV_IOCTL_MAC,
+  IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024,
+  "mac"},
+{ RTPRIV_IOCTL_E2P,
+  IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024,
+  "e2p"},
+#endif  /* DBG */
+
+{ RTPRIV_IOCTL_STATISTICS,
+  0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  "stat"},
+{ RTPRIV_IOCTL_GSITESURVEY,
+  0, IW_PRIV_TYPE_CHAR | 1024,
+  "get_site_survey"},
+};
+
+INT Set_SSID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+#ifdef WMM_SUPPORT
+INT    Set_WmmCapable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif
+
+INT Set_NetworkType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_AuthMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_EncrypType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_DefaultKeyID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key1_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key2_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key3_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key4_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_WPAPSK_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+
+INT Set_PSMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+INT Set_Wpa_Support(
+    IN PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef DBG
+VOID RTMPIoctlBBP(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq);
+
+VOID RTMPIoctlMAC(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq);
+
+VOID RTMPIoctlE2PROM(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  struct iwreq    *wrq);
+#endif // DBG //
+
+
+NDIS_STATUS RTMPWPANoneAddKeyProc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN PVOID                   pBuf);
+
+INT Set_FragTest_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+#ifdef DOT11_N_SUPPORT
+INT Set_TGnWifiTest_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg);
+#endif // DOT11_N_SUPPORT //
+
+INT Set_LongRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg);
+
+INT Set_ShortRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg);
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+INT Set_Ieee80211dClientMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+#ifdef CARRIER_DETECTION_SUPPORT
+INT Set_CarrierDetect_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg);
+#endif // CARRIER_DETECTION_SUPPORT //
+
+INT    Show_Adhoc_MacTable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PCHAR                   extra);
+
+static struct {
+       CHAR *name;
+       INT (*set_proc)(PRTMP_ADAPTER pAdapter, PUCHAR arg);
+} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = {
+       {"DriverVersion",                               Set_DriverVersion_Proc},
+       {"CountryRegion",                               Set_CountryRegion_Proc},
+       {"CountryRegionABand",                  Set_CountryRegionABand_Proc},
+       {"SSID",                                                Set_SSID_Proc},
+       {"WirelessMode",                                Set_WirelessMode_Proc},
+       {"TxBurst",                                     Set_TxBurst_Proc},
+       {"TxPreamble",                          Set_TxPreamble_Proc},
+       {"TxPower",                                     Set_TxPower_Proc},
+       {"Channel",                                     Set_Channel_Proc},
+       {"BGProtection",                                Set_BGProtection_Proc},
+       {"RTSThreshold",                                Set_RTSThreshold_Proc},
+       {"FragThreshold",                               Set_FragThreshold_Proc},
+#ifdef DOT11_N_SUPPORT
+       {"HtBw",                                Set_HtBw_Proc},
+       {"HtMcs",                               Set_HtMcs_Proc},
+       {"HtGi",                                Set_HtGi_Proc},
+       {"HtOpMode",                        Set_HtOpMode_Proc},
+       {"HtExtcha",                        Set_HtExtcha_Proc},
+       {"HtMpduDensity",                       Set_HtMpduDensity_Proc},
+       {"HtBaWinSize",                         Set_HtBaWinSize_Proc},
+       {"HtRdg",                                       Set_HtRdg_Proc},
+       {"HtAmsdu",                                     Set_HtAmsdu_Proc},
+       {"HtAutoBa",                            Set_HtAutoBa_Proc},
+       {"HtBaDecline",                                 Set_BADecline_Proc},
+       {"HtProtect",                           Set_HtProtect_Proc},
+       {"HtMimoPs",                            Set_HtMimoPs_Proc},
+#endif // DOT11_N_SUPPORT //
+
+#ifdef AGGREGATION_SUPPORT
+       {"PktAggregate",                                Set_PktAggregate_Proc},
+#endif
+
+#ifdef WMM_SUPPORT
+       {"WmmCapable",                                  Set_WmmCapable_Proc},
+#endif
+       {"IEEE80211H",                                  Set_IEEE80211H_Proc},
+    {"NetworkType",                 Set_NetworkType_Proc},
+       {"AuthMode",                                    Set_AuthMode_Proc},
+       {"EncrypType",                                  Set_EncrypType_Proc},
+       {"DefaultKeyID",                                Set_DefaultKeyID_Proc},
+       {"Key1",                                                Set_Key1_Proc},
+       {"Key2",                                                Set_Key2_Proc},
+       {"Key3",                                                Set_Key3_Proc},
+       {"Key4",                                                Set_Key4_Proc},
+       {"WPAPSK",                                              Set_WPAPSK_Proc},
+       {"ResetCounter",                                Set_ResetStatCounter_Proc},
+       {"PSMode",                      Set_PSMode_Proc},
+#ifdef DBG
+       {"Debug",                                               Set_Debug_Proc},
+#endif
+
+#ifdef RALINK_ATE
+       {"ATE",                                                 Set_ATE_Proc},
+       {"ATEDA",                                               Set_ATE_DA_Proc},
+       {"ATESA",                                               Set_ATE_SA_Proc},
+       {"ATEBSSID",                                    Set_ATE_BSSID_Proc},
+       {"ATECHANNEL",                                  Set_ATE_CHANNEL_Proc},
+       {"ATETXPOW0",                                   Set_ATE_TX_POWER0_Proc},
+       {"ATETXPOW1",                                   Set_ATE_TX_POWER1_Proc},
+       {"ATETXANT",                                    Set_ATE_TX_Antenna_Proc},
+       {"ATERXANT",                                    Set_ATE_RX_Antenna_Proc},
+       {"ATETXFREQOFFSET",                             Set_ATE_TX_FREQOFFSET_Proc},
+       {"ATETXBW",                                             Set_ATE_TX_BW_Proc},
+       {"ATETXLEN",                                    Set_ATE_TX_LENGTH_Proc},
+       {"ATETXCNT",                                    Set_ATE_TX_COUNT_Proc},
+       {"ATETXMCS",                                    Set_ATE_TX_MCS_Proc},
+       {"ATETXMODE",                                   Set_ATE_TX_MODE_Proc},
+       {"ATETXGI",                                             Set_ATE_TX_GI_Proc},
+       {"ATERXFER",                                    Set_ATE_RX_FER_Proc},
+       {"ATERRF",                                              Set_ATE_Read_RF_Proc},
+       {"ATEWRF1",                                             Set_ATE_Write_RF1_Proc},
+       {"ATEWRF2",                                             Set_ATE_Write_RF2_Proc},
+       {"ATEWRF3",                                             Set_ATE_Write_RF3_Proc},
+       {"ATEWRF4",                                             Set_ATE_Write_RF4_Proc},
+       {"ATELDE2P",                                Set_ATE_Load_E2P_Proc},
+       {"ATERE2P",                                             Set_ATE_Read_E2P_Proc},
+       {"ATESHOW",                                             Set_ATE_Show_Proc},
+       {"ATEHELP",                                             Set_ATE_Help_Proc},
+
+#ifdef RALINK_28xx_QA
+       {"TxStop",                                              Set_TxStop_Proc},
+       {"RxStop",                                              Set_RxStop_Proc},
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+    {"WpaSupport",                  Set_Wpa_Support},
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+
+
+       {"FixedTxMode",                 Set_FixedTxMode_Proc},
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+       {"OpMode",                                              Set_OpMode_Proc},
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+#ifdef DOT11_N_SUPPORT
+    {"TGnWifiTest",                 Set_TGnWifiTest_Proc},
+    {"ForceGF",                                        Set_ForceGF_Proc},
+#endif // DOT11_N_SUPPORT //
+#ifdef QOS_DLS_SUPPORT
+       {"DlsAddEntry",                                 Set_DlsAddEntry_Proc},
+       {"DlsTearDownEntry",                    Set_DlsTearDownEntry_Proc},
+#endif // QOS_DLS_SUPPORT //
+       {"LongRetry",                           Set_LongRetryLimit_Proc},
+       {"ShortRetry",                          Set_ShortRetryLimit_Proc},
+#ifdef EXT_BUILD_CHANNEL_LIST
+       {"11dClientMode",                               Set_Ieee80211dClientMode_Proc},
+#endif // EXT_BUILD_CHANNEL_LIST //
+#ifdef CARRIER_DETECTION_SUPPORT
+       {"CarrierDetect",                               Set_CarrierDetect_Proc},
+#endif // CARRIER_DETECTION_SUPPORT //
+
+       {NULL,}
+};
+
+
+VOID RTMPAddKey(
+       IN      PRTMP_ADAPTER       pAd,
+       IN      PNDIS_802_11_KEY    pKey)
+{
+       ULONG                           KeyIdx;
+       MAC_TABLE_ENTRY         *pEntry;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey ------>\n"));
+
+       if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+       {
+               if (pKey->KeyIndex & 0x80000000)
+               {
+                   if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+            {
+                NdisZeroMemory(pAd->StaCfg.PMK, 32);
+                NdisMoveMemory(pAd->StaCfg.PMK, pKey->KeyMaterial, pKey->KeyLength);
+                goto end;
+            }
+                   // Update PTK
+                   NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
+            pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
+            NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pKey->KeyMaterial, LEN_TKIP_EK);
+#ifdef WPA_SUPPLICANT_SUPPORT
+            if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+            {
+                NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+            else
+#endif // WPA_SUPPLICANT_SUPPORT //
+            {
+               NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+
+            // Decide its ChiperAlg
+               if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+                       pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
+               else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
+                       pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
+               else
+                       pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE;
+
+            // Update these related information to MAC_TABLE_ENTRY
+               pEntry = &pAd->MacTab.Content[BSSID_WCID];
+            NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[BSS0][0].Key, LEN_TKIP_EK);
+               NdisMoveMemory(pEntry->PairwiseKey.RxMic, pAd->SharedKey[BSS0][0].RxMic, LEN_TKIP_RXMICK);
+               NdisMoveMemory(pEntry->PairwiseKey.TxMic, pAd->SharedKey[BSS0][0].TxMic, LEN_TKIP_TXMICK);
+               pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
+
+               // Update pairwise key information to ASIC Shared Key Table
+               AsicAddSharedKeyEntry(pAd,
+                                                         BSS0,
+                                                         0,
+                                                         pAd->SharedKey[BSS0][0].CipherAlg,
+                                                         pAd->SharedKey[BSS0][0].Key,
+                                                         pAd->SharedKey[BSS0][0].TxMic,
+                                                         pAd->SharedKey[BSS0][0].RxMic);
+
+               // Update ASIC WCID attribute table and IVEIV table
+               RTMPAddWcidAttributeEntry(pAd,
+                                                                 BSS0,
+                                                                 0,
+                                                                 pAd->SharedKey[BSS0][0].CipherAlg,
+                                                                 pEntry);
+
+            if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2)
+            {
+                // set 802.1x port control
+                   //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               STA_PORT_SECURED(pAd);
+
+                // Indicate Connected for GUI
+                pAd->IndicateMediaState = NdisMediaStateConnected;
+            }
+               }
+        else
+        {
+            // Update GTK
+            pAd->StaCfg.DefaultKeyId = (pKey->KeyIndex & 0xFF);
+            NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY));
+            pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK;
+            NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKey->KeyMaterial, LEN_TKIP_EK);
+#ifdef WPA_SUPPLICANT_SUPPORT
+            if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
+            {
+                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+            else
+#endif // WPA_SUPPLICANT_SUPPORT //
+            {
+               NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+
+            // Update Shared Key CipherAlg
+               pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE;
+               if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP;
+               else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES;
+
+            // Update group key information to ASIC Shared Key Table
+               AsicAddSharedKeyEntry(pAd,
+                                                         BSS0,
+                                                         pAd->StaCfg.DefaultKeyId,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic);
+
+               // Update ASIC WCID attribute table and IVEIV table
+               RTMPAddWcidAttributeEntry(pAd,
+                                                                 BSS0,
+                                                                 pAd->StaCfg.DefaultKeyId,
+                                                                 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+                                                                 NULL);
+
+            // set 802.1x port control
+               //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAd);
+
+            // Indicate Connected for GUI
+            pAd->IndicateMediaState = NdisMediaStateConnected;
+        }
+       }
+       else    // dynamic WEP from wpa_supplicant
+       {
+               UCHAR   CipherAlg;
+       PUCHAR  Key;
+
+               if(pKey->KeyLength == 32)
+                       goto end;
+
+               KeyIdx = pKey->KeyIndex & 0x0fffffff;
+
+               if (KeyIdx < 4)
+               {
+                       // it is a default shared key, for Pairwise key setting
+                       if (pKey->KeyIndex & 0x80000000)
+                       {
+                               pEntry = MacTableLookup(pAd, pKey->BSSID);
+
+                               if (pEntry)
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey: Set Pair-wise Key\n"));
+
+                                       // set key material and key length
+                                       pEntry->PairwiseKey.KeyLen = (UCHAR)pKey->KeyLength;
+                                       NdisMoveMemory(pEntry->PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength);
+
+                                       // set Cipher type
+                                       if (pKey->KeyLength == 5)
+                                               pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64;
+                                       else
+                                               pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128;
+
+                                       // Add Pair-wise key to Asic
+                                       AsicAddPairwiseKeyEntry(
+                                               pAd,
+                                               pEntry->Addr,
+                                               (UCHAR)pEntry->Aid,
+                               &pEntry->PairwiseKey);
+
+                                       // update WCID attribute table and IVEIV table for this entry
+                                       RTMPAddWcidAttributeEntry(
+                                               pAd,
+                                               BSS0,
+                                               KeyIdx, // The value may be not zero
+                                               pEntry->PairwiseKey.CipherAlg,
+                                               pEntry);
+
+                               }
+                       }
+                       else
+            {
+                               // Default key for tx (shared key)
+                               pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx;
+
+                               // set key material and key length
+                               pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pKey->KeyLength;
+                               NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength);
+
+                               // Set Ciper type
+                               if (pKey->KeyLength == 5)
+                                       pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP64;
+                               else
+                                       pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP128;
+
+                       CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
+                       Key = pAd->SharedKey[BSS0][KeyIdx].Key;
+
+                               // Set Group key material to Asic
+                       AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL);
+
+                               // Update WCID attribute table and IVEIV table for this group key table
+                               RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, CipherAlg, NULL);
+
+                       }
+               }
+       }
+end:
+       return;
+}
+
+char * rtstrchr(const char * s, int c)
+{
+    for(; *s != (char) c; ++s)
+        if (*s == '\0')
+            return NULL;
+    return (char *) s;
+}
+
+/*
+This is required for LinEX2004/kernel2.6.7 to provide iwlist scanning function
+*/
+
+int
+rt_ioctl_giwname(struct net_device *dev,
+                  struct iw_request_info *info,
+                  char *name, char *extra)
+{
+//     PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+#ifdef RT2870
+       strncpy(name, "RT2870 Wireless", IFNAMSIZ);
+#endif // RT2870 //
+       return 0;
+}
+
+int rt_ioctl_siwfreq(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_freq *freq, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       int     chan = -1;
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+        return -ENETDOWN;
+    }
+
+
+       if (freq->e > 1)
+               return -EINVAL;
+
+       if((freq->e == 0) && (freq->m <= 1000))
+               chan = freq->m; // Setting by channel number
+       else
+               MAP_KHZ_TO_CHANNEL_ID( (freq->m /100) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G,
+
+    if (ChannelSanity(pAdapter, chan) == TRUE)
+    {
+       pAdapter->CommonCfg.Channel = chan;
+       DBGPRINT(RT_DEBUG_ERROR, ("==>rt_ioctl_siwfreq::SIOCSIWFREQ[cmd=0x%x] (Channel=%d)\n", SIOCSIWFREQ, pAdapter->CommonCfg.Channel));
+    }
+    else
+        return -EINVAL;
+
+       return 0;
+}
+int rt_ioctl_giwfreq(struct net_device *dev,
+                  struct iw_request_info *info,
+                  struct iw_freq *freq, char *extra)
+{
+    VIRTUAL_ADAPTER *pVirtualAd = NULL;
+       PRTMP_ADAPTER pAdapter = NULL;
+       UCHAR ch;
+       ULONG   m;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+               ch = pAdapter->CommonCfg.Channel;
+
+       DBGPRINT(RT_DEBUG_TRACE,("==>rt_ioctl_giwfreq  %d\n", ch));
+
+    MAP_CHANNEL_ID_TO_KHZ(ch, m);
+       freq->m = m * 100;
+       freq->e = 1;
+       return 0;
+}
+
+int rt_ioctl_siwmode(struct net_device *dev,
+                  struct iw_request_info *info,
+                  __u32 *mode, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+       DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+    }
+
+       switch (*mode)
+       {
+               case IW_MODE_ADHOC:
+                       Set_NetworkType_Proc(pAdapter, "Adhoc");
+                       break;
+               case IW_MODE_INFRA:
+                       Set_NetworkType_Proc(pAdapter, "Infra");
+                       break;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
+        case IW_MODE_MONITOR:
+                       Set_NetworkType_Proc(pAdapter, "Monitor");
+                       break;
+#endif
+               default:
+                       DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_siwmode::SIOCSIWMODE (unknown %d)\n", *mode));
+                       return -EINVAL;
+       }
+
+       // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key
+       pAdapter->StaCfg.WpaState = SS_NOTUSE;
+
+       return 0;
+}
+
+int rt_ioctl_giwmode(struct net_device *dev,
+                  struct iw_request_info *info,
+                  __u32 *mode, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       if (ADHOC_ON(pAdapter))
+               *mode = IW_MODE_ADHOC;
+    else if (INFRA_ON(pAdapter))
+               *mode = IW_MODE_INFRA;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
+    else if (MONITOR_ON(pAdapter))
+    {
+        *mode = IW_MODE_MONITOR;
+    }
+#endif
+    else
+        *mode = IW_MODE_AUTO;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("==>rt_ioctl_giwmode(mode=%d)\n", *mode));
+       return 0;
+}
+
+int rt_ioctl_siwsens(struct net_device *dev,
+                  struct iw_request_info *info,
+                  char *name, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       return 0;
+}
+
+int rt_ioctl_giwsens(struct net_device *dev,
+                  struct iw_request_info *info,
+                  char *name, char *extra)
+{
+       return 0;
+}
+
+int rt_ioctl_giwrange(struct net_device *dev,
+                  struct iw_request_info *info,
+                  struct iw_point *data, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+       struct iw_range *range = (struct iw_range *) extra;
+       u16 val;
+       int i;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE ,("===>rt_ioctl_giwrange\n"));
+       data->length = sizeof(struct iw_range);
+       memset(range, 0, sizeof(struct iw_range));
+
+       range->txpower_capa = IW_TXPOW_DBM;
+
+       if (INFRA_ON(pAdapter)||ADHOC_ON(pAdapter))
+       {
+               range->min_pmp = 1 * 1024;
+               range->max_pmp = 65535 * 1024;
+               range->min_pmt = 1 * 1024;
+               range->max_pmt = 1000 * 1024;
+               range->pmp_flags = IW_POWER_PERIOD;
+               range->pmt_flags = IW_POWER_TIMEOUT;
+               range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT |
+                       IW_POWER_UNICAST_R | IW_POWER_ALL_R;
+       }
+
+       range->we_version_compiled = WIRELESS_EXT;
+       range->we_version_source = 14;
+
+       range->retry_capa = IW_RETRY_LIMIT;
+       range->retry_flags = IW_RETRY_LIMIT;
+       range->min_retry = 0;
+       range->max_retry = 255;
+
+       range->num_channels =  pAdapter->ChannelListNum;
+
+       val = 0;
+       for (i = 1; i <= range->num_channels; i++)
+       {
+               u32 m;
+               range->freq[val].i = pAdapter->ChannelList[i-1].Channel;
+               MAP_CHANNEL_ID_TO_KHZ(pAdapter->ChannelList[i-1].Channel, m);
+               range->freq[val].m = m * 100; /* HZ */
+
+               range->freq[val].e = 1;
+               val++;
+               if (val == IW_MAX_FREQUENCIES)
+                       break;
+       }
+       range->num_frequency = val;
+
+       range->max_qual.qual = 100; /* what is correct max? This was not
+                                       * documented exactly. At least
+                                       * 69 has been observed. */
+       range->max_qual.level = 0; /* dB */
+       range->max_qual.noise = 0; /* dB */
+
+       /* What would be suitable values for "average/typical" qual? */
+       range->avg_qual.qual = 20;
+       range->avg_qual.level = -60;
+       range->avg_qual.noise = -95;
+       range->sensitivity = 3;
+
+       range->max_encoding_tokens = NR_WEP_KEYS;
+       range->num_encoding_sizes = 2;
+       range->encoding_size[0] = 5;
+       range->encoding_size[1] = 13;
+
+       range->min_rts = 0;
+       range->max_rts = 2347;
+       range->min_frag = 256;
+       range->max_frag = 2346;
+
+#if WIRELESS_EXT > 17
+       /* IW_ENC_CAPA_* bit field */
+       range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+                                       IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+#endif
+
+       return 0;
+}
+
+int rt_ioctl_siwap(struct net_device *dev,
+                     struct iw_request_info *info,
+                     struct sockaddr *ap_addr, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+    NDIS_802_11_MAC_ADDRESS Bssid;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+    }
+
+       if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+    {
+        RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+        DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+    }
+
+    // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+    // this request, because this request is initiated by NDIS.
+    pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+       // Prevent to connect AP again in STAMlmePeriodicExec
+       pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+
+    memset(Bssid, 0, MAC_ADDR_LEN);
+    memcpy(Bssid, ap_addr->sa_data, MAC_ADDR_LEN);
+    MlmeEnqueue(pAdapter,
+                MLME_CNTL_STATE_MACHINE,
+                OID_802_11_BSSID,
+                sizeof(NDIS_802_11_MAC_ADDRESS),
+                (VOID *)&Bssid);
+
+    DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCSIWAP %02x:%02x:%02x:%02x:%02x:%02x\n",
+        Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
+
+       return 0;
+}
+
+int rt_ioctl_giwap(struct net_device *dev,
+                     struct iw_request_info *info,
+                     struct sockaddr *ap_addr, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
+       {
+               ap_addr->sa_family = ARPHRD_ETHER;
+               memcpy(ap_addr->sa_data, &pAdapter->CommonCfg.Bssid, ETH_ALEN);
+       }
+#ifdef WPA_SUPPLICANT_SUPPORT
+    // Add for RT2870
+    else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+    {
+        ap_addr->sa_family = ARPHRD_ETHER;
+        memcpy(ap_addr->sa_data, &pAdapter->MlmeAux.Bssid, ETH_ALEN);
+    }
+#endif // WPA_SUPPLICANT_SUPPORT //
+       else
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=EMPTY)\n"));
+               return -ENOTCONN;
+       }
+
+       return 0;
+}
+
+/*
+ * Units are in db above the noise floor. That means the
+ * rssi values reported in the tx/rx descriptors in the
+ * driver are the SNR expressed in db.
+ *
+ * If you assume that the noise floor is -95, which is an
+ * excellent assumption 99.5 % of the time, then you can
+ * derive the absolute signal level (i.e. -95 + rssi).
+ * There are some other slight factors to take into account
+ * depending on whether the rssi measurement is from 11b,
+ * 11g, or 11a.   These differences are at most 2db and
+ * can be documented.
+ *
+ * NB: various calculations are based on the orinoco/wavelan
+ *     drivers for compatibility
+ */
+static void set_quality(PRTMP_ADAPTER pAdapter,
+                        struct iw_quality *iq,
+                        signed char rssi)
+{
+       __u8 ChannelQuality;
+
+       // Normalize Rssi
+       if (rssi >= -50)
+               ChannelQuality = 100;
+       else if (rssi >= -80) // between -50 ~ -80dbm
+               ChannelQuality = (__u8)(24 + ((rssi + 80) * 26)/10);
+       else if (rssi >= -90)   // between -80 ~ -90dbm
+        ChannelQuality = (__u8)((rssi + 90) * 26)/10;
+       else
+               ChannelQuality = 0;
+
+    iq->qual = (__u8)ChannelQuality;
+
+    iq->level = (__u8)(rssi);
+    iq->noise = (pAdapter->BbpWriteLatch[66] > pAdapter->BbpTuning.FalseCcaUpperThreshold) ? ((__u8)pAdapter->BbpTuning.FalseCcaUpperThreshold) : ((__u8) pAdapter->BbpWriteLatch[66]);        // noise level (dBm)
+    iq->noise += 256 - 143;
+    iq->updated = pAdapter->iw_stats.qual.updated;
+}
+
+int rt_ioctl_iwaplist(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_point *data, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       struct sockaddr addr[IW_MAX_AP];
+       struct iw_quality qual[IW_MAX_AP];
+       int i;
+
+       //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               data->length = 0;
+               return 0;
+        //return -ENETDOWN;
+       }
+
+       for (i = 0; i <IW_MAX_AP ; i++)
+       {
+               if (i >=  pAdapter->ScanTab.BssNr)
+                       break;
+               addr[i].sa_family = ARPHRD_ETHER;
+                       memcpy(addr[i].sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN);
+               set_quality(pAdapter, &qual[i], pAdapter->ScanTab.BssEntry[i].Rssi);
+       }
+       data->length = i;
+       memcpy(extra, &addr, i*sizeof(addr[0]));
+       data->flags = 1;                /* signal quality present (sort of) */
+       memcpy(extra + i*sizeof(addr[0]), &qual, i*sizeof(qual[i]));
+
+       return 0;
+}
+
+#ifdef SIOCGIWSCAN
+int rt_ioctl_siwscan(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_point *data, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       ULONG                                                           Now;
+       int Status = NDIS_STATUS_SUCCESS;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       if (MONITOR_ON(pAdapter))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n"));
+        return -EINVAL;
+    }
+
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+       if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE)
+       {
+               pAdapter->StaCfg.WpaSupplicantScanCount++;
+       }
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+    pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE;
+       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+               return 0;
+       do{
+               Now = jiffies;
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+               if ((pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) &&
+                       (pAdapter->StaCfg.WpaSupplicantScanCount > 3))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!! WpaSupplicantScanCount > 3\n"));
+                       Status = NDIS_STATUS_SUCCESS;
+                       break;
+               }
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+               if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) &&
+                       ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+                       (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) &&
+                       (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n"));
+                       Status = NDIS_STATUS_SUCCESS;
+                       break;
+               }
+
+               if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+               {
+                       RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+               }
+
+               // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+               // this request, because this request is initiated by NDIS.
+               pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+               // Reset allowed scan retries
+               pAdapter->StaCfg.ScanCnt = 0;
+               pAdapter->StaCfg.LastScanTime = Now;
+
+               MlmeEnqueue(pAdapter,
+                       MLME_CNTL_STATE_MACHINE,
+                       OID_802_11_BSSID_LIST_SCAN,
+                       0,
+                       NULL);
+
+               Status = NDIS_STATUS_SUCCESS;
+               RT28XX_MLME_HANDLER(pAdapter);
+       }while(0);
+       return 0;
+}
+
+int rt_ioctl_giwscan(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_point *data, char *extra)
+{
+
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       int i=0;
+       char *current_ev = extra, *previous_ev = extra;
+       char *end_buf;
+       char *current_val, custom[MAX_CUSTOM_LEN] = {0};
+#ifndef IWEVGENIE
+       char idx;
+#endif // IWEVGENIE //
+       struct iw_event iwe;
+
+       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+    {
+               /*
+                * Still scanning, indicate the caller should try again.
+                */
+               return -EAGAIN;
+       }
+
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+       if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE)
+       {
+               pAdapter->StaCfg.WpaSupplicantScanCount = 0;
+       }
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+       if (pAdapter->ScanTab.BssNr == 0)
+       {
+               data->length = 0;
+               return 0;
+       }
+
+#if WIRELESS_EXT >= 17
+    if (data->length > 0)
+        end_buf = extra + data->length;
+    else
+        end_buf = extra + IW_SCAN_MAX_DATA;
+#else
+    end_buf = extra + IW_SCAN_MAX_DATA;
+#endif
+
+       for (i = 0; i < pAdapter->ScanTab.BssNr; i++)
+       {
+               if (current_ev >= end_buf)
+        {
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+        }
+
+               //MAC address
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWAP;
+               iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+                               memcpy(iwe.u.ap_addr.sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, ETH_ALEN);
+
+        previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //ESSID
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWESSID;
+               iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].SsidLen;
+               iwe.u.data.flags = 1;
+
+        previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_POINT(info, current_ev,end_buf, &iwe, pAdapter->ScanTab.BssEntry[i].Ssid);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Network Type
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWMODE;
+               if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11IBSS)
+               {
+                       iwe.u.mode = IW_MODE_ADHOC;
+               }
+               else if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11Infrastructure)
+               {
+                       iwe.u.mode = IW_MODE_INFRA;
+               }
+               else
+               {
+                       iwe.u.mode = IW_MODE_AUTO;
+               }
+               iwe.len = IW_EV_UINT_LEN;
+
+        previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe,  IW_EV_UINT_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Channel and Frequency
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWFREQ;
+               if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
+                       iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
+               else
+                       iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
+               iwe.u.freq.e = 0;
+               iwe.u.freq.i = 0;
+
+               previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+        //Add quality statistics
+        //================================
+        memset(&iwe, 0, sizeof(iwe));
+       iwe.cmd = IWEVQUAL;
+       iwe.u.qual.level = 0;
+       iwe.u.qual.noise = 0;
+        set_quality(pAdapter, &iwe.u.qual, pAdapter->ScanTab.BssEntry[i].Rssi);
+       current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Encyption key
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWENCODE;
+               if (CAP_IS_PRIVACY_ON (pAdapter->ScanTab.BssEntry[i].CapabilityInfo ))
+                       iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+               else
+                       iwe.u.data.flags = IW_ENCODE_DISABLED;
+
+        previous_ev = current_ev;
+        current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,&iwe, (char *)pAdapter->SharedKey[BSS0][(iwe.u.data.flags & IW_ENCODE_INDEX)-1].Key);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Bit Rate
+               //================================
+               if (pAdapter->ScanTab.BssEntry[i].SupRateLen)
+        {
+            UCHAR tmpRate = pAdapter->ScanTab.BssEntry[i].SupRate[pAdapter->ScanTab.BssEntry[i].SupRateLen-1];
+                       memset(&iwe, 0, sizeof(iwe));
+                       iwe.cmd = SIOCGIWRATE;
+               current_val = current_ev + IW_EV_LCP_LEN;
+            if (tmpRate == 0x82)
+                iwe.u.bitrate.value =  1 * 1000000;
+            else if (tmpRate == 0x84)
+                iwe.u.bitrate.value =  2 * 1000000;
+            else if (tmpRate == 0x8B)
+                iwe.u.bitrate.value =  5.5 * 1000000;
+            else if (tmpRate == 0x96)
+                iwe.u.bitrate.value =  11 * 1000000;
+            else
+                   iwe.u.bitrate.value =  (tmpRate/2) * 1000000;
+
+                       iwe.u.bitrate.disabled = 0;
+                       current_val = IWE_STREAM_ADD_VALUE(info, current_ev,
+                               current_val, end_buf, &iwe,
+                       IW_EV_PARAM_LEN);
+
+               if((current_val-current_ev)>IW_EV_LCP_LEN)
+               current_ev = current_val;
+               else
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+
+#ifdef IWEVGENIE
+               //WPA IE
+               if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0)
+               {
+                       memset(&iwe, 0, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+                       memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].WpaIE.IE[0]),
+                                                  pAdapter->ScanTab.BssEntry[i].WpaIE.IELen);
+                       iwe.cmd = IWEVGENIE;
+                       iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].WpaIE.IELen;
+                       current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom);
+                       if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+               }
+
+               //WPA2 IE
+        if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0)
+        {
+               memset(&iwe, 0, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+                       memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].RsnIE.IE[0]),
+                                                  pAdapter->ScanTab.BssEntry[i].RsnIE.IELen);
+                       iwe.cmd = IWEVGENIE;
+                       iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].RsnIE.IELen;
+                       current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom);
+                       if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+#else
+        //WPA IE
+               //================================
+        if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0)
+        {
+               NdisZeroMemory(&iwe, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+               iwe.cmd = IWEVCUSTOM;
+            iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen * 2) + 7;
+            NdisMoveMemory(custom, "wpa_ie=", 7);
+            for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].WpaIE.IELen; idx++)
+                sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].WpaIE.IE[idx]);
+            previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe,  custom);
+            if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+
+        //WPA2 IE
+        if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0)
+        {
+               NdisZeroMemory(&iwe, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+               iwe.cmd = IWEVCUSTOM;
+            iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen * 2) + 7;
+            NdisMoveMemory(custom, "rsn_ie=", 7);
+                       for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].RsnIE.IELen; idx++)
+                sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].RsnIE.IE[idx]);
+            previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe,  custom);
+            if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+#endif // IWEVGENIE //
+       }
+
+       data->length = current_ev - extra;
+    pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE;
+       DBGPRINT(RT_DEBUG_ERROR ,("===>rt_ioctl_giwscan. %d(%d) BSS returned, data->length = %d\n",i , pAdapter->ScanTab.BssNr, data->length));
+       return 0;
+}
+#endif
+
+int rt_ioctl_siwessid(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *essid)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+    }
+
+       if (data->flags)
+       {
+               PCHAR   pSsidString = NULL;
+
+               // Includes null character.
+               if (data->length > (IW_ESSID_MAX_SIZE + 1))
+                       return -E2BIG;
+
+               pSsidString = (CHAR *) kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG);
+               if (pSsidString)
+               {
+                       NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1);
+                       NdisMoveMemory(pSsidString, essid, data->length);
+                       if (Set_SSID_Proc(pAdapter, pSsidString) == FALSE)
+                               return -EINVAL;
+               }
+               else
+                       return -ENOMEM;
+       }
+       else
+       {
+               // ANY ssid
+               if (Set_SSID_Proc(pAdapter, "") == FALSE)
+                       return -EINVAL;
+    }
+       return 0;
+}
+
+int rt_ioctl_giwessid(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *essid)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       data->flags = 1;
+    if (MONITOR_ON(pAdapter))
+    {
+        data->length  = 0;
+        return 0;
+    }
+
+       if (OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED))
+       {
+               DBGPRINT(RT_DEBUG_TRACE ,("MediaState is connected\n"));
+               data->length = pAdapter->CommonCfg.SsidLen;
+               memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen);
+       }
+#ifdef RT2870
+#ifdef WPA_SUPPLICANT_SUPPORT
+    // Add for RT2870
+    else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+    {
+        data->length = pAdapter->CommonCfg.SsidLen;
+               memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen);
+       }
+#endif // WPA_SUPPLICANT_SUPPORT //
+#endif // RT2870 //
+       else
+       {//the ANY ssid was specified
+               data->length  = 0;
+               DBGPRINT(RT_DEBUG_TRACE ,("MediaState is not connected, ess\n"));
+       }
+
+       return 0;
+
+}
+
+int rt_ioctl_siwnickn(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *nickname)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+        DBGPRINT(RT_DEBUG_TRACE ,("INFO::Network is down!\n"));
+        return -ENETDOWN;
+    }
+
+       if (data->length > IW_ESSID_MAX_SIZE)
+               return -EINVAL;
+
+       memset(pAdapter->nickname, 0, IW_ESSID_MAX_SIZE + 1);
+       memcpy(pAdapter->nickname, nickname, data->length);
+
+
+       return 0;
+}
+
+int rt_ioctl_giwnickn(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *nickname)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       if (data->length > strlen(pAdapter->nickname) + 1)
+               data->length = strlen(pAdapter->nickname) + 1;
+       if (data->length > 0) {
+               memcpy(nickname, pAdapter->nickname, data->length-1);
+               nickname[data->length-1] = '\0';
+       }
+       return 0;
+}
+
+int rt_ioctl_siwrts(struct net_device *dev,
+                      struct iw_request_info *info,
+                      struct iw_param *rts, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       u16 val;
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+        return -ENETDOWN;
+    }
+
+       if (rts->disabled)
+               val = MAX_RTS_THRESHOLD;
+       else if (rts->value < 0 || rts->value > MAX_RTS_THRESHOLD)
+               return -EINVAL;
+       else if (rts->value == 0)
+           val = MAX_RTS_THRESHOLD;
+       else
+               val = rts->value;
+
+       if (val != pAdapter->CommonCfg.RtsThreshold)
+               pAdapter->CommonCfg.RtsThreshold = val;
+
+       return 0;
+}
+
+int rt_ioctl_giwrts(struct net_device *dev,
+                      struct iw_request_info *info,
+                      struct iw_param *rts, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+       rts->value = pAdapter->CommonCfg.RtsThreshold;
+       rts->disabled = (rts->value == MAX_RTS_THRESHOLD);
+       rts->fixed = 1;
+
+       return 0;
+}
+
+int rt_ioctl_siwfrag(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_param *frag, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       u16 val;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       if (frag->disabled)
+               val = MAX_FRAG_THRESHOLD;
+       else if (frag->value >= MIN_FRAG_THRESHOLD || frag->value <= MAX_FRAG_THRESHOLD)
+        val = __cpu_to_le16(frag->value & ~0x1); /* even numbers only */
+       else if (frag->value == 0)
+           val = MAX_FRAG_THRESHOLD;
+       else
+               return -EINVAL;
+
+       pAdapter->CommonCfg.FragmentThreshold = val;
+       return 0;
+}
+
+int rt_ioctl_giwfrag(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_param *frag, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+       frag->value = pAdapter->CommonCfg.FragmentThreshold;
+       frag->disabled = (frag->value == MAX_FRAG_THRESHOLD);
+       frag->fixed = 1;
+
+       return 0;
+}
+
+#define MAX_WEP_KEY_SIZE 13
+#define MIN_WEP_KEY_SIZE 5
+int rt_ioctl_siwencode(struct net_device *dev,
+                         struct iw_request_info *info,
+                         struct iw_point *erq, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       if ((erq->length == 0) &&
+        (erq->flags & IW_ENCODE_DISABLED))
+       {
+               pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled;
+               pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled;
+               pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled;
+        pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+        goto done;
+       }
+       else if ((erq->length == 0) &&
+             (erq->flags & IW_ENCODE_RESTRICTED || erq->flags & IW_ENCODE_OPEN))
+       {
+           //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+               STA_PORT_SECURED(pAdapter);
+               pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled;
+               pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled;
+               pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled;
+        pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+               if (erq->flags & IW_ENCODE_RESTRICTED)
+                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared;
+       else
+                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+        goto done;
+       }
+
+    if (erq->length > 0)
+       {
+               int keyIdx = (erq->flags & IW_ENCODE_INDEX) - 1;
+               /* Check the size of the key */
+               if (erq->length > MAX_WEP_KEY_SIZE) {
+                       return -EINVAL;
+               }
+               /* Check key index */
+               if ((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS))
+        {
+            DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::Wrong keyIdx=%d! Using default key instead (%d)\n",
+                                        keyIdx, pAdapter->StaCfg.DefaultKeyId));
+
+            //Using default key
+                       keyIdx = pAdapter->StaCfg.DefaultKeyId;
+        }
+
+        NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key,  16);
+
+               if (erq->length == MAX_WEP_KEY_SIZE)
+        {
+                       pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE;
+            pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128;
+               }
+               else if (erq->length == MIN_WEP_KEY_SIZE)
+        {
+            pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE;
+            pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64;
+               }
+               else
+                       /* Disable the key */
+                       pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0;
+
+               /* Check if the key is not marked as invalid */
+               if(!(erq->flags & IW_ENCODE_NOKEY)) {
+                       /* Copy the key in the driver */
+                       NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, extra, erq->length);
+        }
+       }
+    else
+                       {
+               /* Do we want to just set the transmit key index ? */
+               int index = (erq->flags & IW_ENCODE_INDEX) - 1;
+               if ((index >= 0) && (index < 4))
+        {
+                       pAdapter->StaCfg.DefaultKeyId = index;
+            }
+        else
+                       /* Don't complain if only change the mode */
+                       if(!erq->flags & IW_ENCODE_MODE) {
+                               return -EINVAL;
+               }
+       }
+
+done:
+    DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::erq->flags=%x\n",erq->flags));
+       DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::AuthMode=%x\n",pAdapter->StaCfg.AuthMode));
+       DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::DefaultKeyId=%x, KeyLen = %d\n",pAdapter->StaCfg.DefaultKeyId , pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen));
+       DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::WepStatus=%x\n",pAdapter->StaCfg.WepStatus));
+       return 0;
+}
+
+int
+rt_ioctl_giwencode(struct net_device *dev,
+                         struct iw_request_info *info,
+                         struct iw_point *erq, char *key)
+{
+       int kid;
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+       kid = erq->flags & IW_ENCODE_INDEX;
+       DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_giwencode %d\n", erq->flags & IW_ENCODE_INDEX));
+
+       if (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled)
+       {
+               erq->length = 0;
+               erq->flags = IW_ENCODE_DISABLED;
+       }
+       else if ((kid > 0) && (kid <=4))
+       {
+               // copy wep key
+               erq->flags = kid ;                      /* NB: base 1 */
+               if (erq->length > pAdapter->SharedKey[BSS0][kid-1].KeyLen)
+                       erq->length = pAdapter->SharedKey[BSS0][kid-1].KeyLen;
+               memcpy(key, pAdapter->SharedKey[BSS0][kid-1].Key, erq->length);
+               //if ((kid == pAdapter->PortCfg.DefaultKeyId))
+               //erq->flags |= IW_ENCODE_ENABLED;      /* XXX */
+               if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared)
+                       erq->flags |= IW_ENCODE_RESTRICTED;             /* XXX */
+               else
+                       erq->flags |= IW_ENCODE_OPEN;           /* XXX */
+
+       }
+       else if (kid == 0)
+       {
+               if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared)
+                       erq->flags |= IW_ENCODE_RESTRICTED;             /* XXX */
+               else
+                       erq->flags |= IW_ENCODE_OPEN;           /* XXX */
+               erq->length = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen;
+               memcpy(key, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, erq->length);
+               // copy default key ID
+               if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared)
+                       erq->flags |= IW_ENCODE_RESTRICTED;             /* XXX */
+               else
+                       erq->flags |= IW_ENCODE_OPEN;           /* XXX */
+               erq->flags = pAdapter->StaCfg.DefaultKeyId + 1;                 /* NB: base 1 */
+               erq->flags |= IW_ENCODE_ENABLED;        /* XXX */
+       }
+
+       return 0;
+
+}
+
+static int
+rt_ioctl_setparam(struct net_device *dev, struct iw_request_info *info,
+                        void *w, char *extra)
+{
+    VIRTUAL_ADAPTER    *pVirtualAd = NULL;
+       PRTMP_ADAPTER pAdapter;
+       POS_COOKIE pObj;
+       char *this_char = extra;
+       char *value;
+       int  Status=0;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+       pObj = (POS_COOKIE) pAdapter->OS_Cookie;
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       {
+               pObj->ioctl_if_type = INT_MAIN;
+        pObj->ioctl_if = MAIN_MBSSID;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+                       return -ENETDOWN;
+       }
+
+       if (!*this_char)
+               return -EINVAL;
+
+       if ((value = rtstrchr(this_char, '=')) != NULL)
+           *value++ = 0;
+
+       if (!value)
+           return -EINVAL;
+
+       // reject setting nothing besides ANY ssid(ssidLen=0)
+    if (!*value && (strcmp(this_char, "SSID") != 0))
+        return -EINVAL;
+
+       for (PRTMP_PRIVATE_SET_PROC = RTMP_PRIVATE_SUPPORT_PROC; PRTMP_PRIVATE_SET_PROC->name; PRTMP_PRIVATE_SET_PROC++)
+       {
+           if (strcmp(this_char, PRTMP_PRIVATE_SET_PROC->name) == 0)
+           {
+               if(!PRTMP_PRIVATE_SET_PROC->set_proc(pAdapter, value))
+               {       //FALSE:Set private failed then return Invalid argument
+                           Status = -EINVAL;
+               }
+                   break;      //Exit for loop.
+           }
+       }
+
+       if(PRTMP_PRIVATE_SET_PROC->name == NULL)
+       {  //Not found argument
+           Status = -EINVAL;
+           DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_setparam:: (iwpriv) Not Support Set Command [%s=%s]\n", this_char, value));
+       }
+
+    return Status;
+}
+
+
+static int
+rt_private_get_statistics(struct net_device *dev, struct iw_request_info *info,
+               struct iw_point *wrq, char *extra)
+{
+       INT                             Status = 0;
+    PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+
+    if (extra == NULL)
+    {
+        wrq->length = 0;
+        return -EIO;
+    }
+
+    memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+    sprintf(extra, "\n\n");
+
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+       {
+           sprintf(extra+strlen(extra), "Tx success                      = %ld\n", (ULONG)pAd->ate.TxDoneCount);
+           //sprintf(extra+strlen(extra), "Tx success without retry        = %ld\n", (ULONG)pAd->ate.TxDoneCount);
+       }
+       else
+#endif // RALINK_ATE //
+       {
+    sprintf(extra+strlen(extra), "Tx success                      = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart);
+    sprintf(extra+strlen(extra), "Tx success without retry        = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart - (ULONG)pAd->WlanCounters.RetryCount.QuadPart);
+       }
+    sprintf(extra+strlen(extra), "Tx success after retry          = %ld\n", (ULONG)pAd->WlanCounters.RetryCount.QuadPart);
+    sprintf(extra+strlen(extra), "Tx fail to Rcv ACK after retry  = %ld\n", (ULONG)pAd->WlanCounters.FailedCount.QuadPart);
+    sprintf(extra+strlen(extra), "RTS Success Rcv CTS             = %ld\n", (ULONG)pAd->WlanCounters.RTSSuccessCount.QuadPart);
+    sprintf(extra+strlen(extra), "RTS Fail Rcv CTS                = %ld\n", (ULONG)pAd->WlanCounters.RTSFailureCount.QuadPart);
+
+    sprintf(extra+strlen(extra), "Rx success                      = %ld\n", (ULONG)pAd->WlanCounters.ReceivedFragmentCount.QuadPart);
+    sprintf(extra+strlen(extra), "Rx with CRC                     = %ld\n", (ULONG)pAd->WlanCounters.FCSErrorCount.QuadPart);
+    sprintf(extra+strlen(extra), "Rx drop due to out of resource  = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer);
+    sprintf(extra+strlen(extra), "Rx duplicate frame              = %ld\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.QuadPart);
+
+    sprintf(extra+strlen(extra), "False CCA (one second)          = %ld\n", (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt);
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+       {
+               if (pAd->ate.RxAntennaSel == 0)
+               {
+               sprintf(extra+strlen(extra), "RSSI-A                          = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta));
+                       sprintf(extra+strlen(extra), "RSSI-B (if available)           = %ld\n", (LONG)(pAd->ate.LastRssi1 - pAd->BbpRssiToDbmDelta));
+                       sprintf(extra+strlen(extra), "RSSI-C (if available)           = %ld\n\n", (LONG)(pAd->ate.LastRssi2 - pAd->BbpRssiToDbmDelta));
+               }
+               else
+               {
+               sprintf(extra+strlen(extra), "RSSI                            = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta));
+               }
+       }
+       else
+#endif // RALINK_ATE //
+       {
+       sprintf(extra+strlen(extra), "RSSI-A                          = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta));
+        sprintf(extra+strlen(extra), "RSSI-B (if available)           = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi1 - pAd->BbpRssiToDbmDelta));
+        sprintf(extra+strlen(extra), "RSSI-C (if available)           = %ld\n\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi2 - pAd->BbpRssiToDbmDelta));
+       }
+#ifdef WPA_SUPPLICANT_SUPPORT
+    sprintf(extra+strlen(extra), "WpaSupplicantUP                 = %d\n\n", pAd->StaCfg.WpaSupplicantUP);
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+
+    wrq->length = strlen(extra) + 1; // 1: size of '\0'
+    DBGPRINT(RT_DEBUG_TRACE, ("<== rt_private_get_statistics, wrq->length = %d\n", wrq->length));
+
+    return Status;
+}
+
+#ifdef DOT11_N_SUPPORT
+void   getBaInfo(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pOutBuf)
+{
+       INT i, j;
+       BA_ORI_ENTRY *pOriBAEntry;
+       BA_REC_ENTRY *pRecBAEntry;
+
+       for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+               if (((pEntry->ValidAsCLI || pEntry->ValidAsApCli) && (pEntry->Sst == SST_ASSOC))
+                       || (pEntry->ValidAsWDS) || (pEntry->ValidAsMesh))
+               {
+                       sprintf(pOutBuf, "%s\n%02X:%02X:%02X:%02X:%02X:%02X (Aid = %d) (AP) -\n",
+                pOutBuf,
+                               pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+                               pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5], pEntry->Aid);
+
+                       sprintf(pOutBuf, "%s[Recipient]\n", pOutBuf);
+                       for (j=0; j < NUM_OF_TID; j++)
+                       {
+                               if (pEntry->BARecWcidArray[j] != 0)
+                               {
+                                       pRecBAEntry =&pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]];
+                                       sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, LastIndSeq=%d, ReorderingPkts=%d\n", pOutBuf, j, pRecBAEntry->BAWinSize, pRecBAEntry->LastIndSeq, pRecBAEntry->list.qlen);
+                               }
+                       }
+                       sprintf(pOutBuf, "%s\n", pOutBuf);
+
+                       sprintf(pOutBuf, "%s[Originator]\n", pOutBuf);
+                       for (j=0; j < NUM_OF_TID; j++)
+                       {
+                               if (pEntry->BAOriWcidArray[j] != 0)
+                               {
+                                       pOriBAEntry =&pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]];
+                                       sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, StartSeq=%d, CurTxSeq=%d\n", pOutBuf, j, pOriBAEntry->BAWinSize, pOriBAEntry->Sequence, pEntry->TxSeq[j]);
+                               }
+                       }
+                       sprintf(pOutBuf, "%s\n\n", pOutBuf);
+               }
+        if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30))
+                break;
+       }
+
+       return;
+}
+#endif // DOT11_N_SUPPORT //
+
+static int
+rt_private_show(struct net_device *dev, struct iw_request_info *info,
+               struct iw_point *wrq, char *extra)
+{
+    INT                                Status = 0;
+    VIRTUAL_ADAPTER    *pVirtualAd = NULL;
+    PRTMP_ADAPTER   pAd;
+       POS_COOKIE              pObj;
+    u32             subcmd = wrq->flags;
+
+       if (dev->priv_flags == INT_MAIN)
+               pAd = dev->priv;
+       else
+       {
+               pVirtualAd = dev->priv;
+               pAd = pVirtualAd->RtmpDev->priv;
+       }
+       pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+       if (pAd == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+    if (extra == NULL)
+    {
+        wrq->length = 0;
+        return -EIO;
+    }
+    memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+
+       {
+               pObj->ioctl_if_type = INT_MAIN;
+        pObj->ioctl_if = MAIN_MBSSID;
+       }
+
+    switch(subcmd)
+    {
+
+        case SHOW_CONN_STATUS:
+            if (MONITOR_ON(pAd))
+            {
+#ifdef DOT11_N_SUPPORT
+                if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED &&
+                    pAd->CommonCfg.RegTransmitSetting.field.BW)
+                    sprintf(extra, "Monitor Mode(CentralChannel %d)\n", pAd->CommonCfg.CentralChannel);
+                else
+#endif // DOT11_N_SUPPORT //
+                    sprintf(extra, "Monitor Mode(Channel %d)\n", pAd->CommonCfg.Channel);
+            }
+            else
+            {
+                if (pAd->IndicateMediaState == NdisMediaStateConnected)
+               {
+                   if (INFRA_ON(pAd))
+                    {
+                    sprintf(extra, "Connected(AP: %s[%02X:%02X:%02X:%02X:%02X:%02X])\n",
+                                    pAd->CommonCfg.Ssid,
+                                    pAd->CommonCfg.Bssid[0],
+                                    pAd->CommonCfg.Bssid[1],
+                                    pAd->CommonCfg.Bssid[2],
+                                    pAd->CommonCfg.Bssid[3],
+                                    pAd->CommonCfg.Bssid[4],
+                                    pAd->CommonCfg.Bssid[5]);
+                       DBGPRINT(RT_DEBUG_TRACE ,("Ssid=%s ,Ssidlen = %d\n",pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen));
+               }
+                    else if (ADHOC_ON(pAd))
+                        sprintf(extra, "Connected\n");
+               }
+               else
+               {
+                   sprintf(extra, "Disconnected\n");
+                       DBGPRINT(RT_DEBUG_TRACE ,("ConnStatus is not connected\n"));
+               }
+            }
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+        case SHOW_DRVIER_VERION:
+            sprintf(extra, "Driver version-%s, %s %s\n", STA_DRIVER_VERSION, __DATE__, __TIME__ );
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+#ifdef DOT11_N_SUPPORT
+        case SHOW_BA_INFO:
+            getBaInfo(pAd, extra);
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+#endif // DOT11_N_SUPPORT //
+               case SHOW_DESC_INFO:
+                       {
+                               Show_DescInfo_Proc(pAd, NULL);
+                               wrq->length = 0; // 1: size of '\0'
+                       }
+                       break;
+        case RAIO_OFF:
+            if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+            {
+                sprintf(extra, "Scanning\n");
+                wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                break;
+            }
+            pAd->StaCfg.bSwRadio = FALSE;
+            if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
+            {
+                pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
+                if (pAd->StaCfg.bRadio == FALSE)
+                {
+                    MlmeRadioOff(pAd);
+                    // Update extra information
+                                       pAd->ExtraInfo = SW_RADIO_OFF;
+                }
+            }
+            sprintf(extra, "Radio Off\n");
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+        case RAIO_ON:
+            if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+            {
+                sprintf(extra, "Scanning\n");
+                wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                break;
+            }
+            pAd->StaCfg.bSwRadio = TRUE;
+            //if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
+            {
+                pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
+                if (pAd->StaCfg.bRadio == TRUE)
+                {
+                    MlmeRadioOn(pAd);
+                    // Update extra information
+                                       pAd->ExtraInfo = EXTRA_INFO_CLEAR;
+                }
+            }
+            sprintf(extra, "Radio On\n");
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+
+
+#ifdef QOS_DLS_SUPPORT
+               case SHOW_DLS_ENTRY_INFO:
+                       {
+                               Set_DlsEntryInfo_Display_Proc(pAd, NULL);
+                               wrq->length = 0; // 1: size of '\0'
+                       }
+                       break;
+#endif // QOS_DLS_SUPPORT //
+
+               case SHOW_CFG_VALUE:
+                       {
+                               Status = RTMPShowCfgValue(pAd, wrq->pointer, extra);
+                               if (Status == 0)
+                                       wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                       }
+                       break;
+               case SHOW_ADHOC_ENTRY_INFO:
+                       Show_Adhoc_MacTable_Proc(pAd, extra);
+                       wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                       break;
+        default:
+            DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow subcmd = %d\n", __FUNCTION__, subcmd));
+            break;
+    }
+
+    return Status;
+}
+
+#ifdef SIOCSIWMLME
+int rt_ioctl_siwmlme(struct net_device *dev,
+                          struct iw_request_info *info,
+                          union iwreq_data *wrqu,
+                          char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+       struct iw_mlme *pMlme = (struct iw_mlme *)wrqu->data.pointer;
+       MLME_QUEUE_ELEM                         MsgElem;
+       MLME_DISASSOC_REQ_STRUCT        DisAssocReq;
+       MLME_DEAUTH_REQ_STRUCT      DeAuthReq;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__));
+
+       if (pMlme == NULL)
+               return -EINVAL;
+
+       switch(pMlme->cmd)
+       {
+#ifdef IW_MLME_DEAUTH
+               case IW_MLME_DEAUTH:
+                       DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DEAUTH\n", __FUNCTION__));
+                       COPY_MAC_ADDR(DeAuthReq.Addr, pAd->CommonCfg.Bssid);
+                       DeAuthReq.Reason = pMlme->reason_code;
+                       MsgElem.MsgLen = sizeof(MLME_DEAUTH_REQ_STRUCT);
+                       NdisMoveMemory(MsgElem.Msg, &DeAuthReq, sizeof(MLME_DEAUTH_REQ_STRUCT));
+                       MlmeDeauthReqAction(pAd, &MsgElem);
+                       if (INFRA_ON(pAd))
+                       {
+                           LinkDown(pAd, FALSE);
+                           pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+                       }
+                       break;
+#endif // IW_MLME_DEAUTH //
+#ifdef IW_MLME_DISASSOC
+               case IW_MLME_DISASSOC:
+                       DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DISASSOC\n", __FUNCTION__));
+                       COPY_MAC_ADDR(DisAssocReq.Addr, pAd->CommonCfg.Bssid);
+                       DisAssocReq.Reason =  pMlme->reason_code;
+
+                       MsgElem.Machine = ASSOC_STATE_MACHINE;
+                       MsgElem.MsgType = MT2_MLME_DISASSOC_REQ;
+                       MsgElem.MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT);
+                       NdisMoveMemory(MsgElem.Msg, &DisAssocReq, sizeof(MLME_DISASSOC_REQ_STRUCT));
+
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC;
+                       MlmeDisassocReqAction(pAd, &MsgElem);
+                       break;
+#endif // IW_MLME_DISASSOC //
+               default:
+                       DBGPRINT(RT_DEBUG_TRACE, ("====> %s - Unknow Command\n", __FUNCTION__));
+                       break;
+       }
+
+       return 0;
+}
+#endif // SIOCSIWMLME //
+
+#if WIRELESS_EXT > 17
+int rt_ioctl_siwauth(struct net_device *dev,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = (PRTMP_ADAPTER) dev->priv;
+       struct iw_param *param = &wrqu->param;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_WPA_VERSION:
+            if (param->value == IW_AUTH_WPA_VERSION_WPA)
+            {
+                pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK;
+                               if (pAdapter->StaCfg.BssType == BSS_ADHOC)
+                                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone;
+            }
+            else if (param->value == IW_AUTH_WPA_VERSION_WPA2)
+                pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK;
+
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_CIPHER_PAIRWISE:
+            if (param->value == IW_AUTH_CIPHER_NONE)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_WEP40 ||
+                     param->value == IW_AUTH_CIPHER_WEP104)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled;
+#ifdef WPA_SUPPLICANT_SUPPORT
+                pAdapter->StaCfg.IEEE8021X = FALSE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+            }
+            else if (param->value == IW_AUTH_CIPHER_TKIP)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11Encryption2Enabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_CCMP)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11Encryption3Enabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11Encryption3Enabled;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_PAIRWISE - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_CIPHER_GROUP:
+            if (param->value == IW_AUTH_CIPHER_NONE)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_WEP40 ||
+                     param->value == IW_AUTH_CIPHER_WEP104)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_TKIP)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_CCMP)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_GROUP - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_KEY_MGMT:
+            if (param->value == IW_AUTH_KEY_MGMT_802_1X)
+            {
+                if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
+                {
+                    pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA;
+#ifdef WPA_SUPPLICANT_SUPPORT
+                    pAdapter->StaCfg.IEEE8021X = FALSE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+                }
+                else if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+                {
+                    pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2;
+#ifdef WPA_SUPPLICANT_SUPPORT
+                    pAdapter->StaCfg.IEEE8021X = FALSE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+                }
+#ifdef WPA_SUPPLICANT_SUPPORT
+                else
+                    // WEP 1x
+                    pAdapter->StaCfg.IEEE8021X = TRUE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+            }
+            else if (param->value == 0)
+            {
+                //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               STA_PORT_SECURED(pAdapter);
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_KEY_MGMT - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+            break;
+       case IW_AUTH_PRIVACY_INVOKED:
+            /*if (param->value == 0)
+                       {
+                pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+                pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled;
+                   pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled;
+            }*/
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_PRIVACY_INVOKED - param->value = %d!\n", __FUNCTION__, param->value));
+               break;
+       case IW_AUTH_DROP_UNENCRYPTED:
+            if (param->value != 0)
+                pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                       else
+                       {
+                //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               STA_PORT_SECURED(pAdapter);
+                       }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value));
+               break;
+       case IW_AUTH_80211_AUTH_ALG:
+                       if (param->value & IW_AUTH_ALG_SHARED_KEY)
+            {
+                               pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared;
+                       }
+            else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
+            {
+                               pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+                       }
+            else
+                               return -EINVAL;
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_80211_AUTH_ALG - param->value = %d!\n", __FUNCTION__, param->value));
+                       break;
+       case IW_AUTH_WPA_ENABLED:
+               DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_ENABLED - Driver supports WPA!(param->value = %d)\n", __FUNCTION__, param->value));
+               break;
+       default:
+               return -EOPNOTSUPP;
+}
+
+       return 0;
+}
+
+int rt_ioctl_giwauth(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = (PRTMP_ADAPTER) dev->priv;
+       struct iw_param *param = &wrqu->param;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+    }
+
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_DROP_UNENCRYPTED:
+        param->value = (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) ? 0 : 1;
+               break;
+
+       case IW_AUTH_80211_AUTH_ALG:
+        param->value = (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) ? IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM;
+               break;
+
+       case IW_AUTH_WPA_ENABLED:
+               param->value = (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) ? 1 : 0;
+               break;
+
+       default:
+               return -EOPNOTSUPP;
+       }
+    DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_giwauth::param->value = %d!\n", param->value));
+       return 0;
+}
+
+void fnSetCipherKey(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  INT             keyIdx,
+    IN  UCHAR           CipherAlg,
+    IN  BOOLEAN         bGTK,
+    IN  struct iw_encode_ext *ext)
+{
+    NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY));
+    pAdapter->SharedKey[BSS0][keyIdx].KeyLen = LEN_TKIP_EK;
+    NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, LEN_TKIP_EK);
+    NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].TxMic, ext->key + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+    NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].RxMic, ext->key + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+    pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CipherAlg;
+
+    // Update group key information to ASIC Shared Key Table
+       AsicAddSharedKeyEntry(pAdapter,
+                                                 BSS0,
+                                                 keyIdx,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].CipherAlg,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].Key,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].TxMic,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].RxMic);
+
+    if (bGTK)
+        // Update ASIC WCID attribute table and IVEIV table
+       RTMPAddWcidAttributeEntry(pAdapter,
+                                                         BSS0,
+                                                         keyIdx,
+                                                         pAdapter->SharedKey[BSS0][keyIdx].CipherAlg,
+                                                         NULL);
+    else
+        // Update ASIC WCID attribute table and IVEIV table
+       RTMPAddWcidAttributeEntry(pAdapter,
+                                                         BSS0,
+                                                         keyIdx,
+                                                         pAdapter->SharedKey[BSS0][keyIdx].CipherAlg,
+                                                         &pAdapter->MacTab.Content[BSSID_WCID]);
+}
+
+int rt_ioctl_siwencodeext(struct net_device *dev,
+                          struct iw_request_info *info,
+                          union iwreq_data *wrqu,
+                          char *extra)
+                       {
+    PRTMP_ADAPTER   pAdapter = (PRTMP_ADAPTER) dev->priv;
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+    int keyIdx, alg = ext->alg;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+    if (encoding->flags & IW_ENCODE_DISABLED)
+       {
+        keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1;
+        // set BSSID wcid entry of the Pair-wise Key table as no-security mode
+           AsicRemovePairwiseKeyEntry(pAdapter, BSS0, BSSID_WCID);
+        pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0;
+               pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_NONE;
+               AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)keyIdx);
+        NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY));
+        DBGPRINT(RT_DEBUG_TRACE, ("%s::Remove all keys!(encoding->flags = %x)\n", __FUNCTION__, encoding->flags));
+    }
+                                       else
+    {
+        // Get Key Index and convet to our own defined key index
+       keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1;
+       if((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS))
+               return -EINVAL;
+
+        if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+        {
+            pAdapter->StaCfg.DefaultKeyId = keyIdx;
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::DefaultKeyId = %d\n", __FUNCTION__, pAdapter->StaCfg.DefaultKeyId));
+        }
+
+        switch (alg) {
+               case IW_ENCODE_ALG_NONE:
+                DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_NONE\n", __FUNCTION__));
+                       break;
+               case IW_ENCODE_ALG_WEP:
+                DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_WEP - ext->key_len = %d, keyIdx = %d\n", __FUNCTION__, ext->key_len, keyIdx));
+                       if (ext->key_len == MAX_WEP_KEY_SIZE)
+                {
+                               pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE;
+                    pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128;
+                               }
+                       else if (ext->key_len == MIN_WEP_KEY_SIZE)
+                {
+                    pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE;
+                    pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64;
+                               }
+                       else
+                    return -EINVAL;
+
+                NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key,  16);
+                           NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, ext->key_len);
+
+                               if (pAdapter->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled ||
+                                       pAdapter->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
+                               {
+                                       // Set Group key material to Asic
+                                       AsicAddSharedKeyEntry(pAdapter, BSS0, keyIdx, pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, pAdapter->SharedKey[BSS0][keyIdx].Key, NULL, NULL);
+
+                                       // Update WCID attribute table and IVEIV table for this group key table
+                                       RTMPAddWcidAttributeEntry(pAdapter, BSS0, keyIdx, pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, NULL);
+
+                                       STA_PORT_SECURED(pAdapter);
+
+                               // Indicate Connected for GUI
+                               pAdapter->IndicateMediaState = NdisMediaStateConnected;
+                               }
+                       break;
+            case IW_ENCODE_ALG_TKIP:
+                DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_TKIP - keyIdx = %d, ext->key_len = %d\n", __FUNCTION__, keyIdx, ext->key_len));
+                if (ext->key_len == 32)
+                {
+                    if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+                    {
+                        fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, FALSE, ext);
+                        if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2)
+                        {
+                            //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                            STA_PORT_SECURED(pAdapter);
+                        }
+               }
+                    else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+                    {
+                        fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, TRUE, ext);
+
+                        // set 802.1x port control
+                       //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAdapter);
+                    }
+                }
+                else
+                    return -EINVAL;
+                break;
+            case IW_ENCODE_ALG_CCMP:
+                if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+               {
+                    fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, FALSE, ext);
+                    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2)
+                       //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAdapter);
+                }
+                else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+                {
+                    fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, TRUE, ext);
+
+                    // set 802.1x port control
+                       //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAdapter);
+                }
+                break;
+               default:
+                       return -EINVAL;
+               }
+    }
+
+    return 0;
+}
+
+int
+rt_ioctl_giwencodeext(struct net_device *dev,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) dev->priv;
+       PCHAR pKey = NULL;
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+       int idx, max_key_len;
+
+       DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_giwencodeext\n"));
+
+       max_key_len = encoding->length - sizeof(*ext);
+       if (max_key_len < 0)
+               return -EINVAL;
+
+       idx = encoding->flags & IW_ENCODE_INDEX;
+       if (idx)
+       {
+               if (idx < 1 || idx > 4)
+                       return -EINVAL;
+               idx--;
+
+               if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
+                       (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled))
+               {
+                       if (idx != pAd->StaCfg.DefaultKeyId)
+                       {
+                               ext->key_len = 0;
+                               return 0;
+                       }
+               }
+       }
+       else
+               idx = pAd->StaCfg.DefaultKeyId;
+
+       encoding->flags = idx + 1;
+       memset(ext, 0, sizeof(*ext));
+
+       ext->key_len = 0;
+       switch(pAd->StaCfg.WepStatus) {
+               case Ndis802_11WEPDisabled:
+                       ext->alg = IW_ENCODE_ALG_NONE;
+                       encoding->flags |= IW_ENCODE_DISABLED;
+                       break;
+               case Ndis802_11WEPEnabled:
+                       ext->alg = IW_ENCODE_ALG_WEP;
+                       if (pAd->SharedKey[BSS0][idx].KeyLen > max_key_len)
+                               return -E2BIG;
+                       else
+                       {
+                               ext->key_len = pAd->SharedKey[BSS0][idx].KeyLen;
+                               pKey = &(pAd->SharedKey[BSS0][idx].Key[0]);
+                       }
+                       break;
+               case Ndis802_11Encryption2Enabled:
+               case Ndis802_11Encryption3Enabled:
+                       if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)
+                               ext->alg = IW_ENCODE_ALG_TKIP;
+                       else
+                               ext->alg = IW_ENCODE_ALG_CCMP;
+
+                       if (max_key_len < 32)
+                               return -E2BIG;
+                       else
+                       {
+                               ext->key_len = 32;
+                               pKey = &pAd->StaCfg.PMK[0];
+                       }
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       if (ext->key_len && pKey)
+       {
+               encoding->flags |= IW_ENCODE_ENABLED;
+               memcpy(ext->key, pKey, ext->key_len);
+       }
+
+       return 0;
+}
+
+#ifdef SIOCSIWGENIE
+int rt_ioctl_siwgenie(struct net_device *dev,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+
+       if (wrqu->data.length > MAX_LEN_OF_RSNIE ||
+           (wrqu->data.length && extra == NULL))
+               return -EINVAL;
+
+       if (wrqu->data.length)
+       {
+               pAd->StaCfg.RSNIE_Len = wrqu->data.length;
+               NdisMoveMemory(&pAd->StaCfg.RSN_IE[0], extra, pAd->StaCfg.RSNIE_Len);
+       }
+       else
+       {
+               pAd->StaCfg.RSNIE_Len = 0;
+               NdisZeroMemory(&pAd->StaCfg.RSN_IE[0], MAX_LEN_OF_RSNIE);
+       }
+
+       return 0;
+}
+#endif // SIOCSIWGENIE //
+
+int rt_ioctl_giwgenie(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+
+       if ((pAd->StaCfg.RSNIE_Len == 0) ||
+               (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA))
+       {
+               wrqu->data.length = 0;
+               return 0;
+       }
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+#ifdef SIOCSIWGENIE
+       if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE)
+       {
+       if (wrqu->data.length < pAd->StaCfg.RSNIE_Len)
+               return -E2BIG;
+
+       wrqu->data.length = pAd->StaCfg.RSNIE_Len;
+       memcpy(extra, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len);
+       }
+       else
+#endif // SIOCSIWGENIE //
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+       {
+               UCHAR RSNIe = IE_WPA;
+
+               if (wrqu->data.length < (pAd->StaCfg.RSNIE_Len + 2)) // ID, Len
+                       return -E2BIG;
+               wrqu->data.length = pAd->StaCfg.RSNIE_Len + 2;
+
+               if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
+            (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2))
+                       RSNIe = IE_RSN;
+
+               extra[0] = (char)RSNIe;
+               extra[1] = pAd->StaCfg.RSNIE_Len;
+               memcpy(extra+2, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len);
+       }
+
+       return 0;
+}
+
+int rt_ioctl_siwpmksa(struct net_device *dev,
+                          struct iw_request_info *info,
+                          union iwreq_data *wrqu,
+                          char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+       struct iw_pmksa *pPmksa = (struct iw_pmksa *)wrqu->data.pointer;
+       INT     CachedIdx = 0, idx = 0;
+
+       if (pPmksa == NULL)
+               return -EINVAL;
+
+       DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_siwpmksa\n"));
+       switch(pPmksa->cmd)
+       {
+               case IW_PMKSA_FLUSH:
+                       NdisZeroMemory(pAd->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO);
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_FLUSH\n"));
+                       break;
+               case IW_PMKSA_REMOVE:
+                       for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++)
+                       {
+                       // compare the BSSID
+                       if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN))
+                       {
+                               NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN);
+                                       NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].PMKID, 16);
+                                       for (idx = CachedIdx; idx < (pAd->StaCfg.SavedPMKNum - 1); idx++)
+                                       {
+                                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].BSSID[0], &pAd->StaCfg.SavedPMK[idx+1].BSSID[0], MAC_ADDR_LEN);
+                                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].PMKID[0], &pAd->StaCfg.SavedPMK[idx+1].PMKID[0], 16);
+                                       }
+                                       pAd->StaCfg.SavedPMKNum--;
+                               break;
+                       }
+               }
+
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_REMOVE\n"));
+                       break;
+               case IW_PMKSA_ADD:
+                       for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++)
+                       {
+                       // compare the BSSID
+                       if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN))
+                               break;
+               }
+
+               // Found, replace it
+               if (CachedIdx < PMKID_NO)
+               {
+                       DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx));
+                       NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN);
+                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16);
+                       pAd->StaCfg.SavedPMKNum++;
+               }
+               // Not found, replace the last one
+               else
+               {
+                       // Randomly replace one
+                       CachedIdx = (pPmksa->bssid.sa_data[5] % PMKID_NO);
+                       DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx));
+                       NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN);
+                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16);
+               }
+
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_ADD\n"));
+                       break;
+               default:
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - Unknow Command!!\n"));
+                       break;
+       }
+
+       return 0;
+}
+#endif // #if WIRELESS_EXT > 17
+
+#ifdef DBG
+static int
+rt_private_ioctl_bbp(struct net_device *dev, struct iw_request_info *info,
+               struct iw_point *wrq, char *extra)
+                       {
+       CHAR                            *this_char;
+       CHAR                            *value = NULL;
+       UCHAR                           regBBP = 0;
+//     CHAR                            arg[255]={0};
+       UINT32                          bbpId;
+       UINT32                          bbpValue;
+       BOOLEAN                         bIsPrintAllBBP = FALSE;
+       INT                                     Status = 0;
+    PRTMP_ADAPTER       pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+
+       memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+
+       if (wrq->length > 1) //No parameters.
+                               {
+               sprintf(extra, "\n");
+
+               //Parsing Read or Write
+               this_char = wrq->pointer;
+               DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s\n", this_char));
+               if (!*this_char)
+                       goto next;
+
+               if ((value = rtstrchr(this_char, '=')) != NULL)
+                       *value++ = 0;
+
+               if (!value || !*value)
+               { //Read
+                       DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s, value=%s\n", this_char, value));
+                       if (sscanf(this_char, "%d", &(bbpId)) == 1)
+                       {
+                               if (bbpId <= 136)
+                               {
+#ifdef RALINK_ATE
+                                       if (ATE_ON(pAdapter))
+                                       {
+                                               ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                                       }
+                                       else
+#endif // RALINK_ATE //
+                                       {
+                                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                                       }
+                                       sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId*2, regBBP);
+                    wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                                       DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra));
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       bIsPrintAllBBP = TRUE;
+                                       goto next;
+                               }
+                       }
+                       else
+                       { //Invalid parametes, so default printk all bbp
+                               bIsPrintAllBBP = TRUE;
+                               goto next;
+                       }
+               }
+               else
+               { //Write
+                       if ((sscanf(this_char, "%d", &(bbpId)) == 1) && (sscanf(value, "%x", &(bbpValue)) == 1))
+                       {
+                               if (bbpId <= 136)
+                               {
+#ifdef RALINK_ATE
+                                       if (ATE_ON(pAdapter))
+                                       {
+                                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue);
+                                               //Read it back for showing
+                                               ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                                       }
+                                       else
+#endif // RALINK_ATE //
+                                       {
+                                           RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue);
+                                       //Read it back for showing
+                                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                       }
+                                       sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId*2, regBBP);
+                    wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                                       DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra));
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       bIsPrintAllBBP = TRUE;
+                                       goto next;
+                               }
+                       }
+                       else
+                       { //Invalid parametes, so default printk all bbp
+                               bIsPrintAllBBP = TRUE;
+                               goto next;
+                       }
+               }
+               }
+       else
+               bIsPrintAllBBP = TRUE;
+
+next:
+       if (bIsPrintAllBBP)
+       {
+               memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+               sprintf(extra, "\n");
+               for (bbpId = 0; bbpId <= 136; bbpId++)
+               {
+                   if (strlen(extra) >= (IW_PRIV_SIZE_MASK - 10))
+                break;
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                       }
+                       else
+#endif // RALINK_ATE //
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                       sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X    ", bbpId, bbpId*2, regBBP);
+                       if (bbpId%5 == 4)
+                               sprintf(extra+strlen(extra), "\n");
+               }
+
+        wrq->length = strlen(extra) + 1; // 1: size of '\0'
+        DBGPRINT(RT_DEBUG_TRACE, ("wrq->length = %d\n", wrq->length));
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<==rt_private_ioctl_bbp\n\n"));
+
+    return Status;
+}
+#endif // DBG //
+
+int rt_ioctl_siwrate(struct net_device *dev,
+                       struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
+{
+    PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+    UINT32          rate = wrqu->bitrate.value, fixed = wrqu->bitrate.fixed;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+    DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(rate = %d, fixed = %d)\n", rate, fixed));
+    /* rate = -1 => auto rate
+       rate = X, fixed = 1 => (fixed rate X)
+    */
+    if (rate == -1)
+    {
+               //Auto Rate
+               pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+               pAd->StaCfg.bAutoTxRateSwitch = TRUE;
+               if ((pAd->CommonCfg.PhyMode <= PHY_11G) ||
+                   (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))
+                       RTMPSetDesiredRates(pAd, -1);
+
+#ifdef DOT11_N_SUPPORT
+               SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+    }
+    else
+    {
+        if (fixed)
+        {
+               pAd->StaCfg.bAutoTxRateSwitch = FALSE;
+            if ((pAd->CommonCfg.PhyMode <= PHY_11G) ||
+                (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))
+                RTMPSetDesiredRates(pAd, rate);
+            else
+            {
+                pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+#ifdef DOT11_N_SUPPORT
+                SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(HtMcs=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.MCS));
+        }
+        else
+        {
+            // TODO: rate = X, fixed = 0 => (rates <= X)
+            return -EOPNOTSUPP;
+        }
+    }
+
+    return 0;
+}
+
+int rt_ioctl_giwrate(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+    PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+    int rate_index = 0, rate_count = 0;
+    HTTRANSMIT_SETTING ht_setting;
+    __s32 ralinkrate[] =
+       {2,  4,   11,  22, // CCK
+       12, 18,   24,  36, 48, 72, 96, 108, // OFDM
+       13, 26,   39,  52,  78, 104, 117, 130, 26,  52,  78, 104, 156, 208, 234, 260, // 20MHz, 800ns GI, MCS: 0 ~ 15
+       39, 78,  117, 156, 234, 312, 351, 390,                                                                            // 20MHz, 800ns GI, MCS: 16 ~ 23
+       27, 54,   81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, // 40MHz, 800ns GI, MCS: 0 ~ 15
+       81, 162, 243, 324, 486, 648, 729, 810,                                                                            // 40MHz, 800ns GI, MCS: 16 ~ 23
+       14, 29,   43,  57,  87, 115, 130, 144, 29, 59,   87, 115, 173, 230, 260, 288, // 20MHz, 400ns GI, MCS: 0 ~ 15
+       43, 87,  130, 173, 260, 317, 390, 433,                                                                            // 20MHz, 400ns GI, MCS: 16 ~ 23
+       30, 60,   90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, // 40MHz, 400ns GI, MCS: 0 ~ 15
+       90, 180, 270, 360, 540, 720, 810, 900};                                                                           // 40MHz, 400ns GI, MCS: 16 ~ 23
+
+    rate_count = sizeof(ralinkrate)/sizeof(__s32);
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+    if ((pAd->StaCfg.bAutoTxRateSwitch == FALSE) &&
+        (INFRA_ON(pAd)) &&
+        ((pAd->CommonCfg.PhyMode <= PHY_11G) || (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)))
+        ht_setting.word = pAd->StaCfg.HTPhyMode.word;
+    else
+        ht_setting.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word;
+
+#ifdef DOT11_N_SUPPORT
+    if (ht_setting.field.MODE >= MODE_HTMIX)
+    {
+//     rate_index = 12 + ((UCHAR)ht_setting.field.BW *16) + ((UCHAR)ht_setting.field.ShortGI *32) + ((UCHAR)ht_setting.field.MCS);
+       rate_index = 12 + ((UCHAR)ht_setting.field.BW *24) + ((UCHAR)ht_setting.field.ShortGI *48) + ((UCHAR)ht_setting.field.MCS);
+    }
+    else
+#endif // DOT11_N_SUPPORT //
+    if (ht_setting.field.MODE == MODE_OFDM)
+       rate_index = (UCHAR)(ht_setting.field.MCS) + 4;
+    else if (ht_setting.field.MODE == MODE_CCK)
+       rate_index = (UCHAR)(ht_setting.field.MCS);
+
+    if (rate_index < 0)
+        rate_index = 0;
+
+    if (rate_index > rate_count)
+        rate_index = rate_count;
+
+    wrqu->bitrate.value = ralinkrate[rate_index] * 500000;
+    wrqu->bitrate.disabled = 0;
+
+    return 0;
+}
+
+static const iw_handler rt_handler[] =
+{
+       (iw_handler) NULL,                                  /* SIOCSIWCOMMIT */
+       (iw_handler) rt_ioctl_giwname,                  /* SIOCGIWNAME   */
+       (iw_handler) NULL,                                  /* SIOCSIWNWID   */
+       (iw_handler) NULL,                                  /* SIOCGIWNWID   */
+       (iw_handler) rt_ioctl_siwfreq,              /* SIOCSIWFREQ   */
+       (iw_handler) rt_ioctl_giwfreq,              /* SIOCGIWFREQ   */
+       (iw_handler) rt_ioctl_siwmode,              /* SIOCSIWMODE   */
+       (iw_handler) rt_ioctl_giwmode,              /* SIOCGIWMODE   */
+       (iw_handler) NULL,                              /* SIOCSIWSENS   */
+       (iw_handler) NULL,                              /* SIOCGIWSENS   */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWRANGE  */
+       (iw_handler) rt_ioctl_giwrange,             /* SIOCGIWRANGE  */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWPRIV   */
+       (iw_handler) NULL /* kernel code */,    /* SIOCGIWPRIV   */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWSTATS  */
+       (iw_handler) rt28xx_get_wireless_stats /* kernel code */,    /* SIOCGIWSTATS  */
+       (iw_handler) NULL,                              /* SIOCSIWSPY    */
+       (iw_handler) NULL,                              /* SIOCGIWSPY    */
+       (iw_handler) NULL,                                      /* SIOCSIWTHRSPY */
+       (iw_handler) NULL,                                      /* SIOCGIWTHRSPY */
+       (iw_handler) rt_ioctl_siwap,            /* SIOCSIWAP     */
+       (iw_handler) rt_ioctl_giwap,                /* SIOCGIWAP     */
+#ifdef SIOCSIWMLME
+       (iw_handler) rt_ioctl_siwmlme,          /* SIOCSIWMLME   */
+#else
+       (iw_handler) NULL,                                      /* SIOCSIWMLME */
+#endif // SIOCSIWMLME //
+       (iw_handler) rt_ioctl_iwaplist,             /* SIOCGIWAPLIST */
+#ifdef SIOCGIWSCAN
+       (iw_handler) rt_ioctl_siwscan,              /* SIOCSIWSCAN   */
+       (iw_handler) rt_ioctl_giwscan,              /* SIOCGIWSCAN   */
+#else
+       (iw_handler) NULL,                                      /* SIOCSIWSCAN   */
+       (iw_handler) NULL,                                      /* SIOCGIWSCAN   */
+#endif /* SIOCGIWSCAN */
+       (iw_handler) rt_ioctl_siwessid,             /* SIOCSIWESSID  */
+       (iw_handler) rt_ioctl_giwessid,             /* SIOCGIWESSID  */
+       (iw_handler) rt_ioctl_siwnickn,             /* SIOCSIWNICKN  */
+       (iw_handler) rt_ioctl_giwnickn,             /* SIOCGIWNICKN  */
+       (iw_handler) NULL,                                      /* -- hole --    */
+       (iw_handler) NULL,                                      /* -- hole --    */
+       (iw_handler) rt_ioctl_siwrate,          /* SIOCSIWRATE   */
+       (iw_handler) rt_ioctl_giwrate,          /* SIOCGIWRATE   */
+       (iw_handler) rt_ioctl_siwrts,               /* SIOCSIWRTS    */
+       (iw_handler) rt_ioctl_giwrts,               /* SIOCGIWRTS    */
+       (iw_handler) rt_ioctl_siwfrag,              /* SIOCSIWFRAG   */
+       (iw_handler) rt_ioctl_giwfrag,              /* SIOCGIWFRAG   */
+       (iw_handler) NULL,                              /* SIOCSIWTXPOW  */
+       (iw_handler) NULL,                              /* SIOCGIWTXPOW  */
+       (iw_handler) NULL,                              /* SIOCSIWRETRY  */
+       (iw_handler) NULL,                              /* SIOCGIWRETRY  */
+       (iw_handler) rt_ioctl_siwencode,                /* SIOCSIWENCODE */
+       (iw_handler) rt_ioctl_giwencode,                /* SIOCGIWENCODE */
+       (iw_handler) NULL,                              /* SIOCSIWPOWER  */
+       (iw_handler) NULL,                              /* SIOCGIWPOWER  */
+       (iw_handler) NULL,                                              /* -- hole -- */
+       (iw_handler) NULL,                                              /* -- hole -- */
+#if WIRELESS_EXT > 17
+    (iw_handler) rt_ioctl_siwgenie,         /* SIOCSIWGENIE  */
+       (iw_handler) rt_ioctl_giwgenie,         /* SIOCGIWGENIE  */
+       (iw_handler) rt_ioctl_siwauth,              /* SIOCSIWAUTH   */
+       (iw_handler) rt_ioctl_giwauth,              /* SIOCGIWAUTH   */
+       (iw_handler) rt_ioctl_siwencodeext,         /* SIOCSIWENCODEEXT */
+       (iw_handler) rt_ioctl_giwencodeext,             /* SIOCGIWENCODEEXT */
+       (iw_handler) rt_ioctl_siwpmksa,         /* SIOCSIWPMKSA  */
+#endif
+};
+
+static const iw_handler rt_priv_handlers[] = {
+       (iw_handler) NULL, /* + 0x00 */
+       (iw_handler) NULL, /* + 0x01 */
+#ifndef CONFIG_AP_SUPPORT
+       (iw_handler) rt_ioctl_setparam, /* + 0x02 */
+#else
+       (iw_handler) NULL, /* + 0x02 */
+#endif // CONFIG_AP_SUPPORT //
+#ifdef DBG
+       (iw_handler) rt_private_ioctl_bbp, /* + 0x03 */
+#else
+       (iw_handler) NULL, /* + 0x03 */
+#endif
+       (iw_handler) NULL, /* + 0x04 */
+       (iw_handler) NULL, /* + 0x05 */
+       (iw_handler) NULL, /* + 0x06 */
+       (iw_handler) NULL, /* + 0x07 */
+       (iw_handler) NULL, /* + 0x08 */
+       (iw_handler) rt_private_get_statistics, /* + 0x09 */
+       (iw_handler) NULL, /* + 0x0A */
+       (iw_handler) NULL, /* + 0x0B */
+       (iw_handler) NULL, /* + 0x0C */
+       (iw_handler) NULL, /* + 0x0D */
+       (iw_handler) NULL, /* + 0x0E */
+       (iw_handler) NULL, /* + 0x0F */
+       (iw_handler) NULL, /* + 0x10 */
+       (iw_handler) rt_private_show, /* + 0x11 */
+    (iw_handler) NULL, /* + 0x12 */
+       (iw_handler) NULL, /* + 0x13 */
+       (iw_handler) NULL, /* + 0x15 */
+       (iw_handler) NULL, /* + 0x17 */
+       (iw_handler) NULL, /* + 0x18 */
+};
+
+const struct iw_handler_def rt28xx_iw_handler_def =
+{
+#define        N(a)    (sizeof (a) / sizeof (a[0]))
+       .standard       = (iw_handler *) rt_handler,
+       .num_standard   = sizeof(rt_handler) / sizeof(iw_handler),
+       .private        = (iw_handler *) rt_priv_handlers,
+       .num_private            = N(rt_priv_handlers),
+       .private_args   = (struct iw_priv_args *) privtab,
+       .num_private_args       = N(privtab),
+#if IW_HANDLER_VERSION >= 7
+    .get_wireless_stats = rt28xx_get_wireless_stats,
+#endif
+};
+
+INT RTMPSetInformation(
+    IN  PRTMP_ADAPTER pAdapter,
+    IN  OUT struct ifreq    *rq,
+    IN  INT                 cmd)
+{
+    struct iwreq                        *wrq = (struct iwreq *) rq;
+    NDIS_802_11_SSID                    Ssid;
+    NDIS_802_11_MAC_ADDRESS             Bssid;
+    RT_802_11_PHY_MODE                  PhyMode;
+    RT_802_11_STA_CONFIG                StaConfig;
+    NDIS_802_11_RATES                   aryRates;
+    RT_802_11_PREAMBLE                  Preamble;
+    NDIS_802_11_WEP_STATUS              WepStatus;
+    NDIS_802_11_AUTHENTICATION_MODE     AuthMode = Ndis802_11AuthModeMax;
+    NDIS_802_11_NETWORK_INFRASTRUCTURE  BssType;
+    NDIS_802_11_RTS_THRESHOLD           RtsThresh;
+    NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh;
+    NDIS_802_11_POWER_MODE              PowerMode;
+    PNDIS_802_11_KEY                    pKey = NULL;
+    PNDIS_802_11_WEP                           pWepKey =NULL;
+    PNDIS_802_11_REMOVE_KEY             pRemoveKey = NULL;
+    NDIS_802_11_CONFIGURATION           Config, *pConfig = NULL;
+    NDIS_802_11_NETWORK_TYPE            NetType;
+    ULONG                               Now;
+    UINT                                KeyIdx = 0;
+    INT                                 Status = NDIS_STATUS_SUCCESS, MaxPhyMode = PHY_11G;
+    ULONG                               PowerTemp;
+    BOOLEAN                             RadioState;
+    BOOLEAN                             StateMachineTouched = FALSE;
+#ifdef DOT11_N_SUPPORT
+       OID_SET_HT_PHYMODE                                      HT_PhyMode;     //11n ,kathy
+#endif // DOT11_N_SUPPORT //
+#ifdef WPA_SUPPLICANT_SUPPORT
+    PNDIS_802_11_PMKID                  pPmkId = NULL;
+    BOOLEAN                                            IEEE8021xState = FALSE;
+    BOOLEAN                                            IEEE8021x_required_keys = FALSE;
+    UCHAR                               wpa_supplicant_enable = 0;
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef SNMP_SUPPORT
+       TX_RTY_CFG_STRUC                        tx_rty_cfg;
+       ULONG                                           ShortRetryLimit, LongRetryLimit;
+       UCHAR                                           ctmp;
+#endif // SNMP_SUPPORT //
+
+
+
+#ifdef DOT11_N_SUPPORT
+       MaxPhyMode = PHY_11N_5G;
+#endif // DOT11_N_SUPPORT //
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("-->RTMPSetInformation(),     0x%08x\n", cmd&0x7FFF));
+    switch(cmd & 0x7FFF) {
+        case RT_OID_802_11_COUNTRY_REGION:
+            if (wrq->u.data.length < sizeof(UCHAR))
+                Status = -EINVAL;
+                       // Only avaliable when EEPROM not programming
+            else if (!(pAdapter->CommonCfg.CountryRegion & 0x80) && !(pAdapter->CommonCfg.CountryRegionForABand & 0x80))
+            {
+                ULONG   Country;
+                UCHAR  TmpPhy;
+
+                               Status = copy_from_user(&Country, wrq->u.data.pointer, wrq->u.data.length);
+                               pAdapter->CommonCfg.CountryRegion = (UCHAR)(Country & 0x000000FF);
+                               pAdapter->CommonCfg.CountryRegionForABand = (UCHAR)((Country >> 8) & 0x000000FF);
+                TmpPhy = pAdapter->CommonCfg.PhyMode;
+                               pAdapter->CommonCfg.PhyMode = 0xff;
+                               // Build all corresponding channel information
+                               RTMPSetPhyMode(pAdapter, TmpPhy);
+#ifdef DOT11_N_SUPPORT
+                               SetCommonHT(pAdapter);
+#endif // DOT11_N_SUPPORT //
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_COUNTRY_REGION (A:%d  B/G:%d)\n", pAdapter->CommonCfg.CountryRegionForABand,
+                                   pAdapter->CommonCfg.CountryRegion));
+            }
+            break;
+        case OID_802_11_BSSID_LIST_SCAN:
+ #ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               break;
+                       }
+#endif // RALINK_ATE //
+            Now = jiffies;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID_LIST_SCAN, TxCnt = %d \n", pAdapter->RalinkCounters.LastOneSecTotalTxCount));
+
+            if (MONITOR_ON(pAdapter))
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n"));
+                break;
+            }
+
+                       //Benson add 20080527, when radio off, sta don't need to scan
+                       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF))
+                               break;
+
+                       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+                       {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is scanning now !!!\n"));
+                               pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE;
+                               Status = NDIS_STATUS_SUCCESS;
+                break;
+            }
+
+                       if (pAdapter->RalinkCounters.LastOneSecTotalTxCount > 100)
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, ignore this set::OID_802_11_BSSID_LIST_SCAN\n"));
+                               Status = NDIS_STATUS_SUCCESS;
+                               pAdapter->StaCfg.ScanCnt = 99;          // Prevent auto scan triggered by this OID
+                               break;
+            }
+
+            if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) &&
+                               ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+                               (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+                               (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
+                               (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) &&
+                (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n"));
+                               Status = NDIS_STATUS_SUCCESS;
+                               pAdapter->StaCfg.ScanCnt = 99;          // Prevent auto scan triggered by this OID
+                               break;
+            }
+
+
+            if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+            {
+                RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+            }
+
+            // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+            // this request, because this request is initiated by NDIS.
+            pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+            // Reset allowed scan retries
+            pAdapter->StaCfg.ScanCnt = 0;
+            pAdapter->StaCfg.LastScanTime = Now;
+
+                       pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE;
+            RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+            MlmeEnqueue(pAdapter,
+                        MLME_CNTL_STATE_MACHINE,
+                        OID_802_11_BSSID_LIST_SCAN,
+                        0,
+                        NULL);
+
+            Status = NDIS_STATUS_SUCCESS;
+            StateMachineTouched = TRUE;
+            break;
+        case OID_802_11_SSID:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_SSID))
+                Status = -EINVAL;
+            else
+            {
+               PCHAR pSsidString = NULL;
+                Status = copy_from_user(&Ssid, wrq->u.data.pointer, wrq->u.data.length);
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SSID (Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid));
+                if (Ssid.SsidLength > MAX_LEN_OF_SSID)
+                    Status = -EINVAL;
+                else
+                {
+                       if (Ssid.SsidLength == 0)
+                       {
+                               Set_SSID_Proc(pAdapter, "");
+                       }
+                                       else
+                       {
+                               pSsidString = (CHAR *) kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG);
+                                               if (pSsidString)
+                                               {
+                                                       NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1);
+                                                       NdisMoveMemory(pSsidString, Ssid.Ssid, Ssid.SsidLength);
+                                       Set_SSID_Proc(pAdapter, pSsidString);
+                                                       kfree(pSsidString);
+                                               }
+                                               else
+                                                       Status = -ENOMEM;
+                       }
+                }
+            }
+            break;
+        case OID_802_11_BSSID:
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               break;
+                       }
+#endif // RALINK_ATE //
+            if (wrq->u.data.length != sizeof(NDIS_802_11_MAC_ADDRESS))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&Bssid, wrq->u.data.pointer, wrq->u.data.length);
+
+                // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+                // this request, because this request is initiated by NDIS.
+                pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+
+                               // Prevent to connect AP again in STAMlmePeriodicExec
+                               pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+
+                // Reset allowed scan retries
+                               pAdapter->StaCfg.ScanCnt = 0;
+
+                if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+                {
+                    RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                    DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+                }
+                MlmeEnqueue(pAdapter,
+                            MLME_CNTL_STATE_MACHINE,
+                            OID_802_11_BSSID,
+                            sizeof(NDIS_802_11_MAC_ADDRESS),
+                            (VOID *)&Bssid);
+                Status = NDIS_STATUS_SUCCESS;
+                StateMachineTouched = TRUE;
+
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                        Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
+            }
+            break;
+        case RT_OID_802_11_RADIO:
+            if (wrq->u.data.length != sizeof(BOOLEAN))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&RadioState, wrq->u.data.pointer, wrq->u.data.length);
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RADIO (=%d)\n", RadioState));
+                if (pAdapter->StaCfg.bSwRadio != RadioState)
+                {
+                    pAdapter->StaCfg.bSwRadio = RadioState;
+                    if (pAdapter->StaCfg.bRadio != (pAdapter->StaCfg.bHwRadio && pAdapter->StaCfg.bSwRadio))
+                    {
+                        pAdapter->StaCfg.bRadio = (pAdapter->StaCfg.bHwRadio && pAdapter->StaCfg.bSwRadio);
+                        if (pAdapter->StaCfg.bRadio == TRUE)
+                        {
+                            MlmeRadioOn(pAdapter);
+                            // Update extra information
+                                                       pAdapter->ExtraInfo = EXTRA_INFO_CLEAR;
+                        }
+                        else
+                        {
+                            MlmeRadioOff(pAdapter);
+                            // Update extra information
+                                                       pAdapter->ExtraInfo = SW_RADIO_OFF;
+                        }
+                    }
+                }
+            }
+            break;
+        case RT_OID_802_11_PHY_MODE:
+            if (wrq->u.data.length != sizeof(RT_802_11_PHY_MODE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&PhyMode, wrq->u.data.pointer, wrq->u.data.length);
+                               if (PhyMode <= MaxPhyMode)
+                               {
+                       RTMPSetPhyMode(pAdapter, PhyMode);
+#ifdef DOT11_N_SUPPORT
+                                       SetCommonHT(pAdapter);
+#endif // DOT11_N_SUPPORT //
+                               }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PHY_MODE (=%d)\n", PhyMode));
+            }
+            break;
+        case RT_OID_802_11_STA_CONFIG:
+            if (wrq->u.data.length != sizeof(RT_802_11_STA_CONFIG))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&StaConfig, wrq->u.data.pointer, wrq->u.data.length);
+                pAdapter->CommonCfg.bEnableTxBurst = StaConfig.EnableTxBurst;
+                pAdapter->CommonCfg.UseBGProtection = StaConfig.UseBGProtection;
+                pAdapter->CommonCfg.bUseShortSlotTime = 1; // 2003-10-30 always SHORT SLOT capable
+                if ((pAdapter->CommonCfg.PhyMode != StaConfig.AdhocMode) &&
+                                       (StaConfig.AdhocMode <= MaxPhyMode))
+                {
+                    // allow dynamic change of "USE OFDM rate or not" in ADHOC mode
+                    // if setting changed, need to reset current TX rate as well as BEACON frame format
+                    if (pAdapter->StaCfg.BssType == BSS_ADHOC)
+                    {
+                                               pAdapter->CommonCfg.PhyMode = StaConfig.AdhocMode;
+                       RTMPSetPhyMode(pAdapter, PhyMode);
+                        MlmeUpdateTxRates(pAdapter, FALSE, 0);
+                        MakeIbssBeacon(pAdapter);           // re-build BEACON frame
+                        AsicEnableIbssSync(pAdapter);   // copy to on-chip memory
+                    }
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_STA_CONFIG (Burst=%d, Protection=%ld,ShortSlot=%d\n",
+                                        pAdapter->CommonCfg.bEnableTxBurst,
+                                        pAdapter->CommonCfg.UseBGProtection,
+                                        pAdapter->CommonCfg.bUseShortSlotTime));
+            }
+            break;
+        case OID_802_11_DESIRED_RATES:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_RATES))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&aryRates, wrq->u.data.pointer, wrq->u.data.length);
+                NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES);
+                NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES));
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DESIRED_RATES (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n",
+                    pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1],
+                    pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3],
+                    pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5],
+                    pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] ));
+                // Changing DesiredRate may affect the MAX TX rate we used to TX frames out
+                MlmeUpdateTxRates(pAdapter, FALSE, 0);
+            }
+            break;
+        case RT_OID_802_11_PREAMBLE:
+            if (wrq->u.data.length != sizeof(RT_802_11_PREAMBLE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&Preamble, wrq->u.data.pointer, wrq->u.data.length);
+                if (Preamble == Rt802_11PreambleShort)
+                {
+                    pAdapter->CommonCfg.TxPreamble = Preamble;
+                    MlmeSetTxPreamble(pAdapter, Rt802_11PreambleShort);
+                }
+                else if ((Preamble == Rt802_11PreambleLong) || (Preamble == Rt802_11PreambleAuto))
+                {
+                    // if user wants AUTO, initialize to LONG here, then change according to AP's
+                    // capability upon association.
+                    pAdapter->CommonCfg.TxPreamble = Preamble;
+                    MlmeSetTxPreamble(pAdapter, Rt802_11PreambleLong);
+                }
+                else
+                {
+                    Status = -EINVAL;
+                    break;
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PREAMBLE (=%d)\n", Preamble));
+            }
+            break;
+        case OID_802_11_WEP_STATUS:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_WEP_STATUS))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&WepStatus, wrq->u.data.pointer, wrq->u.data.length);
+                // Since TKIP, AES, WEP are all supported. It should not have any invalid setting
+                if (WepStatus <= Ndis802_11Encryption3KeyAbsent)
+                {
+                    if (pAdapter->StaCfg.WepStatus != WepStatus)
+                    {
+                        // Config has changed
+                        pAdapter->bConfigChanged = TRUE;
+                    }
+                    pAdapter->StaCfg.WepStatus     = WepStatus;
+                    pAdapter->StaCfg.OrigWepStatus = WepStatus;
+                    pAdapter->StaCfg.PairCipher    = WepStatus;
+                       pAdapter->StaCfg.GroupCipher   = WepStatus;
+                }
+                else
+                {
+                    Status  = -EINVAL;
+                    break;
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEP_STATUS (=%d)\n",WepStatus));
+            }
+            break;
+        case OID_802_11_AUTHENTICATION_MODE:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_AUTHENTICATION_MODE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&AuthMode, wrq->u.data.pointer, wrq->u.data.length);
+                if (AuthMode > Ndis802_11AuthModeMax)
+                {
+                    Status  = -EINVAL;
+                    break;
+                }
+                else
+                {
+                    if (pAdapter->StaCfg.AuthMode != AuthMode)
+                    {
+                        // Config has changed
+                        pAdapter->bConfigChanged = TRUE;
+                    }
+                    pAdapter->StaCfg.AuthMode = AuthMode;
+                }
+                pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n",pAdapter->StaCfg.AuthMode));
+            }
+            break;
+        case OID_802_11_INFRASTRUCTURE_MODE:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&BssType, wrq->u.data.pointer, wrq->u.data.length);
+
+                               if (BssType == Ndis802_11IBSS)
+                                       Set_NetworkType_Proc(pAdapter, "Adhoc");
+                               else if (BssType == Ndis802_11Infrastructure)
+                                       Set_NetworkType_Proc(pAdapter, "Infra");
+                               else if (BssType == Ndis802_11Monitor)
+                                       Set_NetworkType_Proc(pAdapter, "Monitor");
+                               else
+                               {
+                                       Status  = -EINVAL;
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_INFRASTRUCTURE_MODE (unknown)\n"));
+                               }
+                       }
+                       break;
+        case OID_802_11_REMOVE_WEP:
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_WEP\n"));
+            if (wrq->u.data.length != sizeof(NDIS_802_11_KEY_INDEX))
+            {
+                               Status = -EINVAL;
+            }
+            else
+            {
+                               KeyIdx = *(NDIS_802_11_KEY_INDEX *) wrq->u.data.pointer;
+
+                               if (KeyIdx & 0x80000000)
+                               {
+                                       // Should never set default bit when remove key
+                                       Status = -EINVAL;
+                               }
+                               else
+                               {
+                                       KeyIdx = KeyIdx & 0x0fffffff;
+                                       if (KeyIdx >= 4){
+                                               Status = -EINVAL;
+                                       }
+                                       else
+                                       {
+                                               pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = 0;
+                                               pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE;
+                                               AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)KeyIdx);
+                                       }
+                               }
+            }
+            break;
+        case RT_OID_802_11_RESET_COUNTERS:
+            NdisZeroMemory(&pAdapter->WlanCounters, sizeof(COUNTER_802_11));
+            NdisZeroMemory(&pAdapter->Counters8023, sizeof(COUNTER_802_3));
+            NdisZeroMemory(&pAdapter->RalinkCounters, sizeof(COUNTER_RALINK));
+            pAdapter->Counters8023.RxNoBuffer   = 0;
+                       pAdapter->Counters8023.GoodReceives = 0;
+                       pAdapter->Counters8023.RxNoBuffer   = 0;
+#ifdef RT2870
+                       pAdapter->BulkOutComplete       = 0;
+                       pAdapter->BulkOutCompleteOther= 0;
+                       pAdapter->BulkOutCompleteCancel = 0;
+                       pAdapter->BulkOutReq = 0;
+                       pAdapter->BulkInReq= 0;
+                       pAdapter->BulkInComplete = 0;
+                       pAdapter->BulkInCompleteFail = 0;
+#endif // RT2870 //
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RESET_COUNTERS \n"));
+            break;
+        case OID_802_11_RTS_THRESHOLD:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_RTS_THRESHOLD))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&RtsThresh, wrq->u.data.pointer, wrq->u.data.length);
+                if (RtsThresh > MAX_RTS_THRESHOLD)
+                    Status  = -EINVAL;
+                else
+                    pAdapter->CommonCfg.RtsThreshold = (USHORT)RtsThresh;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_RTS_THRESHOLD (=%ld)\n",RtsThresh));
+            break;
+        case OID_802_11_FRAGMENTATION_THRESHOLD:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_FRAGMENTATION_THRESHOLD))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&FragThresh, wrq->u.data.pointer, wrq->u.data.length);
+                pAdapter->CommonCfg.bUseZeroToDisableFragment = FALSE;
+                if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD)
+                {
+                    if (FragThresh == 0)
+                    {
+                        pAdapter->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;
+                        pAdapter->CommonCfg.bUseZeroToDisableFragment = TRUE;
+                    }
+                    else
+                        Status  = -EINVAL;
+                }
+                else
+                    pAdapter->CommonCfg.FragmentThreshold = (USHORT)FragThresh;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_FRAGMENTATION_THRESHOLD (=%ld) \n",FragThresh));
+            break;
+        case OID_802_11_POWER_MODE:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_POWER_MODE))
+                Status = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&PowerMode, wrq->u.data.pointer, wrq->u.data.length);
+                if (PowerMode == Ndis802_11PowerModeCAM)
+                       Set_PSMode_Proc(pAdapter, "CAM");
+                else if (PowerMode == Ndis802_11PowerModeMAX_PSP)
+                       Set_PSMode_Proc(pAdapter, "Max_PSP");
+                else if (PowerMode == Ndis802_11PowerModeFast_PSP)
+                                       Set_PSMode_Proc(pAdapter, "Fast_PSP");
+                else if (PowerMode == Ndis802_11PowerModeLegacy_PSP)
+                                       Set_PSMode_Proc(pAdapter, "Legacy_PSP");
+                else
+                    Status = -EINVAL;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_POWER_MODE (=%d)\n",PowerMode));
+            break;
+         case RT_OID_802_11_TX_POWER_LEVEL_1:
+                       if (wrq->u.data.length  < sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&PowerTemp, wrq->u.data.pointer, wrq->u.data.length);
+                               if (PowerTemp > 100)
+                                       PowerTemp = 0xffffffff;  // AUTO
+                               pAdapter->CommonCfg.TxPowerDefault = PowerTemp; //keep current setting.
+                                       pAdapter->CommonCfg.TxPowerPercentage = pAdapter->CommonCfg.TxPowerDefault;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAdapter->CommonCfg.TxPowerPercentage));
+                       }
+               break;
+               case OID_802_11_NETWORK_TYPE_IN_USE:
+                       if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_TYPE))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&NetType, wrq->u.data.pointer, wrq->u.data.length);
+
+                               if (NetType == Ndis802_11DS)
+                                       RTMPSetPhyMode(pAdapter, PHY_11B);
+                               else if (NetType == Ndis802_11OFDM24)
+                                       RTMPSetPhyMode(pAdapter, PHY_11BG_MIXED);
+                               else if (NetType == Ndis802_11OFDM5)
+                                       RTMPSetPhyMode(pAdapter, PHY_11A);
+                               else
+                                       Status = -EINVAL;
+#ifdef DOT11_N_SUPPORT
+                               if (Status == NDIS_STATUS_SUCCESS)
+                                       SetCommonHT(pAdapter);
+#endif // DOT11_N_SUPPORT //
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_NETWORK_TYPE_IN_USE (=%d)\n",NetType));
+                   }
+                       break;
+        // For WPA PSK PMK key
+        case RT_OID_802_11_ADD_WPA:
+            pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+            if(pKey == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+
+            Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (pKey->Length != wrq->u.data.length)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!!\n"));
+            }
+            else
+            {
+                if ((pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) &&
+                                   (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) &&
+                                   (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) )
+                {
+                    Status = -EOPNOTSUPP;
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!! [AuthMode != WPAPSK/WPA2PSK/WPANONE]\n"));
+                }
+                else if ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+                                                (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
+                                                (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) )     // Only for WPA PSK mode
+                               {
+                    NdisMoveMemory(pAdapter->StaCfg.PMK, &pKey->KeyMaterial, pKey->KeyLength);
+                    // Use RaConfig as PSK agent.
+                    // Start STA supplicant state machine
+                    if (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone)
+                        pAdapter->StaCfg.WpaState = SS_START;
+
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength));
+                }
+                else
+                {
+                    pAdapter->StaCfg.WpaState = SS_NOTUSE;
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength));
+                }
+            }
+            kfree(pKey);
+            break;
+        case OID_802_11_REMOVE_KEY:
+            pRemoveKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+            if(pRemoveKey == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+
+            Status = copy_from_user(pRemoveKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (pRemoveKey->Length != wrq->u.data.length)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!\n"));
+            }
+            else
+            {
+                if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+                {
+                    RTMPWPARemoveKeyProc(pAdapter, pRemoveKey);
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Remove WPA Key!!\n"));
+                }
+                else
+                {
+                    KeyIdx = pRemoveKey->KeyIndex;
+
+                    if (KeyIdx & 0x80000000)
+                    {
+                        // Should never set default bit when remove key
+                        Status  = -EINVAL;
+                        DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(Should never set default bit when remove key)\n"));
+                    }
+                    else
+                    {
+                        KeyIdx = KeyIdx & 0x0fffffff;
+                        if (KeyIdx > 3)
+                        {
+                            Status  = -EINVAL;
+                            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(KeyId[%d] out of range)\n", KeyIdx));
+                        }
+                        else
+                        {
+                            pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = 0;
+                            pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE;
+                            AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)KeyIdx);
+                            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY (id=0x%x, Len=%d-byte)\n", pRemoveKey->KeyIndex, pRemoveKey->Length));
+                        }
+                    }
+                }
+            }
+            kfree(pRemoveKey);
+            break;
+        // New for WPA
+        case OID_802_11_ADD_KEY:
+            pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+            if(pKey == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+            Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (pKey->Length != wrq->u.data.length)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY, Failed!!\n"));
+            }
+            else
+            {
+                RTMPAddKey(pAdapter, pKey);
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength));
+            }
+            kfree(pKey);
+            break;
+        case OID_802_11_CONFIGURATION:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_CONFIGURATION))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&Config, wrq->u.data.pointer, wrq->u.data.length);
+                pConfig = &Config;
+
+                if ((pConfig->BeaconPeriod >= 20) && (pConfig->BeaconPeriod <=400))
+                     pAdapter->CommonCfg.BeaconPeriod = (USHORT) pConfig->BeaconPeriod;
+
+                pAdapter->StaActive.AtimWin = (USHORT) pConfig->ATIMWindow;
+                MAP_KHZ_TO_CHANNEL_ID(pConfig->DSConfig, pAdapter->CommonCfg.Channel);
+                //
+                               // Save the channel on MlmeAux for CntlOidRTBssidProc used.
+                               //
+                               pAdapter->MlmeAux.Channel = pAdapter->CommonCfg.Channel;
+
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CONFIGURATION (BeacnPeriod=%ld,AtimW=%ld,Ch=%d)\n",
+                    pConfig->BeaconPeriod, pConfig->ATIMWindow, pAdapter->CommonCfg.Channel));
+                // Config has changed
+                pAdapter->bConfigChanged = TRUE;
+            }
+            break;
+#ifdef DOT11_N_SUPPORT
+               case RT_OID_802_11_SET_HT_PHYMODE:
+                       if (wrq->u.data.length  != sizeof(OID_SET_HT_PHYMODE))
+                               Status = -EINVAL;
+                       else
+                       {
+                           POID_SET_HT_PHYMODE pHTPhyMode = &HT_PhyMode;
+
+                               Status = copy_from_user(&HT_PhyMode, wrq->u.data.pointer, wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::pHTPhyMode      (PhyMode = %d,TransmitNo = %d, HtMode = %d,     ExtOffset =     %d , MCS = %d, BW =     %d,     STBC = %d, SHORTGI = %d) \n",
+                               pHTPhyMode->PhyMode, pHTPhyMode->TransmitNo,pHTPhyMode->HtMode,pHTPhyMode->ExtOffset,
+                               pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC,      pHTPhyMode->SHORTGI));
+                               if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+                                       RTMPSetHT(pAdapter,     pHTPhyMode);
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_HT_PHYMODE(MCS=%d,BW=%d,SGI=%d,STBC=%d)\n",
+                               pAdapter->StaCfg.HTPhyMode.field.MCS, pAdapter->StaCfg.HTPhyMode.field.BW, pAdapter->StaCfg.HTPhyMode.field.ShortGI,
+                               pAdapter->StaCfg.HTPhyMode.field.STBC));
+                       break;
+#endif // DOT11_N_SUPPORT //
+               case RT_OID_802_11_SET_APSD_SETTING:
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               ULONG apsd ;
+                               Status = copy_from_user(&apsd, wrq->u.data.pointer,     wrq->u.data.length);
+
+                               /*-------------------------------------------------------------------
+                               |B31~B7 |       B6~B5    |       B4      |       B3      |      B2       |      B1       |         B0           |
+                               ---------------------------------------------------------------------
+                               | Rsvd  | Max SP Len | AC_VO | AC_VI | AC_BK | AC_BE | APSD     Capable |
+                               ---------------------------------------------------------------------*/
+                               pAdapter->CommonCfg.bAPSDCapable = (apsd & 0x00000001) ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_BE = ((apsd & 0x00000002) >> 1)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_BK = ((apsd & 0x00000004) >> 2)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_VI = ((apsd & 0x00000008) >> 3)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_VO = ((apsd & 0x00000010) >> 4)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.MaxSPLength = (UCHAR)((apsd & 0x00000060) >> 5);
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_SETTING (apsd=0x%lx, APSDCap=%d, [BE,BK,VI,VO]=[%d/%d/%d/%d],    MaxSPLen=%d)\n", apsd, pAdapter->CommonCfg.bAPSDCapable,
+                                       pAdapter->CommonCfg.bAPSDAC_BE, pAdapter->CommonCfg.bAPSDAC_BK, pAdapter->CommonCfg.bAPSDAC_VI, pAdapter->CommonCfg.bAPSDAC_VO, pAdapter->CommonCfg.MaxSPLength));
+                       }
+                       break;
+
+               case RT_OID_802_11_SET_APSD_PSM:
+                       if (wrq->u.data.length  != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               // Driver needs to notify AP when PSM changes
+                               Status = copy_from_user(&pAdapter->CommonCfg.bAPSDForcePowerSave, wrq->u.data.pointer, wrq->u.data.length);
+                               if (pAdapter->CommonCfg.bAPSDForcePowerSave     != pAdapter->StaCfg.Psm)
+                               {
+                                       MlmeSetPsmBit(pAdapter, pAdapter->CommonCfg.bAPSDForcePowerSave);
+                                       RTMPSendNullFrame(pAdapter,     pAdapter->CommonCfg.TxRate,     TRUE);
+                               }
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_PSM (bAPSDForcePowerSave:%d)\n", pAdapter->CommonCfg.bAPSDForcePowerSave));
+                       }
+                       break;
+#ifdef QOS_DLS_SUPPORT
+               case RT_OID_802_11_SET_DLS:
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               BOOLEAN oldvalue = pAdapter->CommonCfg.bDLSCapable;
+                               Status = copy_from_user(&pAdapter->CommonCfg.bDLSCapable, wrq->u.data.pointer, wrq->u.data.length);
+                               if (oldvalue && !pAdapter->CommonCfg.bDLSCapable)
+                               {
+                                       int     i;
+                                       // tear down local dls table entry
+                                       for     (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+                                       {
+                                               if (pAdapter->StaCfg.DLSEntry[i].Valid && (pAdapter->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+                                               {
+                                                       pAdapter->StaCfg.DLSEntry[i].Status     = DLS_NONE;
+                                                       pAdapter->StaCfg.DLSEntry[i].Valid      = FALSE;
+                                                       RTMPSendDLSTearDownFrame(pAdapter, pAdapter->StaCfg.DLSEntry[i].MacAddr);
+                                               }
+                                       }
+
+                                       // tear down peer dls table     entry
+                                       for     (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+                                       {
+                                               if (pAdapter->StaCfg.DLSEntry[i].Valid && (pAdapter->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+                                               {
+                                                       pAdapter->StaCfg.DLSEntry[i].Status     = DLS_NONE;
+                                                       pAdapter->StaCfg.DLSEntry[i].Valid      = FALSE;
+                                                       RTMPSendDLSTearDownFrame(pAdapter, pAdapter->StaCfg.DLSEntry[i].MacAddr);
+                                               }
+                                       }
+                               }
+
+                               DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS (=%d)\n", pAdapter->CommonCfg.bDLSCapable));
+                       }
+                       break;
+
+               case RT_OID_802_11_SET_DLS_PARAM:
+                       if (wrq->u.data.length  != sizeof(RT_802_11_DLS_UI))
+                               Status = -EINVAL;
+                       else
+                       {
+                               RT_802_11_DLS   Dls;
+
+                               NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
+                               RTMPMoveMemory(&Dls, wrq->u.data.pointer, sizeof(RT_802_11_DLS_UI));
+                               MlmeEnqueue(pAdapter,
+                                                       MLME_CNTL_STATE_MACHINE,
+                                                       RT_OID_802_11_SET_DLS_PARAM,
+                                                       sizeof(RT_802_11_DLS),
+                                                       &Dls);
+                               DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS_PARAM \n"));
+                       }
+                       break;
+#endif // QOS_DLS_SUPPORT //
+               case RT_OID_802_11_SET_WMM:
+                       if (wrq->u.data.length  != sizeof(BOOLEAN))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&pAdapter->CommonCfg.bWmmCapable, wrq->u.data.pointer, wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_WMM (=%d)     \n", pAdapter->CommonCfg.bWmmCapable));
+                       }
+                       break;
+
+               case OID_802_11_DISASSOCIATE:
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               break;
+                       }
+#endif // RALINK_ATE //
+                       //
+                       // Set NdisRadioStateOff to     TRUE, instead of called MlmeRadioOff.
+                       // Later on, NDIS_802_11_BSSID_LIST_EX->NumberOfItems should be 0
+                       // when query OID_802_11_BSSID_LIST.
+                       //
+                       // TRUE:  NumberOfItems will set to     0.
+                       // FALSE: NumberOfItems no change.
+                       //
+                       pAdapter->CommonCfg.NdisRadioStateOff = TRUE;
+                       // Set to immediately send the media disconnect event
+                       pAdapter->MlmeAux.CurrReqIsFromNdis     = TRUE;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DISASSOCIATE \n"));
+
+                       if (INFRA_ON(pAdapter))
+                       {
+                               if (pAdapter->Mlme.CntlMachine.CurrState !=     CNTL_IDLE)
+                               {
+                                       RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME     busy, reset     MLME state machine !!!\n"));
+                               }
+
+                               MlmeEnqueue(pAdapter,
+                                       MLME_CNTL_STATE_MACHINE,
+                                       OID_802_11_DISASSOCIATE,
+                                       0,
+                                       NULL);
+
+                               StateMachineTouched     = TRUE;
+                       }
+                       break;
+
+#ifdef DOT11_N_SUPPORT
+               case RT_OID_802_11_SET_IMME_BA_CAP:
+                               if (wrq->u.data.length != sizeof(OID_BACAP_STRUC))
+                                       Status = -EINVAL;
+                               else
+                               {
+                                       OID_BACAP_STRUC Orde ;
+                                       Status = copy_from_user(&Orde, wrq->u.data.pointer, wrq->u.data.length);
+                                       if (Orde.Policy > BA_NOTUSE)
+                                       {
+                                               Status = NDIS_STATUS_INVALID_DATA;
+                                       }
+                                       else if (Orde.Policy == BA_NOTUSE)
+                                       {
+                                               pAdapter->CommonCfg.BACapability.field.Policy = BA_NOTUSE;
+                                               pAdapter->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MimoPs= Orde.MMPSmode;
+                                               pAdapter->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode;
+                                               // UPdata to HT IE
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode;
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize;
+                                               pAdapter->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity;
+                                       }
+                                       else
+                                       {
+                        pAdapter->CommonCfg.BACapability.field.AutoBA = Orde.AutoBA;
+                                               pAdapter->CommonCfg.BACapability.field.Policy = IMMED_BA; // we only support immediate BA.
+                                               pAdapter->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MimoPs = Orde.MMPSmode;
+                                               pAdapter->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode;
+
+                                               // UPdata to HT IE
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode;
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize;
+                                               pAdapter->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity;
+
+                                               if (pAdapter->CommonCfg.BACapability.field.RxBAWinLimit > MAX_RX_REORDERBUF)
+                                                       pAdapter->CommonCfg.BACapability.field.RxBAWinLimit = MAX_RX_REORDERBUF;
+
+                                       }
+
+                                       pAdapter->CommonCfg.REGBACapability.word = pAdapter->CommonCfg.BACapability.word;
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::(Orde.AutoBA = %d) (Policy=%d)(ReBAWinLimit=%d)(TxBAWinLimit=%d)(AutoMode=%d)\n",Orde.AutoBA, pAdapter->CommonCfg.BACapability.field.Policy,
+                                               pAdapter->CommonCfg.BACapability.field.RxBAWinLimit,pAdapter->CommonCfg.BACapability.field.TxBAWinLimit, pAdapter->CommonCfg.BACapability.field.AutoBA));
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::(MimoPs = %d)(AmsduEnable = %d) (AmsduSize=%d)(MpduDensity=%d)\n",pAdapter->CommonCfg.DesiredHtPhy.MimoPs, pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable,
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduSize, pAdapter->CommonCfg.DesiredHtPhy.MpduDensity));
+                               }
+
+                               break;
+               case RT_OID_802_11_ADD_IMME_BA:
+                       DBGPRINT(RT_DEBUG_TRACE, (" Set :: RT_OID_802_11_ADD_IMME_BA \n"));
+                       if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY))
+                                       Status = -EINVAL;
+                       else
+                       {
+                               UCHAR                   index;
+                               OID_ADD_BA_ENTRY    BA;
+                               MAC_TABLE_ENTRY     *pEntry;
+
+                               Status = copy_from_user(&BA, wrq->u.data.pointer, wrq->u.data.length);
+                               if (BA.TID > 15)
+                               {
+                                       Status = NDIS_STATUS_INVALID_DATA;
+                                       break;
+                               }
+                               else
+                               {
+                                       //BATableInsertEntry
+                                       //As ad-hoc mode, BA pair is not limited to only BSSID. so add via OID.
+                                       index = BA.TID;
+                                       // in ad hoc mode, when adding BA pair, we should insert this entry into MACEntry too
+                                       pEntry = MacTableLookup(pAdapter, BA.MACAddr);
+                                       if (!pEntry)
+                                       {
+                                               DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_802_11_ADD_IMME_BA. break on no connection.----:%x:%x\n", BA.MACAddr[4], BA.MACAddr[5]));
+                                               break;
+                                       }
+                                       if (BA.IsRecipient == FALSE)
+                                       {
+                                           if (pEntry->bIAmBadAtheros == TRUE)
+                                                       pAdapter->CommonCfg.BACapability.field.RxBAWinLimit = 0x10;
+
+                                               BAOriSessionSetUp(pAdapter, pEntry, index, 0, 100, TRUE);
+                                       }
+                                       else
+                                       {
+                                               //BATableInsertEntry(pAdapter, pEntry->Aid, BA.MACAddr, 0, 0xffff, BA.TID, BA.nMSDU, BA.IsRecipient);
+                                       }
+
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_IMME_BA. Rec = %d. Mac = %x:%x:%x:%x:%x:%x . \n",
+                                               BA.IsRecipient, BA.MACAddr[0], BA.MACAddr[1], BA.MACAddr[2], BA.MACAddr[2]
+                                               , BA.MACAddr[4], BA.MACAddr[5]));
+                               }
+                       }
+                       break;
+
+               case RT_OID_802_11_TEAR_IMME_BA:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA \n"));
+                       if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY))
+                                       Status = -EINVAL;
+                       else
+                       {
+                               POID_ADD_BA_ENTRY       pBA;
+                               MAC_TABLE_ENTRY *pEntry;
+
+                               pBA = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+
+                               if (pBA == NULL)
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA kmalloc() can't allocate enough memory\n"));
+                                       Status = NDIS_STATUS_FAILURE;
+                               }
+                               else
+                               {
+                                       Status = copy_from_user(pBA, wrq->u.data.pointer, wrq->u.data.length);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA(TID=%d, bAllTid=%d)\n", pBA->TID, pBA->bAllTid));
+
+                                       if (!pBA->bAllTid && (pBA->TID > NUM_OF_TID))
+                                       {
+                                               Status = NDIS_STATUS_INVALID_DATA;
+                                               break;
+                                       }
+
+                                       if (pBA->IsRecipient == FALSE)
+                                       {
+                                               pEntry = MacTableLookup(pAdapter, pBA->MACAddr);
+                                               DBGPRINT(RT_DEBUG_TRACE, (" pBA->IsRecipient == FALSE\n"));
+                                               if (pEntry)
+                                               {
+                                                       DBGPRINT(RT_DEBUG_TRACE, (" pBA->pEntry\n"));
+                                                       BAOriSessionTearDown(pAdapter, pEntry->Aid, pBA->TID, FALSE, TRUE);
+                                               }
+                                               else
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n"));
+                                       }
+                                       else
+                                       {
+                                               pEntry = MacTableLookup(pAdapter, pBA->MACAddr);
+                                               if (pEntry)
+                                               {
+                                                       BARecSessionTearDown( pAdapter, (UCHAR)pEntry->Aid, pBA->TID, TRUE);
+                                               }
+                                               else
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n"));
+                                       }
+                                       kfree(pBA);
+                               }
+            }
+            break;
+#endif // DOT11_N_SUPPORT //
+
+        // For WPA_SUPPLICANT to set static wep key
+       case OID_802_11_ADD_WEP:
+           pWepKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+
+           if(pWepKey == NULL)
+            {
+                Status = -ENOMEM;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed!!\n"));
+                break;
+            }
+            Status = copy_from_user(pWepKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (Status)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (length mismatch)!!\n"));
+            }
+            else
+            {
+                       KeyIdx = pWepKey->KeyIndex & 0x0fffffff;
+                // KeyIdx must be 0 ~ 3
+                if (KeyIdx > 4)
+                       {
+                    Status  = -EINVAL;
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (KeyIdx must be smaller than 4)!!\n"));
+                }
+                else
+                {
+                    UCHAR CipherAlg = 0;
+                    PUCHAR Key;
+
+                    // set key material and key length
+                    NdisZeroMemory(pAdapter->SharedKey[BSS0][KeyIdx].Key, 16);
+                    pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength;
+                    NdisMoveMemory(pAdapter->SharedKey[BSS0][KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength);
+
+                    switch(pWepKey->KeyLength)
+                    {
+                        case 5:
+                            CipherAlg = CIPHER_WEP64;
+                            break;
+                        case 13:
+                            CipherAlg = CIPHER_WEP128;
+                            break;
+                        default:
+                            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, only support CIPHER_WEP64(len:5) & CIPHER_WEP128(len:13)!!\n"));
+                            Status = -EINVAL;
+                            break;
+                    }
+                    pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CipherAlg;
+
+                    // Default key for tx (shared key)
+                    if (pWepKey->KeyIndex & 0x80000000)
+                    {
+#ifdef WPA_SUPPLICANT_SUPPORT
+                        // set key material and key length
+                        NdisZeroMemory(pAdapter->StaCfg.DesireSharedKey[KeyIdx].Key, 16);
+                        pAdapter->StaCfg.DesireSharedKey[KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength;
+                        NdisMoveMemory(pAdapter->StaCfg.DesireSharedKey[KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength);
+                        pAdapter->StaCfg.DesireSharedKeyId = KeyIdx;
+                        pAdapter->StaCfg.DesireSharedKey[KeyIdx].CipherAlg = CipherAlg;
+#endif // WPA_SUPPLICANT_SUPPORT //
+                        pAdapter->StaCfg.DefaultKeyId = (UCHAR) KeyIdx;
+                    }
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+                                       if ((pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) &&
+                                               (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA))
+                                       {
+                                               Key = pWepKey->KeyMaterial;
+
+                                               // Set Group key material to Asic
+                                       AsicAddSharedKeyEntry(pAdapter, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL);
+
+                                               // Update WCID attribute table and IVEIV table for this group key table
+                                               RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, NULL);
+
+                                               STA_PORT_SECURED(pAdapter);
+
+                                       // Indicate Connected for GUI
+                                       pAdapter->IndicateMediaState = NdisMediaStateConnected;
+                                       }
+                    else if (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)
+#endif // WPA_SUPPLICANT_SUPPORT
+                    {
+                        Key = pAdapter->SharedKey[BSS0][KeyIdx].Key;
+
+                        // Set key material and cipherAlg to Asic
+                                       AsicAddSharedKeyEntry(pAdapter, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL);
+
+                        if (pWepKey->KeyIndex & 0x80000000)
+                        {
+                            PMAC_TABLE_ENTRY pEntry = &pAdapter->MacTab.Content[BSSID_WCID];
+                            // Assign group key info
+                                               RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, NULL);
+                                               // Assign pairwise key info
+                                               RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, pEntry);
+                        }
+                    }
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP (id=0x%x, Len=%d-byte), %s\n", pWepKey->KeyIndex, pWepKey->KeyLength, (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) ? "Port Secured":"Port NOT Secured"));
+                               }
+            }
+            kfree(pWepKey);
+            break;
+#ifdef WPA_SUPPLICANT_SUPPORT
+           case OID_SET_COUNTERMEASURES:
+            if (wrq->u.data.length != sizeof(int))
+                Status  = -EINVAL;
+            else
+            {
+                int enabled = 0;
+                Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length);
+                if (enabled == 1)
+                    pAdapter->StaCfg.bBlockAssoc = TRUE;
+                else
+                    // WPA MIC error should block association attempt for 60 seconds
+                    pAdapter->StaCfg.bBlockAssoc = FALSE;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_SET_COUNTERMEASURES bBlockAssoc=%s\n", pAdapter->StaCfg.bBlockAssoc ? "TRUE":"FALSE"));
+            }
+               break;
+        case RT_OID_WPA_SUPPLICANT_SUPPORT:
+                       if (wrq->u.data.length != sizeof(UCHAR))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&wpa_supplicant_enable, wrq->u.data.pointer, wrq->u.data.length);
+                       pAdapter->StaCfg.WpaSupplicantUP = wpa_supplicant_enable;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAdapter->StaCfg.WpaSupplicantUP));
+                       }
+            break;
+        case OID_802_11_DEAUTHENTICATION:
+            if (wrq->u.data.length != sizeof(MLME_DEAUTH_REQ_STRUCT))
+                Status  = -EINVAL;
+            else
+            {
+                MLME_DEAUTH_REQ_STRUCT      *pInfo;
+                               MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+
+                pInfo = (MLME_DEAUTH_REQ_STRUCT *) MsgElem->Msg;
+                Status = copy_from_user(pInfo, wrq->u.data.pointer, wrq->u.data.length);
+                MlmeDeauthReqAction(pAdapter, MsgElem);
+                               kfree(MsgElem);
+
+                if (INFRA_ON(pAdapter))
+                {
+                    LinkDown(pAdapter, FALSE);
+                    pAdapter->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION (Reason=%d)\n", pInfo->Reason));
+            }
+            break;
+        case OID_802_11_DROP_UNENCRYPTED:
+            if (wrq->u.data.length != sizeof(int))
+                Status  = -EINVAL;
+            else
+            {
+                int enabled = 0;
+                Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length);
+                if (enabled == 1)
+                    pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                else
+                    pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               NdisAcquireSpinLock(&pAdapter->MacTabLock);
+                               pAdapter->MacTab.Content[BSSID_WCID].PortSecured = pAdapter->StaCfg.PortSecured;
+                               NdisReleaseSpinLock(&pAdapter->MacTabLock);
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DROP_UNENCRYPTED (=%d)\n", enabled));
+            }
+            break;
+        case OID_802_11_SET_IEEE8021X:
+            if (wrq->u.data.length != sizeof(BOOLEAN))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&IEEE8021xState, wrq->u.data.pointer, wrq->u.data.length);
+                       pAdapter->StaCfg.IEEE8021X = IEEE8021xState;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X (=%d)\n", IEEE8021xState));
+            }
+            break;
+        case OID_802_11_SET_IEEE8021X_REQUIRE_KEY:
+                       if (wrq->u.data.length != sizeof(BOOLEAN))
+                                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&IEEE8021x_required_keys, wrq->u.data.pointer, wrq->u.data.length);
+                               pAdapter->StaCfg.IEEE8021x_required_keys = IEEE8021x_required_keys;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X_REQUIRE_KEY (%d)\n", IEEE8021x_required_keys));
+                       }
+                       break;
+        case OID_802_11_PMKID:
+               pPmkId = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+
+               if(pPmkId == NULL) {
+                Status = -ENOMEM;
+                break;
+            }
+            Status = copy_from_user(pPmkId, wrq->u.data.pointer, wrq->u.data.length);
+
+               // check the PMKID information
+               if (pPmkId->BSSIDInfoCount == 0)
+                NdisZeroMemory(pAdapter->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO);
+               else
+               {
+                       PBSSID_INFO     pBssIdInfo;
+                       UINT            BssIdx;
+                       UINT            CachedIdx;
+
+                       for (BssIdx = 0; BssIdx < pPmkId->BSSIDInfoCount; BssIdx++)
+                       {
+                               // point to the indexed BSSID_INFO structure
+                               pBssIdInfo = (PBSSID_INFO) ((PUCHAR) pPmkId + 2 * sizeof(UINT) + BssIdx * sizeof(BSSID_INFO));
+                               // Find the entry in the saved data base.
+                               for (CachedIdx = 0; CachedIdx < pAdapter->StaCfg.SavedPMKNum; CachedIdx++)
+                               {
+                                       // compare the BSSID
+                                       if (NdisEqualMemory(pBssIdInfo->BSSID, pAdapter->StaCfg.SavedPMK[CachedIdx].BSSID, sizeof(NDIS_802_11_MAC_ADDRESS)))
+                                               break;
+                               }
+
+                               // Found, replace it
+                               if (CachedIdx < PMKID_NO)
+                               {
+                                       DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx));
+                                       NdisMoveMemory(&pAdapter->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO));
+                                       pAdapter->StaCfg.SavedPMKNum++;
+                               }
+                               // Not found, replace the last one
+                               else
+                               {
+                                       // Randomly replace one
+                                       CachedIdx = (pBssIdInfo->BSSID[5] % PMKID_NO);
+                                       DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx));
+                                       NdisMoveMemory(&pAdapter->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO));
+                               }
+                       }
+                       }
+                       if(pPmkId)
+                               kfree(pPmkId);
+               break;
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+
+
+#ifdef SNMP_SUPPORT
+               case OID_802_11_SHORTRETRYLIMIT:
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&ShortRetryLimit, wrq->u.data.pointer, wrq->u.data.length);
+                               RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                               tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit;
+                               RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SHORTRETRYLIMIT (tx_rty_cfg.field.ShortRetryLimit=%d, ShortRetryLimit=%ld)\n", tx_rty_cfg.field.ShortRtyLimit, ShortRetryLimit));
+                       }
+                       break;
+
+               case OID_802_11_LONGRETRYLIMIT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT \n"));
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&LongRetryLimit, wrq->u.data.pointer, wrq->u.data.length);
+                               RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                               tx_rty_cfg.field.LongRtyLimit = LongRetryLimit;
+                               RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT (tx_rty_cfg.field.LongRetryLimit= %d,LongRetryLimit=%ld)\n", tx_rty_cfg.field.LongRtyLimit, LongRetryLimit));
+                       }
+                       break;
+
+               case OID_802_11_WEPDEFAULTKEYVALUE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE\n"));
+                       pKey = kmalloc(wrq->u.data.length, GFP_KERNEL);
+                       Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length);
+                       //pKey = &WepKey;
+
+                       if ( pKey->Length != wrq->u.data.length)
+                       {
+                               Status = -EINVAL;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE, Failed!!\n"));
+                       }
+                       KeyIdx = pKey->KeyIndex & 0x0fffffff;
+                       DBGPRINT(RT_DEBUG_TRACE,("pKey->KeyIndex =%d, pKey->KeyLength=%d\n", pKey->KeyIndex, pKey->KeyLength));
+
+                       // it is a shared key
+                       if (KeyIdx > 4)
+                               Status = -EINVAL;
+                       else
+                       {
+                               pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen = (UCHAR) pKey->KeyLength;
+                               NdisMoveMemory(&pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, &pKey->KeyMaterial, pKey->KeyLength);
+                               if (pKey->KeyIndex & 0x80000000)
+                               {
+                                       // Default key for tx (shared key)
+                                       pAdapter->StaCfg.DefaultKeyId = (UCHAR) KeyIdx;
+                               }
+                               //RestartAPIsRequired = TRUE;
+                       }
+                       break;
+
+
+               case OID_802_11_WEPDEFAULTKEYID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYID \n"));
+
+                       if (wrq->u.data.length != sizeof(UCHAR))
+                               Status = -EINVAL;
+                       else
+                               Status = copy_from_user(&pAdapter->StaCfg.DefaultKeyId, wrq->u.data.pointer, wrq->u.data.length);
+
+                       break;
+
+
+               case OID_802_11_CURRENTCHANNEL:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CURRENTCHANNEL \n"));
+                       if (wrq->u.data.length != sizeof(UCHAR))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&ctmp, wrq->u.data.pointer, wrq->u.data.length);
+                               sprintf(&ctmp,"%d", ctmp);
+                               Set_Channel_Proc(pAdapter, &ctmp);
+                       }
+                       break;
+#endif
+
+
+
+        default:
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd));
+            Status = -EOPNOTSUPP;
+            break;
+    }
+
+
+    return Status;
+}
+
+INT RTMPQueryInformation(
+    IN  PRTMP_ADAPTER pAdapter,
+    IN  OUT struct ifreq    *rq,
+    IN  INT                 cmd)
+{
+    struct iwreq                        *wrq = (struct iwreq *) rq;
+    NDIS_802_11_BSSID_LIST_EX           *pBssidList = NULL;
+    PNDIS_WLAN_BSSID_EX                 pBss;
+    NDIS_802_11_SSID                    Ssid;
+    NDIS_802_11_CONFIGURATION           *pConfiguration = NULL;
+    RT_802_11_LINK_STATUS               *pLinkStatus = NULL;
+    RT_802_11_STA_CONFIG                *pStaConfig = NULL;
+    NDIS_802_11_STATISTICS              *pStatistics = NULL;
+    NDIS_802_11_RTS_THRESHOLD           RtsThresh;
+    NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh;
+    NDIS_802_11_POWER_MODE              PowerMode;
+    NDIS_802_11_NETWORK_INFRASTRUCTURE  BssType;
+    RT_802_11_PREAMBLE                  PreamType;
+    NDIS_802_11_AUTHENTICATION_MODE     AuthMode;
+    NDIS_802_11_WEP_STATUS              WepStatus;
+    NDIS_MEDIA_STATE                    MediaState;
+    ULONG                               BssBufSize, ulInfo=0, NetworkTypeList[4], apsd = 0;
+    USHORT                              BssLen = 0;
+    PUCHAR                              pBuf = NULL, pPtr;
+    INT                                 Status = NDIS_STATUS_SUCCESS;
+    UINT                                we_version_compiled;
+    UCHAR                               i, Padding = 0;
+    BOOLEAN                             RadioState;
+       UCHAR   driverVersion[8];
+    OID_SET_HT_PHYMODE                         *pHTPhyMode = NULL;
+
+
+#ifdef SNMP_SUPPORT
+       //for snmp, kathy
+       DefaultKeyIdxValue                      *pKeyIdxValue;
+       INT                                                     valueLen;
+       TX_RTY_CFG_STRUC                        tx_rty_cfg;
+       ULONG                                           ShortRetryLimit, LongRetryLimit;
+       UCHAR                                           tmp[64];
+#endif //SNMP
+
+    switch(cmd)
+    {
+        case RT_OID_DEVICE_NAME:
+            wrq->u.data.length = sizeof(STA_NIC_DEVICE_NAME);
+            Status = copy_to_user(wrq->u.data.pointer, STA_NIC_DEVICE_NAME, wrq->u.data.length);
+            break;
+        case RT_OID_VERSION_INFO:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_VERSION_INFO \n"));
+                       wrq->u.data.length = 8*sizeof(UCHAR);
+                       sprintf(&driverVersion[0], "%s", STA_DRIVER_VERSION);
+                       driverVersion[7] = '\0';
+                       if (copy_to_user(wrq->u.data.pointer, &driverVersion, wrq->u.data.length))
+            {
+                               Status = -EFAULT;
+            }
+            break;
+#ifdef RALINK_ATE
+               case RT_QUERY_ATE_TXDONE_COUNT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_QUERY_ATE_TXDONE_COUNT \n"));
+                       wrq->u.data.length = sizeof(UINT32);
+                       if (copy_to_user(wrq->u.data.pointer, &pAdapter->ate.TxDoneCount, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+                       break;
+#endif // RALINK_ATE //
+        case OID_802_11_BSSID_LIST:
+            if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+            {
+               /*
+                * Still scanning, indicate the caller should try again.
+                */
+               DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (Still scanning)\n"));
+                               return -EAGAIN;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (%d BSS returned)\n",pAdapter->ScanTab.BssNr));
+                       pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE;
+            // Claculate total buffer size required
+            BssBufSize = sizeof(ULONG);
+
+            for (i = 0; i < pAdapter->ScanTab.BssNr; i++)
+            {
+                // Align pointer to 4 bytes boundary.
+                //Padding = 4 - (pAdapter->ScanTab.BssEntry[i].VarIELen & 0x0003);
+                //if (Padding == 4)
+                //    Padding = 0;
+                BssBufSize += (sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen + Padding);
+            }
+
+            // For safety issue, we add 256 bytes just in case
+            BssBufSize += 256;
+            // Allocate the same size as passed from higher layer
+            pBuf = kmalloc(BssBufSize, MEM_ALLOC_FLAG);
+            if(pBuf == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+            // Init 802_11_BSSID_LIST_EX structure
+            NdisZeroMemory(pBuf, BssBufSize);
+            pBssidList = (PNDIS_802_11_BSSID_LIST_EX) pBuf;
+            pBssidList->NumberOfItems = pAdapter->ScanTab.BssNr;
+
+            // Calculate total buffer length
+            BssLen = 4; // Consist of NumberOfItems
+            // Point to start of NDIS_WLAN_BSSID_EX
+            // pPtr = pBuf + sizeof(ULONG);
+            pPtr = (PUCHAR) &pBssidList->Bssid[0];
+            for (i = 0; i < pAdapter->ScanTab.BssNr; i++)
+            {
+                pBss = (PNDIS_WLAN_BSSID_EX) pPtr;
+                NdisMoveMemory(&pBss->MacAddress, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN);
+                if ((pAdapter->ScanTab.BssEntry[i].Hidden == 1) && (pAdapter->StaCfg.bShowHiddenSSID == FALSE))
+                {
+                    //
+                                       // We must return this SSID during 4way handshaking, otherwise Aegis will failed to parse WPA infomation
+                                       // and then failed to send EAPOl farame.
+                                       //
+                                       if ((pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAdapter->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED))
+                                       {
+                                               pBss->Ssid.SsidLength = pAdapter->ScanTab.BssEntry[i].SsidLen;
+                                               NdisMoveMemory(pBss->Ssid.Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen);
+                                       }
+                                       else
+                       pBss->Ssid.SsidLength = 0;
+                }
+                else
+                {
+                    pBss->Ssid.SsidLength = pAdapter->ScanTab.BssEntry[i].SsidLen;
+                    NdisMoveMemory(pBss->Ssid.Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen);
+                }
+                pBss->Privacy = pAdapter->ScanTab.BssEntry[i].Privacy;
+                pBss->Rssi = pAdapter->ScanTab.BssEntry[i].Rssi - pAdapter->BbpRssiToDbmDelta;
+                pBss->NetworkTypeInUse = NetworkTypeInUseSanity(&pAdapter->ScanTab.BssEntry[i]);
+                pBss->Configuration.Length = sizeof(NDIS_802_11_CONFIGURATION);
+                pBss->Configuration.BeaconPeriod = pAdapter->ScanTab.BssEntry[i].BeaconPeriod;
+                pBss->Configuration.ATIMWindow = pAdapter->ScanTab.BssEntry[i].AtimWin;
+
+                MAP_CHANNEL_ID_TO_KHZ(pAdapter->ScanTab.BssEntry[i].Channel, pBss->Configuration.DSConfig);
+
+                if (pAdapter->ScanTab.BssEntry[i].BssType == BSS_INFRA)
+                    pBss->InfrastructureMode = Ndis802_11Infrastructure;
+                else
+                    pBss->InfrastructureMode = Ndis802_11IBSS;
+
+                NdisMoveMemory(pBss->SupportedRates, pAdapter->ScanTab.BssEntry[i].SupRate, pAdapter->ScanTab.BssEntry[i].SupRateLen);
+                NdisMoveMemory(pBss->SupportedRates + pAdapter->ScanTab.BssEntry[i].SupRateLen,
+                               pAdapter->ScanTab.BssEntry[i].ExtRate,
+                               pAdapter->ScanTab.BssEntry[i].ExtRateLen);
+
+                if (pAdapter->ScanTab.BssEntry[i].VarIELen == 0)
+                {
+                    pBss->IELength = sizeof(NDIS_802_11_FIXED_IEs);
+                    NdisMoveMemory(pBss->IEs, &pAdapter->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs));
+                    pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs);
+                }
+                else
+                {
+                    pBss->IELength = (ULONG)(sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen);
+                    pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs);
+                    NdisMoveMemory(pBss->IEs, &pAdapter->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs));
+                    NdisMoveMemory(pBss->IEs + sizeof(NDIS_802_11_FIXED_IEs), pAdapter->ScanTab.BssEntry[i].VarIEs, pAdapter->ScanTab.BssEntry[i].VarIELen);
+                    pPtr += pAdapter->ScanTab.BssEntry[i].VarIELen;
+                }
+                pBss->Length = (ULONG)(sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen + Padding);
+
+#if WIRELESS_EXT < 17
+                if ((BssLen + pBss->Length) < wrq->u.data.length)
+                BssLen += pBss->Length;
+                else
+                {
+                    pBssidList->NumberOfItems = i;
+                    break;
+                }
+#else
+                BssLen += pBss->Length;
+#endif
+            }
+
+#if WIRELESS_EXT < 17
+            wrq->u.data.length = BssLen;
+#else
+            if (BssLen > wrq->u.data.length)
+            {
+                kfree(pBssidList);
+                return -E2BIG;
+            }
+            else
+                wrq->u.data.length = BssLen;
+#endif
+            Status = copy_to_user(wrq->u.data.pointer, pBssidList, BssLen);
+            kfree(pBssidList);
+            break;
+        case OID_802_3_CURRENT_ADDRESS:
+            wrq->u.data.length = MAC_ADDR_LEN;
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length);
+            break;
+        case OID_GEN_MEDIA_CONNECT_STATUS:
+            if (pAdapter->IndicateMediaState == NdisMediaStateConnected)
+                MediaState = NdisMediaStateConnected;
+            else
+                MediaState = NdisMediaStateDisconnected;
+
+            wrq->u.data.length = sizeof(NDIS_MEDIA_STATE);
+            Status = copy_to_user(wrq->u.data.pointer, &MediaState, wrq->u.data.length);
+            break;
+        case OID_802_11_BSSID:
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               Status = NDIS_STATUS_RESOURCES;
+                               break;
+                       }
+#endif // RALINK_ATE //
+            if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
+            {
+                Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Bssid, sizeof(NDIS_802_11_MAC_ADDRESS));
+
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID(=EMPTY)\n"));
+                Status = -ENOTCONN;
+            }
+            break;
+        case OID_802_11_SSID:
+                       NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID));
+                       NdisZeroMemory(Ssid.Ssid, MAX_LEN_OF_SSID);
+            Ssid.SsidLength = pAdapter->CommonCfg.SsidLen;
+                       memcpy(Ssid.Ssid, pAdapter->CommonCfg.Ssid,     Ssid.SsidLength);
+            wrq->u.data.length = sizeof(NDIS_802_11_SSID);
+            Status = copy_to_user(wrq->u.data.pointer, &Ssid, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SSID (Len=%d, ssid=%s)\n", Ssid.SsidLength,Ssid.Ssid));
+            break;
+        case RT_OID_802_11_QUERY_LINK_STATUS:
+            pLinkStatus = (RT_802_11_LINK_STATUS *) kmalloc(sizeof(RT_802_11_LINK_STATUS), MEM_ALLOC_FLAG);
+            if (pLinkStatus)
+            {
+                pLinkStatus->CurrTxRate = RateIdTo500Kbps[pAdapter->CommonCfg.TxRate];   // unit : 500 kbps
+                pLinkStatus->ChannelQuality = pAdapter->Mlme.ChannelQuality;
+                pLinkStatus->RxByteCount = pAdapter->RalinkCounters.ReceivedByteCount;
+                pLinkStatus->TxByteCount = pAdapter->RalinkCounters.TransmittedByteCount;
+                       pLinkStatus->CentralChannel = pAdapter->CommonCfg.CentralChannel;
+                wrq->u.data.length = sizeof(RT_802_11_LINK_STATUS);
+                Status = copy_to_user(wrq->u.data.pointer, pLinkStatus, wrq->u.data.length);
+                kfree(pLinkStatus);
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS\n"));
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case OID_802_11_CONFIGURATION:
+            pConfiguration = (NDIS_802_11_CONFIGURATION *) kmalloc(sizeof(NDIS_802_11_CONFIGURATION), MEM_ALLOC_FLAG);
+            if (pConfiguration)
+            {
+                pConfiguration->Length = sizeof(NDIS_802_11_CONFIGURATION);
+                pConfiguration->BeaconPeriod = pAdapter->CommonCfg.BeaconPeriod;
+                pConfiguration->ATIMWindow = pAdapter->StaActive.AtimWin;
+                MAP_CHANNEL_ID_TO_KHZ(pAdapter->CommonCfg.Channel, pConfiguration->DSConfig);
+                wrq->u.data.length = sizeof(NDIS_802_11_CONFIGURATION);
+                Status = copy_to_user(wrq->u.data.pointer, pConfiguration, wrq->u.data.length);
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(BeaconPeriod=%ld,AtimW=%ld,Channel=%d) \n",
+                                        pConfiguration->BeaconPeriod, pConfiguration->ATIMWindow, pAdapter->CommonCfg.Channel));
+                               kfree(pConfiguration);
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+               case RT_OID_802_11_SNR_0:
+                       if ((pAdapter->StaCfg.LastSNR0 > 0))
+                       {
+                               ulInfo = ((0xeb - pAdapter->StaCfg.LastSNR0) * 3) /     16 ;
+                               wrq->u.data.length = sizeof(ulInfo);
+                               Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_SNR_0(0x=%lx)\n", ulInfo));
+                       }
+            else
+                           Status = -EFAULT;
+                       break;
+               case RT_OID_802_11_SNR_1:
+                       if ((pAdapter->Antenna.field.RxPath     > 1) &&
+                (pAdapter->StaCfg.LastSNR1 > 0))
+                       {
+                               ulInfo = ((0xeb - pAdapter->StaCfg.LastSNR1) * 3) /     16 ;
+                               wrq->u.data.length = sizeof(ulInfo);
+                               Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(0x=%lx)\n",ulInfo));
+                       }
+                       else
+                               Status = -EFAULT;
+            DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(pAdapter->StaCfg.LastSNR1=%d)\n",pAdapter->StaCfg.LastSNR1));
+                       break;
+        case OID_802_11_RSSI_TRIGGER:
+            ulInfo = pAdapter->StaCfg.RssiSample.LastRssi0 - pAdapter->BbpRssiToDbmDelta;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RSSI_TRIGGER(=%ld)\n", ulInfo));
+            break;
+               case OID_802_11_RSSI:
+        case RT_OID_802_11_RSSI:
+                       ulInfo = pAdapter->StaCfg.RssiSample.LastRssi0;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       break;
+               case RT_OID_802_11_RSSI_1:
+            ulInfo = pAdapter->StaCfg.RssiSample.LastRssi1;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       break;
+        case RT_OID_802_11_RSSI_2:
+            ulInfo = pAdapter->StaCfg.RssiSample.LastRssi2;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       break;
+        case OID_802_11_STATISTICS:
+            pStatistics = (NDIS_802_11_STATISTICS *) kmalloc(sizeof(NDIS_802_11_STATISTICS), MEM_ALLOC_FLAG);
+            if (pStatistics)
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS \n"));
+                // add the most up-to-date h/w raw counters into software counters
+                           NICUpdateRawCounters(pAdapter);
+
+                // Sanity check for calculation of sucessful count
+                if (pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart < pAdapter->WlanCounters.RetryCount.QuadPart)
+                    pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart;
+
+                pStatistics->TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart;
+                pStatistics->MulticastTransmittedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastTransmittedFrameCount.QuadPart;
+                pStatistics->FailedCount.QuadPart = pAdapter->WlanCounters.FailedCount.QuadPart;
+                pStatistics->RetryCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart;
+                pStatistics->MultipleRetryCount.QuadPart = pAdapter->WlanCounters.MultipleRetryCount.QuadPart;
+                pStatistics->RTSSuccessCount.QuadPart = pAdapter->WlanCounters.RTSSuccessCount.QuadPart;
+                pStatistics->RTSFailureCount.QuadPart = pAdapter->WlanCounters.RTSFailureCount.QuadPart;
+                pStatistics->ACKFailureCount.QuadPart = pAdapter->WlanCounters.ACKFailureCount.QuadPart;
+                pStatistics->FrameDuplicateCount.QuadPart = pAdapter->WlanCounters.FrameDuplicateCount.QuadPart;
+                pStatistics->ReceivedFragmentCount.QuadPart = pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart;
+                pStatistics->MulticastReceivedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastReceivedFrameCount.QuadPart;
+#ifdef DBG
+                pStatistics->FCSErrorCount = pAdapter->RalinkCounters.RealFcsErrCount;
+#else
+                pStatistics->FCSErrorCount.QuadPart = pAdapter->WlanCounters.FCSErrorCount.QuadPart;
+                pStatistics->FrameDuplicateCount.u.LowPart = pAdapter->WlanCounters.FrameDuplicateCount.u.LowPart / 100;
+#endif
+                wrq->u.data.length = sizeof(NDIS_802_11_STATISTICS);
+                Status = copy_to_user(wrq->u.data.pointer, pStatistics, wrq->u.data.length);
+                kfree(pStatistics);
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case OID_GEN_RCV_OK:
+            ulInfo = pAdapter->Counters8023.GoodReceives;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            break;
+        case OID_GEN_RCV_NO_BUFFER:
+            ulInfo = pAdapter->Counters8023.RxNoBuffer;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            break;
+        case RT_OID_802_11_PHY_MODE:
+            ulInfo = (ULONG)pAdapter->CommonCfg.PhyMode;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PHY_MODE (=%ld)\n", ulInfo));
+            break;
+        case RT_OID_802_11_STA_CONFIG:
+            pStaConfig = (RT_802_11_STA_CONFIG *) kmalloc(sizeof(RT_802_11_STA_CONFIG), MEM_ALLOC_FLAG);
+            if (pStaConfig)
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG\n"));
+                pStaConfig->EnableTxBurst = pAdapter->CommonCfg.bEnableTxBurst;
+                pStaConfig->EnableTurboRate = 0;
+                pStaConfig->UseBGProtection = pAdapter->CommonCfg.UseBGProtection;
+                pStaConfig->UseShortSlotTime = pAdapter->CommonCfg.bUseShortSlotTime;
+                //pStaConfig->AdhocMode = pAdapter->StaCfg.AdhocMode;
+                pStaConfig->HwRadioStatus = (pAdapter->StaCfg.bHwRadio == TRUE) ? 1 : 0;
+                pStaConfig->Rsv1 = 0;
+                pStaConfig->SystemErrorBitmap = pAdapter->SystemErrorBitmap;
+                wrq->u.data.length = sizeof(RT_802_11_STA_CONFIG);
+                Status = copy_to_user(wrq->u.data.pointer, pStaConfig, wrq->u.data.length);
+                kfree(pStaConfig);
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case OID_802_11_RTS_THRESHOLD:
+            RtsThresh = pAdapter->CommonCfg.RtsThreshold;
+            wrq->u.data.length = sizeof(RtsThresh);
+            Status = copy_to_user(wrq->u.data.pointer, &RtsThresh, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RTS_THRESHOLD(=%ld)\n", RtsThresh));
+            break;
+        case OID_802_11_FRAGMENTATION_THRESHOLD:
+            FragThresh = pAdapter->CommonCfg.FragmentThreshold;
+            if (pAdapter->CommonCfg.bUseZeroToDisableFragment == TRUE)
+                FragThresh = 0;
+            wrq->u.data.length = sizeof(FragThresh);
+            Status = copy_to_user(wrq->u.data.pointer, &FragThresh, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_FRAGMENTATION_THRESHOLD(=%ld)\n", FragThresh));
+            break;
+        case OID_802_11_POWER_MODE:
+            PowerMode = pAdapter->StaCfg.WindowsPowerMode;
+            wrq->u.data.length = sizeof(PowerMode);
+            Status = copy_to_user(wrq->u.data.pointer, &PowerMode, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_POWER_MODE(=%d)\n", PowerMode));
+            break;
+        case RT_OID_802_11_RADIO:
+            RadioState = (BOOLEAN) pAdapter->StaCfg.bSwRadio;
+            wrq->u.data.length = sizeof(RadioState);
+            Status = copy_to_user(wrq->u.data.pointer, &RadioState, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_RADIO (=%d)\n", RadioState));
+            break;
+        case OID_802_11_INFRASTRUCTURE_MODE:
+            if (pAdapter->StaCfg.BssType == BSS_ADHOC)
+                BssType = Ndis802_11IBSS;
+            else if (pAdapter->StaCfg.BssType == BSS_INFRA)
+                BssType = Ndis802_11Infrastructure;
+            else if (pAdapter->StaCfg.BssType == BSS_MONITOR)
+                BssType = Ndis802_11Monitor;
+            else
+                BssType = Ndis802_11AutoUnknown;
+
+            wrq->u.data.length = sizeof(BssType);
+            Status = copy_to_user(wrq->u.data.pointer, &BssType, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_INFRASTRUCTURE_MODE(=%d)\n", BssType));
+            break;
+        case RT_OID_802_11_PREAMBLE:
+            PreamType = pAdapter->CommonCfg.TxPreamble;
+            wrq->u.data.length = sizeof(PreamType);
+            Status = copy_to_user(wrq->u.data.pointer, &PreamType, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PREAMBLE(=%d)\n", PreamType));
+            break;
+        case OID_802_11_AUTHENTICATION_MODE:
+            AuthMode = pAdapter->StaCfg.AuthMode;
+            wrq->u.data.length = sizeof(AuthMode);
+            Status = copy_to_user(wrq->u.data.pointer, &AuthMode, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_AUTHENTICATION_MODE(=%d)\n", AuthMode));
+            break;
+        case OID_802_11_WEP_STATUS:
+            WepStatus = pAdapter->StaCfg.WepStatus;
+            wrq->u.data.length = sizeof(WepStatus);
+            Status = copy_to_user(wrq->u.data.pointer, &WepStatus, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEP_STATUS(=%d)\n", WepStatus));
+            break;
+        case OID_802_11_TX_POWER_LEVEL:
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.TxPower, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_TX_POWER_LEVEL %x\n",pAdapter->CommonCfg.TxPower));
+                       break;
+        case RT_OID_802_11_TX_POWER_LEVEL_1:
+            wrq->u.data.length = sizeof(ULONG);
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.TxPowerPercentage, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAdapter->CommonCfg.TxPowerPercentage));
+                       break;
+        case OID_802_11_NETWORK_TYPES_SUPPORTED:
+                       if ((pAdapter->RfIcType == RFIC_2850) || (pAdapter->RfIcType == RFIC_2750))
+                       {
+                               NetworkTypeList[0] = 3;                 // NumberOfItems = 3
+                               NetworkTypeList[1] = Ndis802_11DS;      // NetworkType[1] = 11b
+                               NetworkTypeList[2] = Ndis802_11OFDM24;  // NetworkType[2] = 11g
+                               NetworkTypeList[3] = Ndis802_11OFDM5;   // NetworkType[3] = 11a
+                wrq->u.data.length = 16;
+                               Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length);
+                       }
+                       else
+                       {
+                               NetworkTypeList[0] = 2;                 // NumberOfItems = 2
+                               NetworkTypeList[1] = Ndis802_11DS;      // NetworkType[1] = 11b
+                               NetworkTypeList[2] = Ndis802_11OFDM24;  // NetworkType[2] = 11g
+                           wrq->u.data.length = 12;
+                               Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length);
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_NETWORK_TYPES_SUPPORTED\n"));
+                               break;
+           case OID_802_11_NETWORK_TYPE_IN_USE:
+            wrq->u.data.length = sizeof(ULONG);
+                       if (pAdapter->CommonCfg.PhyMode == PHY_11A)
+                               ulInfo = Ndis802_11OFDM5;
+                       else if ((pAdapter->CommonCfg.PhyMode == PHY_11BG_MIXED) || (pAdapter->CommonCfg.PhyMode == PHY_11G))
+                               ulInfo = Ndis802_11OFDM24;
+                       else
+                               ulInfo = Ndis802_11DS;
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       break;
+        case RT_OID_802_11_QUERY_LAST_RX_RATE:
+            ulInfo = (ULONG)pAdapter->LastRxRate;
+            wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_RX_RATE (=%ld)\n", ulInfo));
+                       break;
+               case RT_OID_802_11_QUERY_LAST_TX_RATE:
+                       //ulInfo = (ULONG)pAdapter->LastTxRate;
+                       ulInfo = (ULONG)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_TX_RATE (=%lx)\n", ulInfo));
+                       break;
+        case RT_OID_802_11_QUERY_EEPROM_VERSION:
+            wrq->u.data.length = sizeof(ULONG);
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->EepromVersion, wrq->u.data.length);
+            break;
+        case RT_OID_802_11_QUERY_FIRMWARE_VERSION:
+            wrq->u.data.length = sizeof(ULONG);
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->FirmwareVersion, wrq->u.data.length);
+                       break;
+           case RT_OID_802_11_QUERY_NOISE_LEVEL:
+                       wrq->u.data.length = sizeof(UCHAR);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->BbpWriteLatch[66], wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_NOISE_LEVEL (=%d)\n", pAdapter->BbpWriteLatch[66]));
+                       break;
+           case RT_OID_802_11_EXTRA_INFO:
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->ExtraInfo, wrq->u.data.length);
+               DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_EXTRA_INFO (=%ld)\n", pAdapter->ExtraInfo));
+               break;
+           case RT_OID_WE_VERSION_COMPILED:
+               wrq->u.data.length = sizeof(UINT);
+               we_version_compiled = WIRELESS_EXT;
+               Status = copy_to_user(wrq->u.data.pointer, &we_version_compiled, wrq->u.data.length);
+               break;
+               case RT_OID_802_11_QUERY_APSD_SETTING:
+                       apsd = (pAdapter->CommonCfg.bAPSDCapable | (pAdapter->CommonCfg.bAPSDAC_BE << 1) | (pAdapter->CommonCfg.bAPSDAC_BK << 2)
+                               | (pAdapter->CommonCfg.bAPSDAC_VI << 3) | (pAdapter->CommonCfg.bAPSDAC_VO << 4) | (pAdapter->CommonCfg.MaxSPLength << 5));
+
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &apsd, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_SETTING (=0x%lx,APSDCap=%d,AC_BE=%d,AC_BK=%d,AC_VI=%d,AC_VO=%d,MAXSPLen=%d)\n",
+                               apsd,pAdapter->CommonCfg.bAPSDCapable,pAdapter->CommonCfg.bAPSDAC_BE,pAdapter->CommonCfg.bAPSDAC_BK,pAdapter->CommonCfg.bAPSDAC_VI,pAdapter->CommonCfg.bAPSDAC_VO,pAdapter->CommonCfg.MaxSPLength));
+                       break;
+               case RT_OID_802_11_QUERY_APSD_PSM:
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bAPSDForcePowerSave, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_PSM (=%d)\n", pAdapter->CommonCfg.bAPSDForcePowerSave));
+                       break;
+               case RT_OID_802_11_QUERY_WMM:
+                       wrq->u.data.length = sizeof(BOOLEAN);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bWmmCapable, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_WMM (=%d)\n",     pAdapter->CommonCfg.bWmmCapable));
+                       break;
+#ifdef WPA_SUPPLICANT_SUPPORT
+        case RT_OID_NEW_DRIVER:
+            {
+                UCHAR enabled = 1;
+               wrq->u.data.length = sizeof(UCHAR);
+               Status = copy_to_user(wrq->u.data.pointer, &enabled, wrq->u.data.length);
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_NEW_DRIVER (=%d)\n", enabled));
+            }
+               break;
+        case RT_OID_WPA_SUPPLICANT_SUPPORT:
+               wrq->u.data.length = sizeof(UCHAR);
+               Status = copy_to_user(wrq->u.data.pointer, &pAdapter->StaCfg.WpaSupplicantUP, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAdapter->StaCfg.WpaSupplicantUP));
+               break;
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+        case RT_OID_DRIVER_DEVICE_NAME:
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_DRIVER_DEVICE_NAME \n"));
+                       wrq->u.data.length = 16;
+                       if (copy_to_user(wrq->u.data.pointer, pAdapter->StaCfg.dev_name, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+            break;
+        case RT_OID_802_11_QUERY_HT_PHYMODE:
+            pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG);
+            if (pHTPhyMode)
+            {
+                pHTPhyMode->PhyMode = pAdapter->CommonCfg.PhyMode;
+                       pHTPhyMode->HtMode = (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE;
+                       pHTPhyMode->BW = (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.BW;
+                       pHTPhyMode->MCS= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS;
+                       pHTPhyMode->SHORTGI= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI;
+                       pHTPhyMode->STBC= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC;
+
+                       pHTPhyMode->ExtOffset = ((pAdapter->CommonCfg.CentralChannel < pAdapter->CommonCfg.Channel) ? (EXTCHA_BELOW) : (EXTCHA_ABOVE));
+                wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE);
+                if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n",
+                               pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset));
+                       DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word));
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case RT_OID_802_11_COUNTRY_REGION:
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_COUNTRY_REGION \n"));
+                       wrq->u.data.length = sizeof(ulInfo);
+            ulInfo = pAdapter->CommonCfg.CountryRegionForABand;
+            ulInfo = (ulInfo << 8)|(pAdapter->CommonCfg.CountryRegion);
+                       if (copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length))
+            {
+                               Status = -EFAULT;
+            }
+            break;
+        case RT_OID_802_11_QUERY_DAT_HT_PHYMODE:
+            pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG);
+            if (pHTPhyMode)
+            {
+                pHTPhyMode->PhyMode = pAdapter->CommonCfg.PhyMode;
+                       pHTPhyMode->HtMode = (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.HTMODE;
+                       pHTPhyMode->BW = (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.BW;
+                       pHTPhyMode->MCS= (UCHAR)pAdapter->StaCfg.DesiredTransmitSetting.field.MCS;
+                       pHTPhyMode->SHORTGI= (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.ShortGI;
+                       pHTPhyMode->STBC= (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.STBC;
+
+                wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE);
+                if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n",
+                               pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset));
+                       DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word));
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case RT_OID_QUERY_MULTIPLE_CARD_SUPPORT:
+                       wrq->u.data.length = sizeof(UCHAR);
+            i = 0;
+#ifdef MULTIPLE_CARD_SUPPORT
+            i = 1;
+#endif // MULTIPLE_CARD_SUPPORT //
+                       if (copy_to_user(wrq->u.data.pointer, &i, wrq->u.data.length))
+            {
+                               Status = -EFAULT;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_QUERY_MULTIPLE_CARD_SUPPORT(=%d) \n", i));
+            break;
+#ifdef SNMP_SUPPORT
+               case RT_OID_802_11_MAC_ADDRESS:
+            wrq->u.data.length = MAC_ADDR_LEN;
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_MANUFACTUREROUI:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREROUI \n"));
+                       wrq->u.data.length = ManufacturerOUI_LEN;
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_MANUFACTURERNAME:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTURERNAME \n"));
+                       wrq->u.data.length = strlen(ManufacturerNAME);
+                       Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_RESOURCETYPEIDNAME:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_RESOURCETYPEIDNAME \n"));
+                       wrq->u.data.length = strlen(ResourceTypeIdName);
+                       Status = copy_to_user(wrq->u.data.pointer, ResourceTypeIdName, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED \n"));
+                       ulInfo = 1; // 1 is support wep else 2 is not support.
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_POWERMANAGEMENTMODE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_POWERMANAGEMENTMODE \n"));
+                       if (pAdapter->StaCfg.Psm == PSMP_ACTION)
+                               ulInfo = 1; // 1 is power active else 2 is power save.
+                       else
+                               ulInfo = 2;
+
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       break;
+
+               case OID_802_11_WEPDEFAULTKEYVALUE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEPDEFAULTKEYVALUE \n"));
+                       //KeyIdxValue.KeyIdx = pAd->PortCfg.MBSSID[pAd->IoctlIF].DefaultKeyId;
+                       pKeyIdxValue = wrq->u.data.pointer;
+                       DBGPRINT(RT_DEBUG_TRACE,("KeyIdxValue.KeyIdx = %d, \n",pKeyIdxValue->KeyIdx));
+                       valueLen = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen;
+                       NdisMoveMemory(pKeyIdxValue->Value,
+                                                  &pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key,
+                                                  valueLen);
+                       pKeyIdxValue->Value[valueLen]='\0';
+
+                       wrq->u.data.length = sizeof(DefaultKeyIdxValue);
+
+                       Status = copy_to_user(wrq->u.data.pointer, pKeyIdxValue, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE,("DefaultKeyId = %d, total len = %d, str len=%d, KeyValue= %02x %02x %02x %02x \n", pAdapter->StaCfg.DefaultKeyId, wrq->u.data.length, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen,
+                       pAdapter->SharedKey[BSS0][0].Key[0],
+                       pAdapter->SharedKey[BSS0][1].Key[0],
+                       pAdapter->SharedKey[BSS0][2].Key[0],
+                       pAdapter->SharedKey[BSS0][3].Key[0]));
+                       break;
+
+               case OID_802_11_WEPDEFAULTKEYID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPDEFAULTKEYID \n"));
+                       wrq->u.data.length = sizeof(UCHAR);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->StaCfg.DefaultKeyId, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyId =%d \n", pAdapter->StaCfg.DefaultKeyId));
+                       break;
+
+               case RT_OID_802_11_WEPKEYMAPPINGLENGTH:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPKEYMAPPINGLENGTH \n"));
+                       wrq->u.data.length = sizeof(UCHAR);
+                       Status = copy_to_user(wrq->u.data.pointer,
+                                                                       &pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen,
+                                                                       wrq->u.data.length);
+                       break;
+
+               case OID_802_11_SHORTRETRYLIMIT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SHORTRETRYLIMIT \n"));
+                       wrq->u.data.length = sizeof(ULONG);
+                       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                       ShortRetryLimit = tx_rty_cfg.field.ShortRtyLimit;
+                       DBGPRINT(RT_DEBUG_TRACE, ("ShortRetryLimit =%ld,  tx_rty_cfg.field.ShortRetryLimit=%d\n", ShortRetryLimit, tx_rty_cfg.field.ShortRtyLimit));
+                       Status = copy_to_user(wrq->u.data.pointer, &ShortRetryLimit, wrq->u.data.length);
+                       break;
+
+               case OID_802_11_LONGRETRYLIMIT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_LONGRETRYLIMIT \n"));
+                       wrq->u.data.length = sizeof(ULONG);
+                       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                       LongRetryLimit = tx_rty_cfg.field.LongRtyLimit;
+                       DBGPRINT(RT_DEBUG_TRACE, ("LongRetryLimit =%ld,  tx_rty_cfg.field.LongRtyLimit=%d\n", LongRetryLimit, tx_rty_cfg.field.LongRtyLimit));
+                       Status = copy_to_user(wrq->u.data.pointer, &LongRetryLimit, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_PRODUCTID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRODUCTID \n"));
+
+#ifdef RT2870
+                       sprintf(tmp, "%04x %04x\n", ((POS_COOKIE)pAdapter->OS_Cookie)->pUsb_Dev->descriptor.idVendor ,((POS_COOKIE)pAdapter->OS_Cookie)->pUsb_Dev->descriptor.idProduct);
+
+#endif // RT2870 //
+                       wrq->u.data.length = strlen(tmp);
+                       Status = copy_to_user(wrq->u.data.pointer, tmp, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_MANUFACTUREID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREID \n"));
+                       wrq->u.data.length = strlen(ManufacturerNAME);
+                       Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length);
+                       break;
+
+               case OID_802_11_CURRENTCHANNEL:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CURRENTCHANNEL \n"));
+                       wrq->u.data.length = sizeof(UCHAR);
+                       DBGPRINT(RT_DEBUG_TRACE, ("sizeof UCHAR=%d, channel=%d \n", sizeof(UCHAR), pAdapter->CommonCfg.Channel));
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Channel, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       break;
+#endif //SNMP_SUPPORT
+
+               case OID_802_11_BUILD_CHANNEL_EX:
+                       {
+                               UCHAR value;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BUILD_CHANNEL_EX \n"));
+                               wrq->u.data.length = sizeof(UCHAR);
+#ifdef EXT_BUILD_CHANNEL_LIST
+                               DBGPRINT(RT_DEBUG_TRACE, ("Support EXT_BUILD_CHANNEL_LIST.\n"));
+                               value = 1;
+#else
+                               DBGPRINT(RT_DEBUG_TRACE, ("Doesn't support EXT_BUILD_CHANNEL_LIST.\n"));
+                               value = 0;
+#endif // EXT_BUILD_CHANNEL_LIST //
+                               Status = copy_to_user(wrq->u.data.pointer, &value, 1);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       }
+                       break;
+
+               case OID_802_11_GET_CH_LIST:
+                       {
+                               PRT_CHANNEL_LIST_INFO pChListBuf;
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CH_LIST \n"));
+                               if (pAdapter->ChannelListNum == 0)
+                               {
+                                       wrq->u.data.length = 0;
+                                       break;
+                               }
+
+                               pChListBuf = (RT_CHANNEL_LIST_INFO *) kmalloc(sizeof(RT_CHANNEL_LIST_INFO), MEM_ALLOC_FLAG);
+                               if (pChListBuf == NULL)
+                               {
+                                       wrq->u.data.length = 0;
+                                       break;
+                               }
+
+                               pChListBuf->ChannelListNum = pAdapter->ChannelListNum;
+                               for (i = 0; i < pChListBuf->ChannelListNum; i++)
+                                       pChListBuf->ChannelList[i] = pAdapter->ChannelList[i].Channel;
+
+                               wrq->u.data.length = sizeof(RT_CHANNEL_LIST_INFO);
+                               Status = copy_to_user(wrq->u.data.pointer, pChListBuf, sizeof(RT_CHANNEL_LIST_INFO));
+                               DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+
+                               if (pChListBuf)
+                                       kfree(pChListBuf);
+                       }
+                       break;
+
+               case OID_802_11_GET_COUNTRY_CODE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_COUNTRY_CODE \n"));
+                       wrq->u.data.length = 2;
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.CountryCode, 2);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       break;
+
+               case OID_802_11_GET_CHANNEL_GEOGRAPHY:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CHANNEL_GEOGRAPHY \n"));
+                       wrq->u.data.length = 1;
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Geography, 1);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       break;
+
+
+#ifdef QOS_DLS_SUPPORT
+               case RT_OID_802_11_QUERY_DLS:
+                       wrq->u.data.length = sizeof(BOOLEAN);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bDLSCapable, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS(=%d)\n", pAdapter->CommonCfg.bDLSCapable));
+                       break;
+
+               case RT_OID_802_11_QUERY_DLS_PARAM:
+                       {
+                               PRT_802_11_DLS_INFO     pDlsInfo = kmalloc(sizeof(RT_802_11_DLS_INFO), GFP_ATOMIC);
+                               if (pDlsInfo == NULL)
+                                       break;
+
+                               for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
+                               {
+                                       RTMPMoveMemory(&pDlsInfo->Entry[i], &pAdapter->StaCfg.DLSEntry[i], sizeof(RT_802_11_DLS_UI));
+                               }
+
+                               pDlsInfo->num = MAX_NUM_OF_DLS_ENTRY;
+                               wrq->u.data.length = sizeof(RT_802_11_DLS_INFO);
+                               Status = copy_to_user(wrq->u.data.pointer, pDlsInfo, wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS_PARAM\n"));
+
+                               if (pDlsInfo)
+                                       kfree(pDlsInfo);
+                       }
+                       break;
+#endif // QOS_DLS_SUPPORT //
+        default:
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::unknown IOCTL's subcmd = 0x%08x\n", cmd));
+            Status = -EOPNOTSUPP;
+            break;
+    }
+    return Status;
+}
+
+INT rt28xx_sta_ioctl(
+       IN      struct net_device       *net_dev,
+       IN      OUT     struct ifreq    *rq,
+       IN      INT                                     cmd)
+{
+       POS_COOKIE                      pObj;
+       VIRTUAL_ADAPTER         *pVirtualAd = NULL;
+       RTMP_ADAPTER        *pAd = NULL;
+       struct iwreq        *wrq = (struct iwreq *) rq;
+       BOOLEAN                         StateMachineTouched = FALSE;
+       INT                                     Status = NDIS_STATUS_SUCCESS;
+       USHORT                          subcmd;
+
+       if (net_dev->priv_flags == INT_MAIN)
+       {
+               pAd = net_dev->priv;
+       }
+       else
+       {
+               pVirtualAd = net_dev->priv;
+               pAd = pVirtualAd->RtmpDev->priv;
+       }
+       pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+       if (pAd == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+           if (wrq->u.data.pointer == NULL)
+           {
+                   return Status;
+           }
+
+           if (strstr(wrq->u.data.pointer, "OpMode") == NULL)
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+        {
+            DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+                   return -ENETDOWN;
+        }
+    }
+
+       {       // determine this ioctl command is comming from which interface.
+               pObj->ioctl_if_type = INT_MAIN;
+               pObj->ioctl_if = MAIN_MBSSID;
+       }
+
+       switch(cmd)
+       {
+#ifdef RALINK_ATE
+#ifdef RALINK_28xx_QA
+               case RTPRIV_IOCTL_ATE:
+                       {
+                               RtmpDoAte(pAd, wrq);
+                       }
+                       break;
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+        case SIOCGIFHWADDR:
+                       DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIFHWADDR\n"));
+                       memcpy(wrq->u.name, pAd->CurrentAddress, ETH_ALEN);
+                       break;
+               case SIOCGIWNAME:
+        {
+               char *name=&wrq->u.name[0];
+               rt_ioctl_giwname(net_dev, NULL, name, NULL);
+                       break;
+               }
+               case SIOCGIWESSID:  //Get ESSID
+        {
+               struct iw_point *essid=&wrq->u.essid;
+               rt_ioctl_giwessid(net_dev, NULL, essid, essid->pointer);
+                       break;
+               }
+               case SIOCSIWESSID:  //Set ESSID
+        {
+               struct iw_point *essid=&wrq->u.essid;
+               rt_ioctl_siwessid(net_dev, NULL, essid, essid->pointer);
+                       break;
+               }
+               case SIOCSIWNWID:   // set network id (the cell)
+               case SIOCGIWNWID:   // get network id
+                       Status = -EOPNOTSUPP;
+                       break;
+               case SIOCSIWFREQ:   //set channel/frequency (Hz)
+        {
+               struct iw_freq *freq=&wrq->u.freq;
+               rt_ioctl_siwfreq(net_dev, NULL, freq, NULL);
+                       break;
+               }
+               case SIOCGIWFREQ:   // get channel/frequency (Hz)
+        {
+               struct iw_freq *freq=&wrq->u.freq;
+               rt_ioctl_giwfreq(net_dev, NULL, freq, NULL);
+                       break;
+               }
+               case SIOCSIWNICKN: //set node name/nickname
+        {
+               struct iw_point *data=&wrq->u.data;
+               rt_ioctl_siwnickn(net_dev, NULL, data, NULL);
+                       break;
+               }
+               case SIOCGIWNICKN: //get node name/nickname
+        {
+               struct iw_point *data=&wrq->u.data;
+               rt_ioctl_giwnickn(net_dev, NULL, data, NULL);
+                       break;
+               }
+               case SIOCGIWRATE:   //get default bit rate (bps)
+                   rt_ioctl_giwrate(net_dev, NULL, &wrq->u, NULL);
+            break;
+           case SIOCSIWRATE:  //set default bit rate (bps)
+               rt_ioctl_siwrate(net_dev, NULL, &wrq->u, NULL);
+            break;
+        case SIOCGIWRTS:  // get RTS/CTS threshold (bytes)
+        {
+               struct iw_param *rts=&wrq->u.rts;
+               rt_ioctl_giwrts(net_dev, NULL, rts, NULL);
+                       break;
+               }
+        case SIOCSIWRTS:  //set RTS/CTS threshold (bytes)
+        {
+               struct iw_param *rts=&wrq->u.rts;
+               rt_ioctl_siwrts(net_dev, NULL, rts, NULL);
+                       break;
+               }
+        case SIOCGIWFRAG:  //get fragmentation thr (bytes)
+        {
+               struct iw_param *frag=&wrq->u.frag;
+               rt_ioctl_giwfrag(net_dev, NULL, frag, NULL);
+                       break;
+               }
+        case SIOCSIWFRAG:  //set fragmentation thr (bytes)
+        {
+               struct iw_param *frag=&wrq->u.frag;
+               rt_ioctl_siwfrag(net_dev, NULL, frag, NULL);
+                       break;
+               }
+        case SIOCGIWENCODE:  //get encoding token & mode
+        {
+               struct iw_point *erq=&wrq->u.encoding;
+               if(erq->pointer)
+                       rt_ioctl_giwencode(net_dev, NULL, erq, erq->pointer);
+                       break;
+               }
+        case SIOCSIWENCODE:  //set encoding token & mode
+        {
+               struct iw_point *erq=&wrq->u.encoding;
+               if(erq->pointer)
+                       rt_ioctl_siwencode(net_dev, NULL, erq, erq->pointer);
+                       break;
+               }
+               case SIOCGIWAP:     //get access point MAC addresses
+        {
+               struct sockaddr *ap_addr=&wrq->u.ap_addr;
+               rt_ioctl_giwap(net_dev, NULL, ap_addr, ap_addr->sa_data);
+                       break;
+               }
+           case SIOCSIWAP:  //set access point MAC addresses
+        {
+               struct sockaddr *ap_addr=&wrq->u.ap_addr;
+               rt_ioctl_siwap(net_dev, NULL, ap_addr, ap_addr->sa_data);
+                       break;
+               }
+               case SIOCGIWMODE:   //get operation mode
+        {
+               __u32 *mode=&wrq->u.mode;
+               rt_ioctl_giwmode(net_dev, NULL, mode, NULL);
+                       break;
+               }
+               case SIOCSIWMODE:   //set operation mode
+        {
+               __u32 *mode=&wrq->u.mode;
+               rt_ioctl_siwmode(net_dev, NULL, mode, NULL);
+                       break;
+               }
+               case SIOCGIWSENS:   //get sensitivity (dBm)
+               case SIOCSIWSENS:       //set sensitivity (dBm)
+               case SIOCGIWPOWER:  //get Power Management settings
+               case SIOCSIWPOWER:  //set Power Management settings
+               case SIOCGIWTXPOW:  //get transmit power (dBm)
+               case SIOCSIWTXPOW:  //set transmit power (dBm)
+               case SIOCGIWRANGE:      //Get range of parameters
+               case SIOCGIWRETRY:      //get retry limits and lifetime
+               case SIOCSIWRETRY:      //set retry limits and lifetime
+                       Status = -EOPNOTSUPP;
+                       break;
+               case RT_PRIV_IOCTL:
+                       subcmd = wrq->u.data.flags;
+                       if( subcmd & OID_GET_SET_TOGGLE)
+                               Status = RTMPSetInformation(pAd, rq, subcmd);
+                       else
+                               Status = RTMPQueryInformation(pAd, rq, subcmd);
+                       break;
+               case SIOCGIWPRIV:
+                       if (wrq->u.data.pointer)
+                       {
+                               if ( access_ok(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab)) != TRUE)
+                                       break;
+                               wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
+                               if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
+                                       Status = -EFAULT;
+                       }
+                       break;
+               case RTPRIV_IOCTL_SET:
+                       if(access_ok(VERIFY_READ, wrq->u.data.pointer, wrq->u.data.length) != TRUE)
+                               break;
+                       rt_ioctl_setparam(net_dev, NULL, NULL, wrq->u.data.pointer);
+                       break;
+               case RTPRIV_IOCTL_GSITESURVEY:
+                       RTMPIoctlGetSiteSurvey(pAd, wrq);
+                   break;
+#ifdef DBG
+               case RTPRIV_IOCTL_MAC:
+                       RTMPIoctlMAC(pAd, wrq);
+                       break;
+               case RTPRIV_IOCTL_E2P:
+                       RTMPIoctlE2PROM(pAd, wrq);
+                       break;
+#endif // DBG //
+        case SIOCETHTOOL:
+                break;
+               default:
+                       DBGPRINT(RT_DEBUG_ERROR, ("IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd));
+                       Status = -EOPNOTSUPP;
+                       break;
+       }
+
+    if(StateMachineTouched) // Upper layer sent a MLME-related operations
+       RT28XX_MLME_HANDLER(pAd);
+
+       return Status;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set SSID
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_SSID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    NDIS_802_11_SSID                    Ssid, *pSsid=NULL;
+    BOOLEAN                             StateMachineTouched = FALSE;
+    int                                 success = TRUE;
+
+    if( strlen(arg) <= MAX_LEN_OF_SSID)
+    {
+        NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID));
+        if (strlen(arg) != 0)
+        {
+            NdisMoveMemory(Ssid.Ssid, arg, strlen(arg));
+            Ssid.SsidLength = strlen(arg);
+        }
+        else   //ANY ssid
+        {
+            Ssid.SsidLength = 0;
+                   memcpy(Ssid.Ssid, "", 0);
+                       pAdapter->StaCfg.BssType = BSS_INFRA;
+                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+               pAdapter->StaCfg.WepStatus  = Ndis802_11EncryptionDisabled;
+               }
+        pSsid = &Ssid;
+
+        if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+        {
+            RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+            DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+        }
+
+        pAdapter->MlmeAux.CurrReqIsFromNdis = TRUE;
+        pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE;
+               pAdapter->bConfigChanged = TRUE;
+
+        MlmeEnqueue(pAdapter,
+                    MLME_CNTL_STATE_MACHINE,
+                    OID_802_11_SSID,
+                    sizeof(NDIS_802_11_SSID),
+                    (VOID *)pSsid);
+
+        StateMachineTouched = TRUE;
+        DBGPRINT(RT_DEBUG_TRACE, ("Set_SSID_Proc::(Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid));
+    }
+    else
+        success = FALSE;
+
+    if (StateMachineTouched) // Upper layer sent a MLME-related operations
+       RT28XX_MLME_HANDLER(pAdapter);
+
+    return success;
+}
+
+#ifdef WMM_SUPPORT
+/*
+    ==========================================================================
+    Description:
+        Set WmmCapable Enable or Disable
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_WmmCapable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       BOOLEAN bWmmCapable;
+
+       bWmmCapable = simple_strtol(arg, 0, 10);
+
+       if ((bWmmCapable == 1)
+#ifdef RT2870
+               && (pAd->NumberOfPipes >= 5)
+#endif // RT2870 //
+               )
+               pAd->CommonCfg.bWmmCapable = TRUE;
+       else if (bWmmCapable == 0)
+               pAd->CommonCfg.bWmmCapable = FALSE;
+       else
+               return FALSE;  //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_WmmCapable_Proc::(bWmmCapable=%d)\n",
+               pAd->CommonCfg.bWmmCapable));
+
+       return TRUE;
+}
+#endif // WMM_SUPPORT //
+
+/*
+    ==========================================================================
+    Description:
+        Set Network Type(Infrastructure/Adhoc mode)
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_NetworkType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    UINT32     Value = 0;
+
+    if (strcmp(arg, "Adhoc") == 0)
+       {
+               if (pAdapter->StaCfg.BssType != BSS_ADHOC)
+               {
+                       // Config has changed
+                       pAdapter->bConfigChanged = TRUE;
+            if (MONITOR_ON(pAdapter))
+            {
+                RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL);
+                RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value);
+                               Value &= (~0x80);
+                               RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value);
+                OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED);
+                pAdapter->StaCfg.bAutoReconnect = TRUE;
+                LinkDown(pAdapter, FALSE);
+            }
+                       if (INFRA_ON(pAdapter))
+                       {
+                               //BOOLEAN Cancelled;
+                               // Set the AutoReconnectSsid to prevent it reconnect to old SSID
+                               // Since calling this indicate user don't want to connect to that SSID anymore.
+                               pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+                               NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen);
+
+                               LinkDown(pAdapter, FALSE);
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event BB!\n"));
+                       }
+               }
+               pAdapter->StaCfg.BssType = BSS_ADHOC;
+        pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType;
+               DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(AD-HOC)\n"));
+       }
+    else if (strcmp(arg, "Infra") == 0)
+       {
+               if (pAdapter->StaCfg.BssType != BSS_INFRA)
+               {
+                       // Config has changed
+                       pAdapter->bConfigChanged = TRUE;
+            if (MONITOR_ON(pAdapter))
+            {
+                RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL);
+                RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value);
+                               Value &= (~0x80);
+                               RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value);
+                OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED);
+                pAdapter->StaCfg.bAutoReconnect = TRUE;
+                LinkDown(pAdapter, FALSE);
+            }
+                       if (ADHOC_ON(pAdapter))
+                       {
+                               // Set the AutoReconnectSsid to prevent it reconnect to old SSID
+                               // Since calling this indicate user don't want to connect to that SSID anymore.
+                               pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+                               NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen);
+
+                               LinkDown(pAdapter, FALSE);
+                       }
+               }
+               pAdapter->StaCfg.BssType = BSS_INFRA;
+        pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType;
+               DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(INFRA)\n"));
+
+        pAdapter->StaCfg.BssType = BSS_INFRA;
+       }
+    else if (strcmp(arg, "Monitor") == 0)
+    {
+               UCHAR   bbpValue = 0;
+               BCN_TIME_CFG_STRUC csr;
+               OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_INFRA_ON);
+        OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_ADHOC_ON);
+               OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED);
+               // disable all periodic state machine
+               pAdapter->StaCfg.bAutoReconnect = FALSE;
+               // reset all mlme state machine
+               RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+               DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_MEDIA_STATE_CONNECTED \n"));
+        if (pAdapter->CommonCfg.CentralChannel == 0)
+        {
+#ifdef DOT11_N_SUPPORT
+            if (pAdapter->CommonCfg.PhyMode == PHY_11AN_MIXED)
+                pAdapter->CommonCfg.CentralChannel = 36;
+            else
+#endif // DOT11_N_SUPPORT //
+                pAdapter->CommonCfg.CentralChannel = 6;
+        }
+#ifdef DOT11_N_SUPPORT
+        else
+            N_ChannelCheck(pAdapter);
+#endif // DOT11_N_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+       if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED &&
+            pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 &&
+            pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE)
+               {
+                       // 40MHz ,control channel at lower
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue);
+                       bbpValue &= (~0x18);
+                       bbpValue |= 0x10;
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue);
+                       pAdapter->CommonCfg.BBPCurrentBW = BW_40;
+                       //  RX : control channel at lower
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue);
+                       bbpValue &= (~0x20);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue);
+
+                       RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value);
+                       Value &= 0xfffffffe;
+                       RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value);
+                       pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel + 2;
+            AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE);
+                   AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel);
+            DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n",
+                                       pAdapter->CommonCfg.Channel,
+                                       pAdapter->CommonCfg.CentralChannel));
+               }
+               else if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED &&
+                 pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 &&
+                 pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)
+               {
+                       // 40MHz ,control channel at upper
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue);
+                       bbpValue &= (~0x18);
+                       bbpValue |= 0x10;
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue);
+                       pAdapter->CommonCfg.BBPCurrentBW = BW_40;
+                       RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value);
+                       Value |= 0x1;
+                       RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value);
+
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue);
+                       bbpValue |= (0x20);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue);
+                       pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel - 2;
+            AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE);
+                   AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel);
+            DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n",
+                                       pAdapter->CommonCfg.Channel,
+                                       pAdapter->CommonCfg.CentralChannel));
+               }
+               else
+#endif // DOT11_N_SUPPORT //
+               {
+                       // 20MHz
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue);
+                       bbpValue &= (~0x18);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue);
+                       pAdapter->CommonCfg.BBPCurrentBW = BW_20;
+                       AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.Channel, FALSE);
+                       AsicLockChannel(pAdapter, pAdapter->CommonCfg.Channel);
+                       DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAdapter->CommonCfg.Channel));
+               }
+               // Enable Rx with promiscuous reception
+               RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, 0x3);
+               // ASIC supporsts sniffer function with replacing RSSI with timestamp.
+               //RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value);
+               //Value |= (0x80);
+               //RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value);
+               // disable sync
+               RTMP_IO_READ32(pAdapter, BCN_TIME_CFG, &csr.word);
+               csr.field.bBeaconGen = 0;
+               csr.field.bTBTTEnable = 0;
+               csr.field.TsfSyncMode = 0;
+               RTMP_IO_WRITE32(pAdapter, BCN_TIME_CFG, csr.word);
+
+               pAdapter->StaCfg.BssType = BSS_MONITOR;
+        pAdapter->net_dev->type = ARPHRD_IEEE80211_PRISM; //ARPHRD_IEEE80211; // IEEE80211
+               DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(MONITOR)\n"));
+    }
+
+    // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key
+    pAdapter->StaCfg.WpaState = SS_NOTUSE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_NetworkType_Proc::(NetworkType=%d)\n", pAdapter->StaCfg.BssType));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Authentication mode
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_AuthMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch;
+    else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+    else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared;
+    else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK;
+    else if ((strcmp(arg, "WPANONE") == 0) || (strcmp(arg, "wpanone") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone;
+    else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK;
+#ifdef WPA_SUPPLICANT_SUPPORT
+    else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA;
+    else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2;
+#endif // WPA_SUPPLICANT_SUPPORT //
+    else
+        return FALSE;
+
+    pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_AuthMode_Proc::(AuthMode=%d)\n", pAdapter->StaCfg.AuthMode));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Encryption Type
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_EncrypType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11WEPDisabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11WEPDisabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11WEPDisabled;
+    }
+    else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11WEPEnabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11WEPEnabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11WEPEnabled;
+    }
+    else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11Encryption2Enabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11Encryption2Enabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11Encryption2Enabled;
+    }
+    else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11Encryption3Enabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11Encryption3Enabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11Encryption3Enabled;
+    }
+    else
+        return FALSE;
+
+    pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_EncrypType_Proc::(EncrypType=%d)\n", pAdapter->StaCfg.WepStatus));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Default Key ID
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_DefaultKeyID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    ULONG                               KeyIdx;
+
+    KeyIdx = simple_strtol(arg, 0, 10);
+    if((KeyIdx >= 1 ) && (KeyIdx <= 4))
+        pAdapter->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1 );
+    else
+        return FALSE;  //Invalid argument
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_DefaultKeyID_Proc::(DefaultKeyID=%d)\n", pAdapter->StaCfg.DefaultKeyId));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set WEP KEY1
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key1_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex"));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex"));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+
+    pAdapter->SharedKey[BSS0][0].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              0,
+                              pAdapter->SharedKey[BSS0][0].CipherAlg,
+                              pAdapter->SharedKey[BSS0][0].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+/*
+    ==========================================================================
+
+    Description:
+        Set WEP KEY2
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key2_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex"));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex"));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+    pAdapter->SharedKey[BSS0][1].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              1,
+                              pAdapter->SharedKey[BSS0][1].CipherAlg,
+                              pAdapter->SharedKey[BSS0][1].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+/*
+    ==========================================================================
+    Description:
+        Set WEP KEY3
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key3_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+    pAdapter->SharedKey[BSS0][2].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              2,
+                              pAdapter->SharedKey[BSS0][2].CipherAlg,
+                              pAdapter->SharedKey[BSS0][2].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+/*
+    ==========================================================================
+    Description:
+        Set WEP KEY4
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key4_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex"));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex"));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+    pAdapter->SharedKey[BSS0][3].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              3,
+                              pAdapter->SharedKey[BSS0][3].CipherAlg,
+                              pAdapter->SharedKey[BSS0][3].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set WPA PSK key
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_WPAPSK_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    UCHAR                   keyMaterial[40];
+
+    if ((pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) &&
+        (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) &&
+           (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone)
+               )
+        return TRUE;    // do nothing
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc::(WPAPSK=%s)\n", arg));
+
+    NdisZeroMemory(keyMaterial, 40);
+
+    if ((strlen(arg) < 8) || (strlen(arg) > 64))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("Set failed!!(WPAPSK=%s), WPAPSK key-string required 8 ~ 64 characters \n", arg));
+        return FALSE;
+    }
+
+    if (strlen(arg) == 64)
+    {
+        AtoH(arg, keyMaterial, 32);
+        NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32);
+
+    }
+    else
+    {
+        PasswordHash((char *)arg, pAdapter->MlmeAux.Ssid, pAdapter->MlmeAux.SsidLen, keyMaterial);
+        NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32);
+    }
+
+
+
+    if(pAdapter->StaCfg.BssType == BSS_ADHOC &&
+       pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+    {
+         pAdapter->StaCfg.WpaState = SS_NOTUSE;
+    }
+    else
+    {
+        // Start STA supplicant state machine
+        pAdapter->StaCfg.WpaState = SS_START;
+    }
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Power Saving mode
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_PSMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if (pAdapter->StaCfg.BssType == BSS_INFRA)
+    {
+        if ((strcmp(arg, "Max_PSP") == 0) ||
+                       (strcmp(arg, "max_psp") == 0) ||
+                       (strcmp(arg, "MAX_PSP") == 0))
+        {
+            // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+            // to exclude certain situations.
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP;
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            pAdapter->StaCfg.DefaultListenCount = 5;
+
+        }
+        else if ((strcmp(arg, "Fast_PSP") == 0) ||
+                                (strcmp(arg, "fast_psp") == 0) ||
+                 (strcmp(arg, "FAST_PSP") == 0))
+        {
+            // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+            // to exclude certain situations.
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP;
+            pAdapter->StaCfg.DefaultListenCount = 3;
+        }
+        else if ((strcmp(arg, "Legacy_PSP") == 0) ||
+                 (strcmp(arg, "legacy_psp") == 0) ||
+                 (strcmp(arg, "LEGACY_PSP") == 0))
+        {
+            // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+            // to exclude certain situations.
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP;
+            pAdapter->StaCfg.DefaultListenCount = 3;
+        }
+        else
+        {
+            //Default Ndis802_11PowerModeCAM
+            // clear PSM bit immediately
+            MlmeSetPsmBit(pAdapter, PWR_ACTIVE);
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM;
+        }
+
+        DBGPRINT(RT_DEBUG_TRACE, ("Set_PSMode_Proc::(PSMode=%ld)\n", pAdapter->StaCfg.WindowsPowerMode));
+    }
+    else
+        return FALSE;
+
+
+    return TRUE;
+}
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+/*
+    ==========================================================================
+    Description:
+        Set WpaSupport flag.
+    Value:
+        0: Driver ignore wpa_supplicant.
+        1: wpa_supplicant initiates scanning and AP selection.
+        2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters.
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Wpa_Support(
+    IN PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+
+    if ( simple_strtol(arg, 0, 10) == 0)
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE;
+    else if ( simple_strtol(arg, 0, 10) == 1)
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE;
+    else if ( simple_strtol(arg, 0, 10) == 2)
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE_WITH_WEB_UI;
+    else
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_Wpa_Support::(WpaSupplicantUP=%d)\n", pAd->StaCfg.WpaSupplicantUP));
+
+    return TRUE;
+}
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef DBG
+/*
+    ==========================================================================
+    Description:
+        Read / Write MAC
+    Arguments:
+        pAdapter                    Pointer to our adapter
+        wrq                         Pointer to the ioctl argument
+
+    Return Value:
+        None
+
+    Note:
+        Usage:
+               1.) iwpriv ra0 mac 0        ==> read MAC where Addr=0x0
+               2.) iwpriv ra0 mac 0=12     ==> write MAC where Addr=0x0, value=12
+    ==========================================================================
+*/
+VOID RTMPIoctlMAC(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq)
+{
+       CHAR                            *this_char;
+       CHAR                            *value;
+       INT                                     j = 0, k = 0;
+       CHAR                            msg[1024];
+       CHAR                            arg[255];
+       ULONG                           macAddr = 0;
+       UCHAR                           temp[16], temp2[16];
+       UINT32                          macValue = 0;
+       INT                                     Status;
+
+
+       memset(msg, 0x00, 1024);
+       if (wrq->u.data.length > 1) //No parameters.
+       {
+           Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length);
+               sprintf(msg, "\n");
+
+               //Parsing Read or Write
+           this_char = arg;
+               if (!*this_char)
+                       goto next;
+
+               if ((value = rtstrchr(this_char, '=')) != NULL)
+                       *value++ = 0;
+
+               if (!value || !*value)
+               { //Read
+                       // Sanity check
+                       if(strlen(this_char) > 4)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+
+                       // Mac Addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       if(strlen(this_char) == 4)
+                       {
+                               AtoH(this_char, temp, 2);
+                               macAddr = *temp*256 + temp[1];
+                               if (macAddr < 0xFFFF)
+                               {
+                                       RTMP_IO_READ32(pAdapter, macAddr, &macValue);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%lx, MacValue=%x\n", macAddr, macValue));
+                                       sprintf(msg+strlen(msg), "[0x%08lX]:%08X  ", macAddr , macValue);
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       goto next;
+                               }
+                       }
+               }
+               else
+               { //Write
+                       memcpy(&temp2, value, strlen(value));
+                       temp2[strlen(value)] = '\0';
+
+                       // Sanity check
+                       if((strlen(this_char) > 4) || strlen(temp2) > 8)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+
+                       j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               if(temp2[j] > 'f' || temp2[j] < '0')
+                                       return;
+                       }
+
+                       //MAC Addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       //MAC value
+                       k = j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               temp2[8-k+j] = temp2[j];
+                       }
+
+                       while(k < 8)
+                               temp2[7-k++]='0';
+                       temp2[8]='\0';
+
+                       {
+                               AtoH(this_char, temp, 2);
+                               macAddr = *temp*256 + temp[1];
+
+                               AtoH(temp2, temp, 4);
+                               macValue = *temp*256*256*256 + temp[1]*256*256 + temp[2]*256 + temp[3];
+
+                               // debug mode
+                               if (macAddr == (HW_DEBUG_SETTING_BASE + 4))
+                               {
+                                       // 0x2bf4: byte0 non-zero: enable R17 tuning, 0: disable R17 tuning
+                    if (macValue & 0x000000ff)
+                    {
+                        pAdapter->BbpTuning.bEnable = TRUE;
+                        DBGPRINT(RT_DEBUG_TRACE,("turn on R17 tuning\n"));
+                    }
+                    else
+                    {
+                        UCHAR R66;
+                        pAdapter->BbpTuning.bEnable = FALSE;
+                        R66 = 0x26 + GET_LNA_GAIN(pAdapter);
+#ifdef RALINK_ATE
+                                               if (ATE_ON(pAdapter))
+                                               {
+                                                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter)));
+                                               }
+                                               else
+#endif // RALINK_ATE //
+                                               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter)));
+                        DBGPRINT(RT_DEBUG_TRACE,("turn off R17 tuning, restore to 0x%02x\n", R66));
+                    }
+                                       return;
+                               }
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%02lx, MacValue=0x%x\n", macAddr, macValue));
+
+                               RTMP_IO_WRITE32(pAdapter, macAddr, macValue);
+                               sprintf(msg+strlen(msg), "[0x%08lX]:%08X  ", macAddr, macValue);
+                       }
+               }
+       }
+next:
+       if(strlen(msg) == 1)
+               sprintf(msg+strlen(msg), "===>Error command format!");
+
+       // Copy the information into the user buffer
+       wrq->u.data.length = strlen(msg);
+       Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlMAC\n\n"));
+}
+
+/*
+    ==========================================================================
+    Description:
+        Read / Write E2PROM
+    Arguments:
+        pAdapter                    Pointer to our adapter
+        wrq                         Pointer to the ioctl argument
+
+    Return Value:
+        None
+
+    Note:
+        Usage:
+               1.) iwpriv ra0 e2p 0            ==> read E2PROM where Addr=0x0
+               2.) iwpriv ra0 e2p 0=1234    ==> write E2PROM where Addr=0x0, value=1234
+    ==========================================================================
+*/
+VOID RTMPIoctlE2PROM(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq)
+{
+       CHAR                            *this_char;
+       CHAR                            *value;
+       INT                                     j = 0, k = 0;
+       CHAR                            msg[1024];
+       CHAR                            arg[255];
+       USHORT                          eepAddr = 0;
+       UCHAR                           temp[16], temp2[16];
+       USHORT                          eepValue;
+       int                                     Status;
+
+
+       memset(msg, 0x00, 1024);
+       if (wrq->u.data.length > 1) //No parameters.
+       {
+           Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length);
+               sprintf(msg, "\n");
+
+           //Parsing Read or Write
+               this_char = arg;
+
+
+               if (!*this_char)
+                       goto next;
+
+               if ((value = rtstrchr(this_char, '=')) != NULL)
+                       *value++ = 0;
+
+               if (!value || !*value)
+               { //Read
+
+                       // Sanity check
+                       if(strlen(this_char) > 4)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+
+                       // E2PROM addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       if(strlen(this_char) == 4)
+                       {
+                               AtoH(this_char, temp, 2);
+                               eepAddr = *temp*256 + temp[1];
+                               if (eepAddr < 0xFFFF)
+                               {
+                                       RT28xx_EEPROM_READ16(pAdapter, eepAddr, eepValue);
+                                       sprintf(msg+strlen(msg), "[0x%04X]:0x%04X  ", eepAddr , eepValue);
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       goto next;
+                               }
+                       }
+               }
+               else
+               { //Write
+                       memcpy(&temp2, value, strlen(value));
+                       temp2[strlen(value)] = '\0';
+
+                       // Sanity check
+                       if((strlen(this_char) > 4) || strlen(temp2) > 8)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+                       j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               if(temp2[j] > 'f' || temp2[j] < '0')
+                                       return;
+                       }
+
+                       //MAC Addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       //MAC value
+                       k = j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               temp2[4-k+j] = temp2[j];
+                       }
+
+                       while(k < 4)
+                               temp2[3-k++]='0';
+                       temp2[4]='\0';
+
+                       AtoH(this_char, temp, 2);
+                       eepAddr = *temp*256 + temp[1];
+
+                       AtoH(temp2, temp, 2);
+                       eepValue = *temp*256 + temp[1];
+
+                       RT28xx_EEPROM_WRITE16(pAdapter, eepAddr, eepValue);
+                       sprintf(msg+strlen(msg), "[0x%02X]:%02X  ", eepAddr, eepValue);
+               }
+       }
+next:
+       if(strlen(msg) == 1)
+               sprintf(msg+strlen(msg), "===>Error command format!");
+
+
+       // Copy the information into the user buffer
+       wrq->u.data.length = strlen(msg);
+       Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlE2PROM\n"));
+}
+#endif // DBG //
+
+
+
+
+INT Set_TGnWifiTest_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg)
+{
+    if (simple_strtol(arg, 0, 10) == 0)
+        pAd->StaCfg.bTGnWifiTest = FALSE;
+    else
+        pAd->StaCfg.bTGnWifiTest = TRUE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("IF Set_TGnWifiTest_Proc::(bTGnWifiTest=%d)\n", pAd->StaCfg.bTGnWifiTest));
+       return TRUE;
+}
+
+INT Set_LongRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg)
+{
+       TX_RTY_CFG_STRUC        tx_rty_cfg;
+       UCHAR                           LongRetryLimit = (UCHAR)simple_strtol(arg, 0, 10);
+
+       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+       tx_rty_cfg.field.LongRtyLimit = LongRetryLimit;
+       RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+       DBGPRINT(RT_DEBUG_TRACE, ("IF Set_LongRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word));
+       return TRUE;
+}
+
+INT Set_ShortRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg)
+{
+       TX_RTY_CFG_STRUC        tx_rty_cfg;
+       UCHAR                           ShortRetryLimit = (UCHAR)simple_strtol(arg, 0, 10);
+
+       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+       tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit;
+       RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+       DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ShortRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word));
+       return TRUE;
+}
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+INT Set_Ieee80211dClientMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if (simple_strtol(arg, 0, 10) == 0)
+        pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_None;
+    else if (simple_strtol(arg, 0, 10) == 1)
+        pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Flexible;
+    else if (simple_strtol(arg, 0, 10) == 2)
+        pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Strict;
+    else
+        return FALSE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_Ieee802dMode_Proc::(IEEEE0211dMode=%d)\n", pAdapter->StaCfg.IEEE80211dClientMode));
+    return TRUE;
+}
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+#ifdef CARRIER_DETECTION_SUPPORT
+INT Set_CarrierDetect_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg)
+{
+    if (simple_strtol(arg, 0, 10) == 0)
+        pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+    else
+        pAd->CommonCfg.CarrierDetect.Enable = TRUE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("IF Set_CarrierDetect_Proc::(CarrierDetect.Enable=%d)\n", pAd->CommonCfg.CarrierDetect.Enable));
+       return TRUE;
+}
+#endif // CARRIER_DETECTION_SUPPORT //
+
+
+INT    Show_Adhoc_MacTable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PCHAR                   extra)
+{
+       INT i;
+
+       sprintf(extra, "\n");
+
+#ifdef DOT11_N_SUPPORT
+       sprintf(extra, "%sHT Operating Mode : %d\n", extra, pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode);
+#endif // DOT11_N_SUPPORT //
+
+       sprintf(extra, "%s\n%-19s%-4s%-4s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s\n", extra,
+                       "MAC", "AID", "BSS", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC");
+
+       for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+
+               if (strlen(extra) > (IW_PRIV_SIZE_MASK - 30))
+                   break;
+               if ((pEntry->ValidAsCLI || pEntry->ValidAsApCli) && (pEntry->Sst == SST_ASSOC))
+               {
+                       sprintf(extra, "%s%02X:%02X:%02X:%02X:%02X:%02X  ", extra,
+                               pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+                               pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]);
+                       sprintf(extra, "%s%-4d", extra, (int)pEntry->Aid);
+                       sprintf(extra, "%s%-4d", extra, (int)pEntry->apidx);
+                       sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi0);
+                       sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi1);
+                       sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi2);
+                       sprintf(extra, "%s%-10s", extra, GetPhyMode(pEntry->HTPhyMode.field.MODE));
+                       sprintf(extra, "%s%-6s", extra, GetBW(pEntry->HTPhyMode.field.BW));
+                       sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.MCS);
+                       sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.ShortGI);
+                       sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.STBC);
+                       sprintf(extra, "%s%-10d, %d, %d%%\n", extra, pEntry->DebugFIFOCount, pEntry->DebugTxCount,
+                                               (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0);
+                       sprintf(extra, "%s\n", extra);
+               }
+       }
+
+       return TRUE;
+}
+
+
diff --git a/drivers/staging/rt2870/sta_ioctl.c.patch b/drivers/staging/rt2870/sta_ioctl.c.patch
new file mode 100644 (file)
index 0000000..8672b14
--- /dev/null
@@ -0,0 +1,18 @@
+--- sta_ioctl.c        2008-09-19 14:37:52.000000000 +0800
++++ sta_ioctl.c.fc9    2008-09-19 14:38:20.000000000 +0800
+@@ -49,15 +49,9 @@
+
+ #define GROUP_KEY_NO                4
+
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+ #define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E)              iwe_stream_add_event(_A, _B, _C, _D, _E)
+ #define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E)              iwe_stream_add_point(_A, _B, _C, _D, _E)
+ #define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F)  iwe_stream_add_value(_A, _B, _C, _D, _E, _F)
+-#else
+-#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E)              iwe_stream_add_event(_B, _C, _D, _E)
+-#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E)              iwe_stream_add_point(_B, _C, _D, _E)
+-#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F)  iwe_stream_add_value(_B, _C, _D, _E, _F)
+-#endif
+
+ extern UCHAR    CipherWpa2Template[];
+ extern UCHAR    CipherWpaPskTkip[];
diff --git a/drivers/staging/rt2870/tmp60 b/drivers/staging/rt2870/tmp60
new file mode 100644 (file)
index 0000000..992096a
--- /dev/null
@@ -0,0 +1,7037 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    sta_ioctl.c
+
+    Abstract:
+    IOCTL related subroutines
+
+    Revision History:
+    Who         When          What
+    --------    ----------    ----------------------------------------------
+    Rory Chen   01-03-2003    created
+       Rory Chen   02-14-2005    modify to support RT61
+*/
+
+#include       "rt_config.h"
+
+#ifdef DBG
+extern ULONG    RTDebugLevel;
+#endif
+
+#define NR_WEP_KEYS                            4
+#define WEP_SMALL_KEY_LEN                      (40/8)
+#define WEP_LARGE_KEY_LEN                      (104/8)
+
+#define GROUP_KEY_NO                4
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E)               iwe_stream_add_event(_A, _B, _C, _D, _E)
+#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E)               iwe_stream_add_point(_A, _B, _C, _D, _E)
+#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F)   iwe_stream_add_value(_A, _B, _C, _D, _E, _F)
+#else
+#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E)               iwe_stream_add_event(_B, _C, _D, _E)
+#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E)               iwe_stream_add_point(_B, _C, _D, _E)
+#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F)   iwe_stream_add_value(_B, _C, _D, _E, _F)
+#endif
+
+extern UCHAR    CipherWpa2Template[];
+extern UCHAR    CipherWpaPskTkip[];
+extern UCHAR    CipherWpaPskTkipLen;
+
+typedef struct PACKED _RT_VERSION_INFO{
+    UCHAR       DriverVersionW;
+    UCHAR       DriverVersionX;
+    UCHAR       DriverVersionY;
+    UCHAR       DriverVersionZ;
+    UINT        DriverBuildYear;
+    UINT        DriverBuildMonth;
+    UINT        DriverBuildDay;
+} RT_VERSION_INFO, *PRT_VERSION_INFO;
+
+struct iw_priv_args privtab[] = {
+{ RTPRIV_IOCTL_SET,
+  IW_PRIV_TYPE_CHAR | 1024, 0,
+  "set"},
+
+{ RTPRIV_IOCTL_SHOW, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  ""},
+{ RTPRIV_IOCTL_SHOW, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  ""},
+/* --- sub-ioctls definitions --- */
+    { SHOW_CONN_STATUS,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "connStatus" },
+       { SHOW_DRVIER_VERION,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "driverVer" },
+    { SHOW_BA_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "bainfo" },
+       { SHOW_DESC_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "descinfo" },
+    { RAIO_OFF,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_off" },
+       { RAIO_ON,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_on" },
+#ifdef QOS_DLS_SUPPORT
+       { SHOW_DLS_ENTRY_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "dlsentryinfo" },
+#endif // QOS_DLS_SUPPORT //
+       { SHOW_CFG_VALUE,
+         IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "show" },
+       { SHOW_ADHOC_ENTRY_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "adhocEntry" },
+
+/* --- sub-ioctls relations --- */
+
+#ifdef DBG
+{ RTPRIV_IOCTL_BBP,
+  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  "bbp"},
+{ RTPRIV_IOCTL_MAC,
+  IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024,
+  "mac"},
+{ RTPRIV_IOCTL_E2P,
+  IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024,
+  "e2p"},
+#endif  /* DBG */
+
+{ RTPRIV_IOCTL_STATISTICS,
+  0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  "stat"},
+{ RTPRIV_IOCTL_GSITESURVEY,
+  0, IW_PRIV_TYPE_CHAR | 1024,
+  "get_site_survey"},
+};
+
+INT Set_SSID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+#ifdef WMM_SUPPORT
+INT    Set_WmmCapable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif
+
+INT Set_NetworkType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_AuthMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_EncrypType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_DefaultKeyID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key1_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key2_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key3_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key4_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_WPAPSK_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+
+INT Set_PSMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+INT Set_Wpa_Support(
+    IN PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef DBG
+VOID RTMPIoctlBBP(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq);
+
+VOID RTMPIoctlMAC(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq);
+
+VOID RTMPIoctlE2PROM(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  struct iwreq    *wrq);
+#endif // DBG //
+
+
+NDIS_STATUS RTMPWPANoneAddKeyProc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN PVOID                   pBuf);
+
+INT Set_FragTest_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+#ifdef DOT11_N_SUPPORT
+INT Set_TGnWifiTest_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg);
+#endif // DOT11_N_SUPPORT //
+
+INT Set_LongRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg);
+
+INT Set_ShortRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg);
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+INT Set_Ieee80211dClientMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+#ifdef CARRIER_DETECTION_SUPPORT
+INT Set_CarrierDetect_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg);
+#endif // CARRIER_DETECTION_SUPPORT //
+
+INT    Show_Adhoc_MacTable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PCHAR                   extra);
+
+static struct {
+       CHAR *name;
+       INT (*set_proc)(PRTMP_ADAPTER pAdapter, PUCHAR arg);
+} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = {
+       {"DriverVersion",                               Set_DriverVersion_Proc},
+       {"CountryRegion",                               Set_CountryRegion_Proc},
+       {"CountryRegionABand",                  Set_CountryRegionABand_Proc},
+       {"SSID",                                                Set_SSID_Proc},
+       {"WirelessMode",                                Set_WirelessMode_Proc},
+       {"TxBurst",                                     Set_TxBurst_Proc},
+       {"TxPreamble",                          Set_TxPreamble_Proc},
+       {"TxPower",                                     Set_TxPower_Proc},
+       {"Channel",                                     Set_Channel_Proc},
+       {"BGProtection",                                Set_BGProtection_Proc},
+       {"RTSThreshold",                                Set_RTSThreshold_Proc},
+       {"FragThreshold",                               Set_FragThreshold_Proc},
+#ifdef DOT11_N_SUPPORT
+       {"HtBw",                                Set_HtBw_Proc},
+       {"HtMcs",                               Set_HtMcs_Proc},
+       {"HtGi",                                Set_HtGi_Proc},
+       {"HtOpMode",                        Set_HtOpMode_Proc},
+       {"HtExtcha",                        Set_HtExtcha_Proc},
+       {"HtMpduDensity",                       Set_HtMpduDensity_Proc},
+       {"HtBaWinSize",                         Set_HtBaWinSize_Proc},
+       {"HtRdg",                                       Set_HtRdg_Proc},
+       {"HtAmsdu",                                     Set_HtAmsdu_Proc},
+       {"HtAutoBa",                            Set_HtAutoBa_Proc},
+       {"HtBaDecline",                                 Set_BADecline_Proc},
+       {"HtProtect",                           Set_HtProtect_Proc},
+       {"HtMimoPs",                            Set_HtMimoPs_Proc},
+#endif // DOT11_N_SUPPORT //
+
+#ifdef AGGREGATION_SUPPORT
+       {"PktAggregate",                                Set_PktAggregate_Proc},
+#endif
+
+#ifdef WMM_SUPPORT
+       {"WmmCapable",                                  Set_WmmCapable_Proc},
+#endif
+       {"IEEE80211H",                                  Set_IEEE80211H_Proc},
+    {"NetworkType",                 Set_NetworkType_Proc},
+       {"AuthMode",                                    Set_AuthMode_Proc},
+       {"EncrypType",                                  Set_EncrypType_Proc},
+       {"DefaultKeyID",                                Set_DefaultKeyID_Proc},
+       {"Key1",                                                Set_Key1_Proc},
+       {"Key2",                                                Set_Key2_Proc},
+       {"Key3",                                                Set_Key3_Proc},
+       {"Key4",                                                Set_Key4_Proc},
+       {"WPAPSK",                                              Set_WPAPSK_Proc},
+       {"ResetCounter",                                Set_ResetStatCounter_Proc},
+       {"PSMode",                      Set_PSMode_Proc},
+#ifdef DBG
+       {"Debug",                                               Set_Debug_Proc},
+#endif
+
+#ifdef RALINK_ATE
+       {"ATE",                                                 Set_ATE_Proc},
+       {"ATEDA",                                               Set_ATE_DA_Proc},
+       {"ATESA",                                               Set_ATE_SA_Proc},
+       {"ATEBSSID",                                    Set_ATE_BSSID_Proc},
+       {"ATECHANNEL",                                  Set_ATE_CHANNEL_Proc},
+       {"ATETXPOW0",                                   Set_ATE_TX_POWER0_Proc},
+       {"ATETXPOW1",                                   Set_ATE_TX_POWER1_Proc},
+       {"ATETXANT",                                    Set_ATE_TX_Antenna_Proc},
+       {"ATERXANT",                                    Set_ATE_RX_Antenna_Proc},
+       {"ATETXFREQOFFSET",                             Set_ATE_TX_FREQOFFSET_Proc},
+       {"ATETXBW",                                             Set_ATE_TX_BW_Proc},
+       {"ATETXLEN",                                    Set_ATE_TX_LENGTH_Proc},
+       {"ATETXCNT",                                    Set_ATE_TX_COUNT_Proc},
+       {"ATETXMCS",                                    Set_ATE_TX_MCS_Proc},
+       {"ATETXMODE",                                   Set_ATE_TX_MODE_Proc},
+       {"ATETXGI",                                             Set_ATE_TX_GI_Proc},
+       {"ATERXFER",                                    Set_ATE_RX_FER_Proc},
+       {"ATERRF",                                              Set_ATE_Read_RF_Proc},
+       {"ATEWRF1",                                             Set_ATE_Write_RF1_Proc},
+       {"ATEWRF2",                                             Set_ATE_Write_RF2_Proc},
+       {"ATEWRF3",                                             Set_ATE_Write_RF3_Proc},
+       {"ATEWRF4",                                             Set_ATE_Write_RF4_Proc},
+       {"ATELDE2P",                                Set_ATE_Load_E2P_Proc},
+       {"ATERE2P",                                             Set_ATE_Read_E2P_Proc},
+       {"ATESHOW",                                             Set_ATE_Show_Proc},
+       {"ATEHELP",                                             Set_ATE_Help_Proc},
+
+#ifdef RALINK_28xx_QA
+       {"TxStop",                                              Set_TxStop_Proc},
+       {"RxStop",                                              Set_RxStop_Proc},
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+    {"WpaSupport",                  Set_Wpa_Support},
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+
+
+       {"FixedTxMode",                 Set_FixedTxMode_Proc},
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+       {"OpMode",                                              Set_OpMode_Proc},
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+#ifdef DOT11_N_SUPPORT
+    {"TGnWifiTest",                 Set_TGnWifiTest_Proc},
+    {"ForceGF",                                        Set_ForceGF_Proc},
+#endif // DOT11_N_SUPPORT //
+#ifdef QOS_DLS_SUPPORT
+       {"DlsAddEntry",                                 Set_DlsAddEntry_Proc},
+       {"DlsTearDownEntry",                    Set_DlsTearDownEntry_Proc},
+#endif // QOS_DLS_SUPPORT //
+       {"LongRetry",                           Set_LongRetryLimit_Proc},
+       {"ShortRetry",                          Set_ShortRetryLimit_Proc},
+#ifdef EXT_BUILD_CHANNEL_LIST
+       {"11dClientMode",                               Set_Ieee80211dClientMode_Proc},
+#endif // EXT_BUILD_CHANNEL_LIST //
+#ifdef CARRIER_DETECTION_SUPPORT
+       {"CarrierDetect",                               Set_CarrierDetect_Proc},
+#endif // CARRIER_DETECTION_SUPPORT //
+
+       {NULL,}
+};
+
+
+VOID RTMPAddKey(
+       IN      PRTMP_ADAPTER       pAd,
+       IN      PNDIS_802_11_KEY    pKey)
+{
+       ULONG                           KeyIdx;
+       MAC_TABLE_ENTRY         *pEntry;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey ------>\n"));
+
+       if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+       {
+               if (pKey->KeyIndex & 0x80000000)
+               {
+                   if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+            {
+                NdisZeroMemory(pAd->StaCfg.PMK, 32);
+                NdisMoveMemory(pAd->StaCfg.PMK, pKey->KeyMaterial, pKey->KeyLength);
+                goto end;
+            }
+                   // Update PTK
+                   NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
+            pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
+            NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pKey->KeyMaterial, LEN_TKIP_EK);
+#ifdef WPA_SUPPLICANT_SUPPORT
+            if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+            {
+                NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+            else
+#endif // WPA_SUPPLICANT_SUPPORT //
+            {
+               NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+
+            // Decide its ChiperAlg
+               if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+                       pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
+               else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
+                       pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
+               else
+                       pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE;
+
+            // Update these related information to MAC_TABLE_ENTRY
+               pEntry = &pAd->MacTab.Content[BSSID_WCID];
+            NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[BSS0][0].Key, LEN_TKIP_EK);
+               NdisMoveMemory(pEntry->PairwiseKey.RxMic, pAd->SharedKey[BSS0][0].RxMic, LEN_TKIP_RXMICK);
+               NdisMoveMemory(pEntry->PairwiseKey.TxMic, pAd->SharedKey[BSS0][0].TxMic, LEN_TKIP_TXMICK);
+               pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
+
+               // Update pairwise key information to ASIC Shared Key Table
+               AsicAddSharedKeyEntry(pAd,
+                                                         BSS0,
+                                                         0,
+                                                         pAd->SharedKey[BSS0][0].CipherAlg,
+                                                         pAd->SharedKey[BSS0][0].Key,
+                                                         pAd->SharedKey[BSS0][0].TxMic,
+                                                         pAd->SharedKey[BSS0][0].RxMic);
+
+               // Update ASIC WCID attribute table and IVEIV table
+               RTMPAddWcidAttributeEntry(pAd,
+                                                                 BSS0,
+                                                                 0,
+                                                                 pAd->SharedKey[BSS0][0].CipherAlg,
+                                                                 pEntry);
+
+            if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2)
+            {
+                // set 802.1x port control
+                   //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               STA_PORT_SECURED(pAd);
+
+                // Indicate Connected for GUI
+                pAd->IndicateMediaState = NdisMediaStateConnected;
+            }
+               }
+        else
+        {
+            // Update GTK
+            pAd->StaCfg.DefaultKeyId = (pKey->KeyIndex & 0xFF);
+            NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY));
+            pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK;
+            NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKey->KeyMaterial, LEN_TKIP_EK);
+#ifdef WPA_SUPPLICANT_SUPPORT
+            if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
+            {
+                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+            else
+#endif // WPA_SUPPLICANT_SUPPORT //
+            {
+               NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+
+            // Update Shared Key CipherAlg
+               pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE;
+               if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP;
+               else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES;
+
+            // Update group key information to ASIC Shared Key Table
+               AsicAddSharedKeyEntry(pAd,
+                                                         BSS0,
+                                                         pAd->StaCfg.DefaultKeyId,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic);
+
+               // Update ASIC WCID attribute table and IVEIV table
+               RTMPAddWcidAttributeEntry(pAd,
+                                                                 BSS0,
+                                                                 pAd->StaCfg.DefaultKeyId,
+                                                                 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+                                                                 NULL);
+
+            // set 802.1x port control
+               //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAd);
+
+            // Indicate Connected for GUI
+            pAd->IndicateMediaState = NdisMediaStateConnected;
+        }
+       }
+       else    // dynamic WEP from wpa_supplicant
+       {
+               UCHAR   CipherAlg;
+       PUCHAR  Key;
+
+               if(pKey->KeyLength == 32)
+                       goto end;
+
+               KeyIdx = pKey->KeyIndex & 0x0fffffff;
+
+               if (KeyIdx < 4)
+               {
+                       // it is a default shared key, for Pairwise key setting
+                       if (pKey->KeyIndex & 0x80000000)
+                       {
+                               pEntry = MacTableLookup(pAd, pKey->BSSID);
+
+                               if (pEntry)
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey: Set Pair-wise Key\n"));
+
+                                       // set key material and key length
+                                       pEntry->PairwiseKey.KeyLen = (UCHAR)pKey->KeyLength;
+                                       NdisMoveMemory(pEntry->PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength);
+
+                                       // set Cipher type
+                                       if (pKey->KeyLength == 5)
+                                               pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64;
+                                       else
+                                               pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128;
+
+                                       // Add Pair-wise key to Asic
+                                       AsicAddPairwiseKeyEntry(
+                                               pAd,
+                                               pEntry->Addr,
+                                               (UCHAR)pEntry->Aid,
+                               &pEntry->PairwiseKey);
+
+                                       // update WCID attribute table and IVEIV table for this entry
+                                       RTMPAddWcidAttributeEntry(
+                                               pAd,
+                                               BSS0,
+                                               KeyIdx, // The value may be not zero
+                                               pEntry->PairwiseKey.CipherAlg,
+                                               pEntry);
+
+                               }
+                       }
+                       else
+            {
+                               // Default key for tx (shared key)
+                               pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx;
+
+                               // set key material and key length
+                               pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pKey->KeyLength;
+                               NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength);
+
+                               // Set Ciper type
+                               if (pKey->KeyLength == 5)
+                                       pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP64;
+                               else
+                                       pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP128;
+
+                       CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
+                       Key = pAd->SharedKey[BSS0][KeyIdx].Key;
+
+                               // Set Group key material to Asic
+                       AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL);
+
+                               // Update WCID attribute table and IVEIV table for this group key table
+                               RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, CipherAlg, NULL);
+
+                       }
+               }
+       }
+end:
+       return;
+}
+
+char * rtstrchr(const char * s, int c)
+{
+    for(; *s != (char) c; ++s)
+        if (*s == '\0')
+            return NULL;
+    return (char *) s;
+}
+
+/*
+This is required for LinEX2004/kernel2.6.7 to provide iwlist scanning function
+*/
+
+int
+rt_ioctl_giwname(struct net_device *dev,
+                  struct iw_request_info *info,
+                  char *name, char *extra)
+{
+//     PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+#ifdef RT2870
+       strncpy(name, "RT2870 Wireless", IFNAMSIZ);
+#endif // RT2870 //
+       return 0;
+}
+
+int rt_ioctl_siwfreq(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_freq *freq, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       int     chan = -1;
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+        return -ENETDOWN;
+    }
+
+
+       if (freq->e > 1)
+               return -EINVAL;
+
+       if((freq->e == 0) && (freq->m <= 1000))
+               chan = freq->m; // Setting by channel number
+       else
+               MAP_KHZ_TO_CHANNEL_ID( (freq->m /100) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G,
+
+    if (ChannelSanity(pAdapter, chan) == TRUE)
+    {
+       pAdapter->CommonCfg.Channel = chan;
+       DBGPRINT(RT_DEBUG_ERROR, ("==>rt_ioctl_siwfreq::SIOCSIWFREQ[cmd=0x%x] (Channel=%d)\n", SIOCSIWFREQ, pAdapter->CommonCfg.Channel));
+    }
+    else
+        return -EINVAL;
+
+       return 0;
+}
+int rt_ioctl_giwfreq(struct net_device *dev,
+                  struct iw_request_info *info,
+                  struct iw_freq *freq, char *extra)
+{
+    VIRTUAL_ADAPTER *pVirtualAd = NULL;
+       PRTMP_ADAPTER pAdapter = NULL;
+       UCHAR ch;
+       ULONG   m;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+               ch = pAdapter->CommonCfg.Channel;
+
+       DBGPRINT(RT_DEBUG_TRACE,("==>rt_ioctl_giwfreq  %d\n", ch));
+
+    MAP_CHANNEL_ID_TO_KHZ(ch, m);
+       freq->m = m * 100;
+       freq->e = 1;
+       return 0;
+}
+
+int rt_ioctl_siwmode(struct net_device *dev,
+                  struct iw_request_info *info,
+                  __u32 *mode, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+       DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+    }
+
+       switch (*mode)
+       {
+               case IW_MODE_ADHOC:
+                       Set_NetworkType_Proc(pAdapter, "Adhoc");
+                       break;
+               case IW_MODE_INFRA:
+                       Set_NetworkType_Proc(pAdapter, "Infra");
+                       break;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
+        case IW_MODE_MONITOR:
+                       Set_NetworkType_Proc(pAdapter, "Monitor");
+                       break;
+#endif
+               default:
+                       DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_siwmode::SIOCSIWMODE (unknown %d)\n", *mode));
+                       return -EINVAL;
+       }
+
+       // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key
+       pAdapter->StaCfg.WpaState = SS_NOTUSE;
+
+       return 0;
+}
+
+int rt_ioctl_giwmode(struct net_device *dev,
+                  struct iw_request_info *info,
+                  __u32 *mode, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       if (ADHOC_ON(pAdapter))
+               *mode = IW_MODE_ADHOC;
+    else if (INFRA_ON(pAdapter))
+               *mode = IW_MODE_INFRA;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
+    else if (MONITOR_ON(pAdapter))
+    {
+        *mode = IW_MODE_MONITOR;
+    }
+#endif
+    else
+        *mode = IW_MODE_AUTO;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("==>rt_ioctl_giwmode(mode=%d)\n", *mode));
+       return 0;
+}
+
+int rt_ioctl_siwsens(struct net_device *dev,
+                  struct iw_request_info *info,
+                  char *name, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       return 0;
+}
+
+int rt_ioctl_giwsens(struct net_device *dev,
+                  struct iw_request_info *info,
+                  char *name, char *extra)
+{
+       return 0;
+}
+
+int rt_ioctl_giwrange(struct net_device *dev,
+                  struct iw_request_info *info,
+                  struct iw_point *data, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+       struct iw_range *range = (struct iw_range *) extra;
+       u16 val;
+       int i;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE ,("===>rt_ioctl_giwrange\n"));
+       data->length = sizeof(struct iw_range);
+       memset(range, 0, sizeof(struct iw_range));
+
+       range->txpower_capa = IW_TXPOW_DBM;
+
+       if (INFRA_ON(pAdapter)||ADHOC_ON(pAdapter))
+       {
+               range->min_pmp = 1 * 1024;
+               range->max_pmp = 65535 * 1024;
+               range->min_pmt = 1 * 1024;
+               range->max_pmt = 1000 * 1024;
+               range->pmp_flags = IW_POWER_PERIOD;
+               range->pmt_flags = IW_POWER_TIMEOUT;
+               range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT |
+                       IW_POWER_UNICAST_R | IW_POWER_ALL_R;
+       }
+
+       range->we_version_compiled = WIRELESS_EXT;
+       range->we_version_source = 14;
+
+       range->retry_capa = IW_RETRY_LIMIT;
+       range->retry_flags = IW_RETRY_LIMIT;
+       range->min_retry = 0;
+       range->max_retry = 255;
+
+       range->num_channels =  pAdapter->ChannelListNum;
+
+       val = 0;
+       for (i = 1; i <= range->num_channels; i++)
+       {
+               u32 m;
+               range->freq[val].i = pAdapter->ChannelList[i-1].Channel;
+               MAP_CHANNEL_ID_TO_KHZ(pAdapter->ChannelList[i-1].Channel, m);
+               range->freq[val].m = m * 100; /* HZ */
+
+               range->freq[val].e = 1;
+               val++;
+               if (val == IW_MAX_FREQUENCIES)
+                       break;
+       }
+       range->num_frequency = val;
+
+       range->max_qual.qual = 100; /* what is correct max? This was not
+                                       * documented exactly. At least
+                                       * 69 has been observed. */
+       range->max_qual.level = 0; /* dB */
+       range->max_qual.noise = 0; /* dB */
+
+       /* What would be suitable values for "average/typical" qual? */
+       range->avg_qual.qual = 20;
+       range->avg_qual.level = -60;
+       range->avg_qual.noise = -95;
+       range->sensitivity = 3;
+
+       range->max_encoding_tokens = NR_WEP_KEYS;
+       range->num_encoding_sizes = 2;
+       range->encoding_size[0] = 5;
+       range->encoding_size[1] = 13;
+
+       range->min_rts = 0;
+       range->max_rts = 2347;
+       range->min_frag = 256;
+       range->max_frag = 2346;
+
+#if WIRELESS_EXT > 17
+       /* IW_ENC_CAPA_* bit field */
+       range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+                                       IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+#endif
+
+       return 0;
+}
+
+int rt_ioctl_siwap(struct net_device *dev,
+                     struct iw_request_info *info,
+                     struct sockaddr *ap_addr, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+    NDIS_802_11_MAC_ADDRESS Bssid;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+    }
+
+       if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+    {
+        RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+        DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+    }
+
+    // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+    // this request, because this request is initiated by NDIS.
+    pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+       // Prevent to connect AP again in STAMlmePeriodicExec
+       pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+
+    memset(Bssid, 0, MAC_ADDR_LEN);
+    memcpy(Bssid, ap_addr->sa_data, MAC_ADDR_LEN);
+    MlmeEnqueue(pAdapter,
+                MLME_CNTL_STATE_MACHINE,
+                OID_802_11_BSSID,
+                sizeof(NDIS_802_11_MAC_ADDRESS),
+                (VOID *)&Bssid);
+
+    DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCSIWAP %02x:%02x:%02x:%02x:%02x:%02x\n",
+        Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
+
+       return 0;
+}
+
+int rt_ioctl_giwap(struct net_device *dev,
+                     struct iw_request_info *info,
+                     struct sockaddr *ap_addr, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
+       {
+               ap_addr->sa_family = ARPHRD_ETHER;
+               memcpy(ap_addr->sa_data, &pAdapter->CommonCfg.Bssid, ETH_ALEN);
+       }
+#ifdef WPA_SUPPLICANT_SUPPORT
+    // Add for RT2870
+    else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+    {
+        ap_addr->sa_family = ARPHRD_ETHER;
+        memcpy(ap_addr->sa_data, &pAdapter->MlmeAux.Bssid, ETH_ALEN);
+    }
+#endif // WPA_SUPPLICANT_SUPPORT //
+       else
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=EMPTY)\n"));
+               return -ENOTCONN;
+       }
+
+       return 0;
+}
+
+/*
+ * Units are in db above the noise floor. That means the
+ * rssi values reported in the tx/rx descriptors in the
+ * driver are the SNR expressed in db.
+ *
+ * If you assume that the noise floor is -95, which is an
+ * excellent assumption 99.5 % of the time, then you can
+ * derive the absolute signal level (i.e. -95 + rssi).
+ * There are some other slight factors to take into account
+ * depending on whether the rssi measurement is from 11b,
+ * 11g, or 11a.   These differences are at most 2db and
+ * can be documented.
+ *
+ * NB: various calculations are based on the orinoco/wavelan
+ *     drivers for compatibility
+ */
+static void set_quality(PRTMP_ADAPTER pAdapter,
+                        struct iw_quality *iq,
+                        signed char rssi)
+{
+       __u8 ChannelQuality;
+
+       // Normalize Rssi
+       if (rssi >= -50)
+               ChannelQuality = 100;
+       else if (rssi >= -80) // between -50 ~ -80dbm
+               ChannelQuality = (__u8)(24 + ((rssi + 80) * 26)/10);
+       else if (rssi >= -90)   // between -80 ~ -90dbm
+        ChannelQuality = (__u8)((rssi + 90) * 26)/10;
+       else
+               ChannelQuality = 0;
+
+    iq->qual = (__u8)ChannelQuality;
+
+    iq->level = (__u8)(rssi);
+    iq->noise = (pAdapter->BbpWriteLatch[66] > pAdapter->BbpTuning.FalseCcaUpperThreshold) ? ((__u8)pAdapter->BbpTuning.FalseCcaUpperThreshold) : ((__u8) pAdapter->BbpWriteLatch[66]);        // noise level (dBm)
+    iq->noise += 256 - 143;
+    iq->updated = pAdapter->iw_stats.qual.updated;
+}
+
+int rt_ioctl_iwaplist(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_point *data, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       struct sockaddr addr[IW_MAX_AP];
+       struct iw_quality qual[IW_MAX_AP];
+       int i;
+
+       //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               data->length = 0;
+               return 0;
+        //return -ENETDOWN;
+       }
+
+       for (i = 0; i <IW_MAX_AP ; i++)
+       {
+               if (i >=  pAdapter->ScanTab.BssNr)
+                       break;
+               addr[i].sa_family = ARPHRD_ETHER;
+                       memcpy(addr[i].sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN);
+               set_quality(pAdapter, &qual[i], pAdapter->ScanTab.BssEntry[i].Rssi);
+       }
+       data->length = i;
+       memcpy(extra, &addr, i*sizeof(addr[0]));
+       data->flags = 1;                /* signal quality present (sort of) */
+       memcpy(extra + i*sizeof(addr[0]), &qual, i*sizeof(qual[i]));
+
+       return 0;
+}
+
+#ifdef SIOCGIWSCAN
+int rt_ioctl_siwscan(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_point *data, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       ULONG                                                           Now;
+       int Status = NDIS_STATUS_SUCCESS;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       if (MONITOR_ON(pAdapter))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n"));
+        return -EINVAL;
+    }
+
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+       if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE)
+       {
+               pAdapter->StaCfg.WpaSupplicantScanCount++;
+       }
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+    pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE;
+       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+               return 0;
+       do{
+               Now = jiffies;
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+               if ((pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) &&
+                       (pAdapter->StaCfg.WpaSupplicantScanCount > 3))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!! WpaSupplicantScanCount > 3\n"));
+                       Status = NDIS_STATUS_SUCCESS;
+                       break;
+               }
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+               if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) &&
+                       ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+                       (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) &&
+                       (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n"));
+                       Status = NDIS_STATUS_SUCCESS;
+                       break;
+               }
+
+               if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+               {
+                       RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+               }
+
+               // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+               // this request, because this request is initiated by NDIS.
+               pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+               // Reset allowed scan retries
+               pAdapter->StaCfg.ScanCnt = 0;
+               pAdapter->StaCfg.LastScanTime = Now;
+
+               MlmeEnqueue(pAdapter,
+                       MLME_CNTL_STATE_MACHINE,
+                       OID_802_11_BSSID_LIST_SCAN,
+                       0,
+                       NULL);
+
+               Status = NDIS_STATUS_SUCCESS;
+               RT28XX_MLME_HANDLER(pAdapter);
+       }while(0);
+       return 0;
+}
+
+int rt_ioctl_giwscan(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_point *data, char *extra)
+{
+
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       int i=0;
+       char *current_ev = extra, *previous_ev = extra;
+       char *end_buf;
+       char *current_val, custom[MAX_CUSTOM_LEN] = {0};
+#ifndef IWEVGENIE
+       char idx;
+#endif // IWEVGENIE //
+       struct iw_event iwe;
+
+       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+    {
+               /*
+                * Still scanning, indicate the caller should try again.
+                */
+               return -EAGAIN;
+       }
+
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+       if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE)
+       {
+               pAdapter->StaCfg.WpaSupplicantScanCount = 0;
+       }
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+       if (pAdapter->ScanTab.BssNr == 0)
+       {
+               data->length = 0;
+               return 0;
+       }
+
+#if WIRELESS_EXT >= 17
+    if (data->length > 0)
+        end_buf = extra + data->length;
+    else
+        end_buf = extra + IW_SCAN_MAX_DATA;
+#else
+    end_buf = extra + IW_SCAN_MAX_DATA;
+#endif
+
+       for (i = 0; i < pAdapter->ScanTab.BssNr; i++)
+       {
+               if (current_ev >= end_buf)
+        {
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+        }
+
+               //MAC address
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWAP;
+               iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+                               memcpy(iwe.u.ap_addr.sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, ETH_ALEN);
+
+        previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //ESSID
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWESSID;
+               iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].SsidLen;
+               iwe.u.data.flags = 1;
+
+        previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_POINT(info, current_ev,end_buf, &iwe, pAdapter->ScanTab.BssEntry[i].Ssid);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Network Type
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWMODE;
+               if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11IBSS)
+               {
+                       iwe.u.mode = IW_MODE_ADHOC;
+               }
+               else if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11Infrastructure)
+               {
+                       iwe.u.mode = IW_MODE_INFRA;
+               }
+               else
+               {
+                       iwe.u.mode = IW_MODE_AUTO;
+               }
+               iwe.len = IW_EV_UINT_LEN;
+
+        previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe,  IW_EV_UINT_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Channel and Frequency
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWFREQ;
+               if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
+                       iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
+               else
+                       iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
+               iwe.u.freq.e = 0;
+               iwe.u.freq.i = 0;
+
+               previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+        //Add quality statistics
+        //================================
+        memset(&iwe, 0, sizeof(iwe));
+       iwe.cmd = IWEVQUAL;
+       iwe.u.qual.level = 0;
+       iwe.u.qual.noise = 0;
+        set_quality(pAdapter, &iwe.u.qual, pAdapter->ScanTab.BssEntry[i].Rssi);
+       current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Encyption key
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWENCODE;
+               if (CAP_IS_PRIVACY_ON (pAdapter->ScanTab.BssEntry[i].CapabilityInfo ))
+                       iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+               else
+                       iwe.u.data.flags = IW_ENCODE_DISABLED;
+
+        previous_ev = current_ev;
+        current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,&iwe, (char *)pAdapter->SharedKey[BSS0][(iwe.u.data.flags & IW_ENCODE_INDEX)-1].Key);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Bit Rate
+               //================================
+               if (pAdapter->ScanTab.BssEntry[i].SupRateLen)
+        {
+            UCHAR tmpRate = pAdapter->ScanTab.BssEntry[i].SupRate[pAdapter->ScanTab.BssEntry[i].SupRateLen-1];
+                       memset(&iwe, 0, sizeof(iwe));
+                       iwe.cmd = SIOCGIWRATE;
+               current_val = current_ev + IW_EV_LCP_LEN;
+            if (tmpRate == 0x82)
+                iwe.u.bitrate.value =  1 * 1000000;
+            else if (tmpRate == 0x84)
+                iwe.u.bitrate.value =  2 * 1000000;
+            else if (tmpRate == 0x8B)
+                iwe.u.bitrate.value =  5.5 * 1000000;
+            else if (tmpRate == 0x96)
+                iwe.u.bitrate.value =  11 * 1000000;
+            else
+                   iwe.u.bitrate.value =  (tmpRate/2) * 1000000;
+
+                       iwe.u.bitrate.disabled = 0;
+                       current_val = IWE_STREAM_ADD_VALUE(info, current_ev,
+                               current_val, end_buf, &iwe,
+                       IW_EV_PARAM_LEN);
+
+               if((current_val-current_ev)>IW_EV_LCP_LEN)
+               current_ev = current_val;
+               else
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+
+#ifdef IWEVGENIE
+               //WPA IE
+               if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0)
+               {
+                       memset(&iwe, 0, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+                       memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].WpaIE.IE[0]),
+                                                  pAdapter->ScanTab.BssEntry[i].WpaIE.IELen);
+                       iwe.cmd = IWEVGENIE;
+                       iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].WpaIE.IELen;
+                       current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom);
+                       if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+               }
+
+               //WPA2 IE
+        if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0)
+        {
+               memset(&iwe, 0, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+                       memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].RsnIE.IE[0]),
+                                                  pAdapter->ScanTab.BssEntry[i].RsnIE.IELen);
+                       iwe.cmd = IWEVGENIE;
+                       iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].RsnIE.IELen;
+                       current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom);
+                       if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+#else
+        //WPA IE
+               //================================
+        if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0)
+        {
+               NdisZeroMemory(&iwe, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+               iwe.cmd = IWEVCUSTOM;
+            iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen * 2) + 7;
+            NdisMoveMemory(custom, "wpa_ie=", 7);
+            for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].WpaIE.IELen; idx++)
+                sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].WpaIE.IE[idx]);
+            previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe,  custom);
+            if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+
+        //WPA2 IE
+        if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0)
+        {
+               NdisZeroMemory(&iwe, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+               iwe.cmd = IWEVCUSTOM;
+            iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen * 2) + 7;
+            NdisMoveMemory(custom, "rsn_ie=", 7);
+                       for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].RsnIE.IELen; idx++)
+                sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].RsnIE.IE[idx]);
+            previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe,  custom);
+            if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+#endif // IWEVGENIE //
+       }
+
+       data->length = current_ev - extra;
+    pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE;
+       DBGPRINT(RT_DEBUG_ERROR ,("===>rt_ioctl_giwscan. %d(%d) BSS returned, data->length = %d\n",i , pAdapter->ScanTab.BssNr, data->length));
+       return 0;
+}
+#endif
+
+int rt_ioctl_siwessid(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *essid)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+    }
+
+       if (data->flags)
+       {
+               PCHAR   pSsidString = NULL;
+
+               // Includes null character.
+               if (data->length > (IW_ESSID_MAX_SIZE + 1))
+                       return -E2BIG;
+
+               pSsidString = (CHAR *) kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG);
+               if (pSsidString)
+               {
+                       NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1);
+                       NdisMoveMemory(pSsidString, essid, data->length);
+                       if (Set_SSID_Proc(pAdapter, pSsidString) == FALSE)
+                               return -EINVAL;
+               }
+               else
+                       return -ENOMEM;
+       }
+       else
+       {
+               // ANY ssid
+               if (Set_SSID_Proc(pAdapter, "") == FALSE)
+                       return -EINVAL;
+    }
+       return 0;
+}
+
+int rt_ioctl_giwessid(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *essid)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       data->flags = 1;
+    if (MONITOR_ON(pAdapter))
+    {
+        data->length  = 0;
+        return 0;
+    }
+
+       if (OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED))
+       {
+               DBGPRINT(RT_DEBUG_TRACE ,("MediaState is connected\n"));
+               data->length = pAdapter->CommonCfg.SsidLen;
+               memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen);
+       }
+#ifdef RT2870
+#ifdef WPA_SUPPLICANT_SUPPORT
+    // Add for RT2870
+    else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+    {
+        data->length = pAdapter->CommonCfg.SsidLen;
+               memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen);
+       }
+#endif // WPA_SUPPLICANT_SUPPORT //
+#endif // RT2870 //
+       else
+       {//the ANY ssid was specified
+               data->length  = 0;
+               DBGPRINT(RT_DEBUG_TRACE ,("MediaState is not connected, ess\n"));
+       }
+
+       return 0;
+
+}
+
+int rt_ioctl_siwnickn(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *nickname)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+        DBGPRINT(RT_DEBUG_TRACE ,("INFO::Network is down!\n"));
+        return -ENETDOWN;
+    }
+
+       if (data->length > IW_ESSID_MAX_SIZE)
+               return -EINVAL;
+
+       memset(pAdapter->nickname, 0, IW_ESSID_MAX_SIZE + 1);
+       memcpy(pAdapter->nickname, nickname, data->length);
+
+
+       return 0;
+}
+
+int rt_ioctl_giwnickn(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *nickname)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       if (data->length > strlen(pAdapter->nickname) + 1)
+               data->length = strlen(pAdapter->nickname) + 1;
+       if (data->length > 0) {
+               memcpy(nickname, pAdapter->nickname, data->length-1);
+               nickname[data->length-1] = '\0';
+       }
+       return 0;
+}
+
+int rt_ioctl_siwrts(struct net_device *dev,
+                      struct iw_request_info *info,
+                      struct iw_param *rts, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       u16 val;
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+        return -ENETDOWN;
+    }
+
+       if (rts->disabled)
+               val = MAX_RTS_THRESHOLD;
+       else if (rts->value < 0 || rts->value > MAX_RTS_THRESHOLD)
+               return -EINVAL;
+       else if (rts->value == 0)
+           val = MAX_RTS_THRESHOLD;
+       else
+               val = rts->value;
+
+       if (val != pAdapter->CommonCfg.RtsThreshold)
+               pAdapter->CommonCfg.RtsThreshold = val;
+
+       return 0;
+}
+
+int rt_ioctl_giwrts(struct net_device *dev,
+                      struct iw_request_info *info,
+                      struct iw_param *rts, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+       rts->value = pAdapter->CommonCfg.RtsThreshold;
+       rts->disabled = (rts->value == MAX_RTS_THRESHOLD);
+       rts->fixed = 1;
+
+       return 0;
+}
+
+int rt_ioctl_siwfrag(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_param *frag, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       u16 val;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       if (frag->disabled)
+               val = MAX_FRAG_THRESHOLD;
+       else if (frag->value >= MIN_FRAG_THRESHOLD || frag->value <= MAX_FRAG_THRESHOLD)
+        val = __cpu_to_le16(frag->value & ~0x1); /* even numbers only */
+       else if (frag->value == 0)
+           val = MAX_FRAG_THRESHOLD;
+       else
+               return -EINVAL;
+
+       pAdapter->CommonCfg.FragmentThreshold = val;
+       return 0;
+}
+
+int rt_ioctl_giwfrag(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_param *frag, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+       frag->value = pAdapter->CommonCfg.FragmentThreshold;
+       frag->disabled = (frag->value == MAX_FRAG_THRESHOLD);
+       frag->fixed = 1;
+
+       return 0;
+}
+
+#define MAX_WEP_KEY_SIZE 13
+#define MIN_WEP_KEY_SIZE 5
+int rt_ioctl_siwencode(struct net_device *dev,
+                         struct iw_request_info *info,
+                         struct iw_point *erq, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       if ((erq->length == 0) &&
+        (erq->flags & IW_ENCODE_DISABLED))
+       {
+               pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled;
+               pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled;
+               pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled;
+        pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+        goto done;
+       }
+       else if ((erq->length == 0) &&
+             (erq->flags & IW_ENCODE_RESTRICTED || erq->flags & IW_ENCODE_OPEN))
+       {
+           //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+               STA_PORT_SECURED(pAdapter);
+               pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled;
+               pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled;
+               pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled;
+        pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+               if (erq->flags & IW_ENCODE_RESTRICTED)
+                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared;
+       else
+                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+        goto done;
+       }
+
+    if (erq->length > 0)
+       {
+               int keyIdx = (erq->flags & IW_ENCODE_INDEX) - 1;
+               /* Check the size of the key */
+               if (erq->length > MAX_WEP_KEY_SIZE) {
+                       return -EINVAL;
+               }
+               /* Check key index */
+               if ((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS))
+        {
+            DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::Wrong keyIdx=%d! Using default key instead (%d)\n",
+                                        keyIdx, pAdapter->StaCfg.DefaultKeyId));
+
+            //Using default key
+                       keyIdx = pAdapter->StaCfg.DefaultKeyId;
+        }
+
+        NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key,  16);
+
+               if (erq->length == MAX_WEP_KEY_SIZE)
+        {
+                       pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE;
+            pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128;
+               }
+               else if (erq->length == MIN_WEP_KEY_SIZE)
+        {
+            pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE;
+            pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64;
+               }
+               else
+                       /* Disable the key */
+                       pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0;
+
+               /* Check if the key is not marked as invalid */
+               if(!(erq->flags & IW_ENCODE_NOKEY)) {
+                       /* Copy the key in the driver */
+                       NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, extra, erq->length);
+        }
+       }
+    else
+                       {
+               /* Do we want to just set the transmit key index ? */
+               int index = (erq->flags & IW_ENCODE_INDEX) - 1;
+               if ((index >= 0) && (index < 4))
+        {
+                       pAdapter->StaCfg.DefaultKeyId = index;
+            }
+        else
+                       /* Don't complain if only change the mode */
+                       if(!erq->flags & IW_ENCODE_MODE) {
+                               return -EINVAL;
+               }
+       }
+
+done:
+    DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::erq->flags=%x\n",erq->flags));
+       DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::AuthMode=%x\n",pAdapter->StaCfg.AuthMode));
+       DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::DefaultKeyId=%x, KeyLen = %d\n",pAdapter->StaCfg.DefaultKeyId , pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen));
+       DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::WepStatus=%x\n",pAdapter->StaCfg.WepStatus));
+       return 0;
+}
+
+int
+rt_ioctl_giwencode(struct net_device *dev,
+                         struct iw_request_info *info,
+                         struct iw_point *erq, char *key)
+{
+       int kid;
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+       kid = erq->flags & IW_ENCODE_INDEX;
+       DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_giwencode %d\n", erq->flags & IW_ENCODE_INDEX));
+
+       if (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled)
+       {
+               erq->length = 0;
+               erq->flags = IW_ENCODE_DISABLED;
+       }
+       else if ((kid > 0) && (kid <=4))
+       {
+               // copy wep key
+               erq->flags = kid ;                      /* NB: base 1 */
+               if (erq->length > pAdapter->SharedKey[BSS0][kid-1].KeyLen)
+                       erq->length = pAdapter->SharedKey[BSS0][kid-1].KeyLen;
+               memcpy(key, pAdapter->SharedKey[BSS0][kid-1].Key, erq->length);
+               //if ((kid == pAdapter->PortCfg.DefaultKeyId))
+               //erq->flags |= IW_ENCODE_ENABLED;      /* XXX */
+               if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared)
+                       erq->flags |= IW_ENCODE_RESTRICTED;             /* XXX */
+               else
+                       erq->flags |= IW_ENCODE_OPEN;           /* XXX */
+
+       }
+       else if (kid == 0)
+       {
+               if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared)
+                       erq->flags |= IW_ENCODE_RESTRICTED;             /* XXX */
+               else
+                       erq->flags |= IW_ENCODE_OPEN;           /* XXX */
+               erq->length = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen;
+               memcpy(key, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, erq->length);
+               // copy default key ID
+               if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared)
+                       erq->flags |= IW_ENCODE_RESTRICTED;             /* XXX */
+               else
+                       erq->flags |= IW_ENCODE_OPEN;           /* XXX */
+               erq->flags = pAdapter->StaCfg.DefaultKeyId + 1;                 /* NB: base 1 */
+               erq->flags |= IW_ENCODE_ENABLED;        /* XXX */
+       }
+
+       return 0;
+
+}
+
+static int
+rt_ioctl_setparam(struct net_device *dev, struct iw_request_info *info,
+                        void *w, char *extra)
+{
+    VIRTUAL_ADAPTER    *pVirtualAd = NULL;
+       PRTMP_ADAPTER pAdapter;
+       POS_COOKIE pObj;
+       char *this_char = extra;
+       char *value;
+       int  Status=0;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+       pObj = (POS_COOKIE) pAdapter->OS_Cookie;
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       {
+               pObj->ioctl_if_type = INT_MAIN;
+        pObj->ioctl_if = MAIN_MBSSID;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+                       return -ENETDOWN;
+       }
+
+       if (!*this_char)
+               return -EINVAL;
+
+       if ((value = rtstrchr(this_char, '=')) != NULL)
+           *value++ = 0;
+
+       if (!value)
+           return -EINVAL;
+
+       // reject setting nothing besides ANY ssid(ssidLen=0)
+    if (!*value && (strcmp(this_char, "SSID") != 0))
+        return -EINVAL;
+
+       for (PRTMP_PRIVATE_SET_PROC = RTMP_PRIVATE_SUPPORT_PROC; PRTMP_PRIVATE_SET_PROC->name; PRTMP_PRIVATE_SET_PROC++)
+       {
+           if (strcmp(this_char, PRTMP_PRIVATE_SET_PROC->name) == 0)
+           {
+               if(!PRTMP_PRIVATE_SET_PROC->set_proc(pAdapter, value))
+               {       //FALSE:Set private failed then return Invalid argument
+                           Status = -EINVAL;
+               }
+                   break;      //Exit for loop.
+           }
+       }
+
+       if(PRTMP_PRIVATE_SET_PROC->name == NULL)
+       {  //Not found argument
+           Status = -EINVAL;
+           DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_setparam:: (iwpriv) Not Support Set Command [%s=%s]\n", this_char, value));
+       }
+
+    return Status;
+}
+
+
+static int
+rt_private_get_statistics(struct net_device *dev, struct iw_request_info *info,
+               struct iw_point *wrq, char *extra)
+{
+       INT                             Status = 0;
+    PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+
+    if (extra == NULL)
+    {
+        wrq->length = 0;
+        return -EIO;
+    }
+
+    memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+    sprintf(extra, "\n\n");
+
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+       {
+           sprintf(extra+strlen(extra), "Tx success                      = %ld\n", (ULONG)pAd->ate.TxDoneCount);
+           //sprintf(extra+strlen(extra), "Tx success without retry        = %ld\n", (ULONG)pAd->ate.TxDoneCount);
+       }
+       else
+#endif // RALINK_ATE //
+       {
+    sprintf(extra+strlen(extra), "Tx success                      = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart);
+    sprintf(extra+strlen(extra), "Tx success without retry        = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart - (ULONG)pAd->WlanCounters.RetryCount.QuadPart);
+       }
+    sprintf(extra+strlen(extra), "Tx success after retry          = %ld\n", (ULONG)pAd->WlanCounters.RetryCount.QuadPart);
+    sprintf(extra+strlen(extra), "Tx fail to Rcv ACK after retry  = %ld\n", (ULONG)pAd->WlanCounters.FailedCount.QuadPart);
+    sprintf(extra+strlen(extra), "RTS Success Rcv CTS             = %ld\n", (ULONG)pAd->WlanCounters.RTSSuccessCount.QuadPart);
+    sprintf(extra+strlen(extra), "RTS Fail Rcv CTS                = %ld\n", (ULONG)pAd->WlanCounters.RTSFailureCount.QuadPart);
+
+    sprintf(extra+strlen(extra), "Rx success                      = %ld\n", (ULONG)pAd->WlanCounters.ReceivedFragmentCount.QuadPart);
+    sprintf(extra+strlen(extra), "Rx with CRC                     = %ld\n", (ULONG)pAd->WlanCounters.FCSErrorCount.QuadPart);
+    sprintf(extra+strlen(extra), "Rx drop due to out of resource  = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer);
+    sprintf(extra+strlen(extra), "Rx duplicate frame              = %ld\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.QuadPart);
+
+    sprintf(extra+strlen(extra), "False CCA (one second)          = %ld\n", (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt);
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+       {
+               if (pAd->ate.RxAntennaSel == 0)
+               {
+               sprintf(extra+strlen(extra), "RSSI-A                          = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta));
+                       sprintf(extra+strlen(extra), "RSSI-B (if available)           = %ld\n", (LONG)(pAd->ate.LastRssi1 - pAd->BbpRssiToDbmDelta));
+                       sprintf(extra+strlen(extra), "RSSI-C (if available)           = %ld\n\n", (LONG)(pAd->ate.LastRssi2 - pAd->BbpRssiToDbmDelta));
+               }
+               else
+               {
+               sprintf(extra+strlen(extra), "RSSI                            = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta));
+               }
+       }
+       else
+#endif // RALINK_ATE //
+       {
+       sprintf(extra+strlen(extra), "RSSI-A                          = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta));
+        sprintf(extra+strlen(extra), "RSSI-B (if available)           = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi1 - pAd->BbpRssiToDbmDelta));
+        sprintf(extra+strlen(extra), "RSSI-C (if available)           = %ld\n\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi2 - pAd->BbpRssiToDbmDelta));
+       }
+#ifdef WPA_SUPPLICANT_SUPPORT
+    sprintf(extra+strlen(extra), "WpaSupplicantUP                 = %d\n\n", pAd->StaCfg.WpaSupplicantUP);
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+
+    wrq->length = strlen(extra) + 1; // 1: size of '\0'
+    DBGPRINT(RT_DEBUG_TRACE, ("<== rt_private_get_statistics, wrq->length = %d\n", wrq->length));
+
+    return Status;
+}
+
+#ifdef DOT11_N_SUPPORT
+void   getBaInfo(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pOutBuf)
+{
+       INT i, j;
+       BA_ORI_ENTRY *pOriBAEntry;
+       BA_REC_ENTRY *pRecBAEntry;
+
+       for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+               if (((pEntry->ValidAsCLI || pEntry->ValidAsApCli) && (pEntry->Sst == SST_ASSOC))
+                       || (pEntry->ValidAsWDS) || (pEntry->ValidAsMesh))
+               {
+                       sprintf(pOutBuf, "%s\n%02X:%02X:%02X:%02X:%02X:%02X (Aid = %d) (AP) -\n",
+                pOutBuf,
+                               pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+                               pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5], pEntry->Aid);
+
+                       sprintf(pOutBuf, "%s[Recipient]\n", pOutBuf);
+                       for (j=0; j < NUM_OF_TID; j++)
+                       {
+                               if (pEntry->BARecWcidArray[j] != 0)
+                               {
+                                       pRecBAEntry =&pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]];
+                                       sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, LastIndSeq=%d, ReorderingPkts=%d\n", pOutBuf, j, pRecBAEntry->BAWinSize, pRecBAEntry->LastIndSeq, pRecBAEntry->list.qlen);
+                               }
+                       }
+                       sprintf(pOutBuf, "%s\n", pOutBuf);
+
+                       sprintf(pOutBuf, "%s[Originator]\n", pOutBuf);
+                       for (j=0; j < NUM_OF_TID; j++)
+                       {
+                               if (pEntry->BAOriWcidArray[j] != 0)
+                               {
+                                       pOriBAEntry =&pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]];
+                                       sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, StartSeq=%d, CurTxSeq=%d\n", pOutBuf, j, pOriBAEntry->BAWinSize, pOriBAEntry->Sequence, pEntry->TxSeq[j]);
+                               }
+                       }
+                       sprintf(pOutBuf, "%s\n\n", pOutBuf);
+               }
+        if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30))
+                break;
+       }
+
+       return;
+}
+#endif // DOT11_N_SUPPORT //
+
+static int
+rt_private_show(struct net_device *dev, struct iw_request_info *info,
+               struct iw_point *wrq, char *extra)
+{
+    INT                                Status = 0;
+    VIRTUAL_ADAPTER    *pVirtualAd = NULL;
+    PRTMP_ADAPTER   pAd;
+       POS_COOKIE              pObj;
+    u32             subcmd = wrq->flags;
+
+       if (dev->priv_flags == INT_MAIN)
+               pAd = dev->priv;
+       else
+       {
+               pVirtualAd = dev->priv;
+               pAd = pVirtualAd->RtmpDev->priv;
+       }
+       pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+       if (pAd == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+    if (extra == NULL)
+    {
+        wrq->length = 0;
+        return -EIO;
+    }
+    memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+
+       {
+               pObj->ioctl_if_type = INT_MAIN;
+        pObj->ioctl_if = MAIN_MBSSID;
+       }
+
+    switch(subcmd)
+    {
+
+        case SHOW_CONN_STATUS:
+            if (MONITOR_ON(pAd))
+            {
+#ifdef DOT11_N_SUPPORT
+                if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED &&
+                    pAd->CommonCfg.RegTransmitSetting.field.BW)
+                    sprintf(extra, "Monitor Mode(CentralChannel %d)\n", pAd->CommonCfg.CentralChannel);
+                else
+#endif // DOT11_N_SUPPORT //
+                    sprintf(extra, "Monitor Mode(Channel %d)\n", pAd->CommonCfg.Channel);
+            }
+            else
+            {
+                if (pAd->IndicateMediaState == NdisMediaStateConnected)
+               {
+                   if (INFRA_ON(pAd))
+                    {
+                    sprintf(extra, "Connected(AP: %s[%02X:%02X:%02X:%02X:%02X:%02X])\n",
+                                    pAd->CommonCfg.Ssid,
+                                    pAd->CommonCfg.Bssid[0],
+                                    pAd->CommonCfg.Bssid[1],
+                                    pAd->CommonCfg.Bssid[2],
+                                    pAd->CommonCfg.Bssid[3],
+                                    pAd->CommonCfg.Bssid[4],
+                                    pAd->CommonCfg.Bssid[5]);
+                       DBGPRINT(RT_DEBUG_TRACE ,("Ssid=%s ,Ssidlen = %d\n",pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen));
+               }
+                    else if (ADHOC_ON(pAd))
+                        sprintf(extra, "Connected\n");
+               }
+               else
+               {
+                   sprintf(extra, "Disconnected\n");
+                       DBGPRINT(RT_DEBUG_TRACE ,("ConnStatus is not connected\n"));
+               }
+            }
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+        case SHOW_DRVIER_VERION:
+            sprintf(extra, "Driver version-%s, %s %s\n", STA_DRIVER_VERSION, __DATE__, __TIME__ );
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+#ifdef DOT11_N_SUPPORT
+        case SHOW_BA_INFO:
+            getBaInfo(pAd, extra);
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+#endif // DOT11_N_SUPPORT //
+               case SHOW_DESC_INFO:
+                       {
+                               Show_DescInfo_Proc(pAd, NULL);
+                               wrq->length = 0; // 1: size of '\0'
+                       }
+                       break;
+        case RAIO_OFF:
+            if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+            {
+                sprintf(extra, "Scanning\n");
+                wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                break;
+            }
+            pAd->StaCfg.bSwRadio = FALSE;
+            if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
+            {
+                pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
+                if (pAd->StaCfg.bRadio == FALSE)
+                {
+                    MlmeRadioOff(pAd);
+                    // Update extra information
+                                       pAd->ExtraInfo = SW_RADIO_OFF;
+                }
+            }
+            sprintf(extra, "Radio Off\n");
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+        case RAIO_ON:
+            if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+            {
+                sprintf(extra, "Scanning\n");
+                wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                break;
+            }
+            pAd->StaCfg.bSwRadio = TRUE;
+            //if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
+            {
+                pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
+                if (pAd->StaCfg.bRadio == TRUE)
+                {
+                    MlmeRadioOn(pAd);
+                    // Update extra information
+                                       pAd->ExtraInfo = EXTRA_INFO_CLEAR;
+                }
+            }
+            sprintf(extra, "Radio On\n");
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+
+
+#ifdef QOS_DLS_SUPPORT
+               case SHOW_DLS_ENTRY_INFO:
+                       {
+                               Set_DlsEntryInfo_Display_Proc(pAd, NULL);
+                               wrq->length = 0; // 1: size of '\0'
+                       }
+                       break;
+#endif // QOS_DLS_SUPPORT //
+
+               case SHOW_CFG_VALUE:
+                       {
+                               Status = RTMPShowCfgValue(pAd, wrq->pointer, extra);
+                               if (Status == 0)
+                                       wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                       }
+                       break;
+               case SHOW_ADHOC_ENTRY_INFO:
+                       Show_Adhoc_MacTable_Proc(pAd, extra);
+                       wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                       break;
+        default:
+            DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow subcmd = %d\n", __FUNCTION__, subcmd));
+            break;
+    }
+
+    return Status;
+}
+
+#ifdef SIOCSIWMLME
+int rt_ioctl_siwmlme(struct net_device *dev,
+                          struct iw_request_info *info,
+                          union iwreq_data *wrqu,
+                          char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+       struct iw_mlme *pMlme = (struct iw_mlme *)wrqu->data.pointer;
+       MLME_QUEUE_ELEM                         MsgElem;
+       MLME_DISASSOC_REQ_STRUCT        DisAssocReq;
+       MLME_DEAUTH_REQ_STRUCT      DeAuthReq;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__));
+
+       if (pMlme == NULL)
+               return -EINVAL;
+
+       switch(pMlme->cmd)
+       {
+#ifdef IW_MLME_DEAUTH
+               case IW_MLME_DEAUTH:
+                       DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DEAUTH\n", __FUNCTION__));
+                       COPY_MAC_ADDR(DeAuthReq.Addr, pAd->CommonCfg.Bssid);
+                       DeAuthReq.Reason = pMlme->reason_code;
+                       MsgElem.MsgLen = sizeof(MLME_DEAUTH_REQ_STRUCT);
+                       NdisMoveMemory(MsgElem.Msg, &DeAuthReq, sizeof(MLME_DEAUTH_REQ_STRUCT));
+                       MlmeDeauthReqAction(pAd, &MsgElem);
+                       if (INFRA_ON(pAd))
+                       {
+                           LinkDown(pAd, FALSE);
+                           pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+                       }
+                       break;
+#endif // IW_MLME_DEAUTH //
+#ifdef IW_MLME_DISASSOC
+               case IW_MLME_DISASSOC:
+                       DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DISASSOC\n", __FUNCTION__));
+                       COPY_MAC_ADDR(DisAssocReq.Addr, pAd->CommonCfg.Bssid);
+                       DisAssocReq.Reason =  pMlme->reason_code;
+
+                       MsgElem.Machine = ASSOC_STATE_MACHINE;
+                       MsgElem.MsgType = MT2_MLME_DISASSOC_REQ;
+                       MsgElem.MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT);
+                       NdisMoveMemory(MsgElem.Msg, &DisAssocReq, sizeof(MLME_DISASSOC_REQ_STRUCT));
+
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC;
+                       MlmeDisassocReqAction(pAd, &MsgElem);
+                       break;
+#endif // IW_MLME_DISASSOC //
+               default:
+                       DBGPRINT(RT_DEBUG_TRACE, ("====> %s - Unknow Command\n", __FUNCTION__));
+                       break;
+       }
+
+       return 0;
+}
+#endif // SIOCSIWMLME //
+
+#if WIRELESS_EXT > 17
+int rt_ioctl_siwauth(struct net_device *dev,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = (PRTMP_ADAPTER) dev->priv;
+       struct iw_param *param = &wrqu->param;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_WPA_VERSION:
+            if (param->value == IW_AUTH_WPA_VERSION_WPA)
+            {
+                pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK;
+                               if (pAdapter->StaCfg.BssType == BSS_ADHOC)
+                                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone;
+            }
+            else if (param->value == IW_AUTH_WPA_VERSION_WPA2)
+                pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK;
+
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_CIPHER_PAIRWISE:
+            if (param->value == IW_AUTH_CIPHER_NONE)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_WEP40 ||
+                     param->value == IW_AUTH_CIPHER_WEP104)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled;
+#ifdef WPA_SUPPLICANT_SUPPORT
+                pAdapter->StaCfg.IEEE8021X = FALSE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+            }
+            else if (param->value == IW_AUTH_CIPHER_TKIP)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11Encryption2Enabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_CCMP)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11Encryption3Enabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11Encryption3Enabled;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_PAIRWISE - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_CIPHER_GROUP:
+            if (param->value == IW_AUTH_CIPHER_NONE)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_WEP40 ||
+                     param->value == IW_AUTH_CIPHER_WEP104)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_TKIP)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_CCMP)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_GROUP - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_KEY_MGMT:
+            if (param->value == IW_AUTH_KEY_MGMT_802_1X)
+            {
+                if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
+                {
+                    pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA;
+#ifdef WPA_SUPPLICANT_SUPPORT
+                    pAdapter->StaCfg.IEEE8021X = FALSE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+                }
+                else if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+                {
+                    pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2;
+#ifdef WPA_SUPPLICANT_SUPPORT
+                    pAdapter->StaCfg.IEEE8021X = FALSE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+                }
+#ifdef WPA_SUPPLICANT_SUPPORT
+                else
+                    // WEP 1x
+                    pAdapter->StaCfg.IEEE8021X = TRUE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+            }
+            else if (param->value == 0)
+            {
+                //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               STA_PORT_SECURED(pAdapter);
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_KEY_MGMT - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+            break;
+       case IW_AUTH_PRIVACY_INVOKED:
+            /*if (param->value == 0)
+                       {
+                pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+                pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled;
+                   pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled;
+            }*/
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_PRIVACY_INVOKED - param->value = %d!\n", __FUNCTION__, param->value));
+               break;
+       case IW_AUTH_DROP_UNENCRYPTED:
+            if (param->value != 0)
+                pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                       else
+                       {
+                //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               STA_PORT_SECURED(pAdapter);
+                       }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value));
+               break;
+       case IW_AUTH_80211_AUTH_ALG:
+                       if (param->value & IW_AUTH_ALG_SHARED_KEY)
+            {
+                               pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared;
+                       }
+            else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
+            {
+                               pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+                       }
+            else
+                               return -EINVAL;
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_80211_AUTH_ALG - param->value = %d!\n", __FUNCTION__, param->value));
+                       break;
+       case IW_AUTH_WPA_ENABLED:
+               DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_ENABLED - Driver supports WPA!(param->value = %d)\n", __FUNCTION__, param->value));
+               break;
+       default:
+               return -EOPNOTSUPP;
+}
+
+       return 0;
+}
+
+int rt_ioctl_giwauth(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = (PRTMP_ADAPTER) dev->priv;
+       struct iw_param *param = &wrqu->param;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+    }
+
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_DROP_UNENCRYPTED:
+        param->value = (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) ? 0 : 1;
+               break;
+
+       case IW_AUTH_80211_AUTH_ALG:
+        param->value = (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) ? IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM;
+               break;
+
+       case IW_AUTH_WPA_ENABLED:
+               param->value = (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) ? 1 : 0;
+               break;
+
+       default:
+               return -EOPNOTSUPP;
+       }
+    DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_giwauth::param->value = %d!\n", param->value));
+       return 0;
+}
+
+void fnSetCipherKey(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  INT             keyIdx,
+    IN  UCHAR           CipherAlg,
+    IN  BOOLEAN         bGTK,
+    IN  struct iw_encode_ext *ext)
+{
+    NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY));
+    pAdapter->SharedKey[BSS0][keyIdx].KeyLen = LEN_TKIP_EK;
+    NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, LEN_TKIP_EK);
+    NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].TxMic, ext->key + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+    NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].RxMic, ext->key + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+    pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CipherAlg;
+
+    // Update group key information to ASIC Shared Key Table
+       AsicAddSharedKeyEntry(pAdapter,
+                                                 BSS0,
+                                                 keyIdx,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].CipherAlg,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].Key,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].TxMic,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].RxMic);
+
+    if (bGTK)
+        // Update ASIC WCID attribute table and IVEIV table
+       RTMPAddWcidAttributeEntry(pAdapter,
+                                                         BSS0,
+                                                         keyIdx,
+                                                         pAdapter->SharedKey[BSS0][keyIdx].CipherAlg,
+                                                         NULL);
+    else
+        // Update ASIC WCID attribute table and IVEIV table
+       RTMPAddWcidAttributeEntry(pAdapter,
+                                                         BSS0,
+                                                         keyIdx,
+                                                         pAdapter->SharedKey[BSS0][keyIdx].CipherAlg,
+                                                         &pAdapter->MacTab.Content[BSSID_WCID]);
+}
+
+int rt_ioctl_siwencodeext(struct net_device *dev,
+                          struct iw_request_info *info,
+                          union iwreq_data *wrqu,
+                          char *extra)
+                       {
+    PRTMP_ADAPTER   pAdapter = (PRTMP_ADAPTER) dev->priv;
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+    int keyIdx, alg = ext->alg;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+    if (encoding->flags & IW_ENCODE_DISABLED)
+       {
+        keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1;
+        // set BSSID wcid entry of the Pair-wise Key table as no-security mode
+           AsicRemovePairwiseKeyEntry(pAdapter, BSS0, BSSID_WCID);
+        pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0;
+               pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_NONE;
+               AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)keyIdx);
+        NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY));
+        DBGPRINT(RT_DEBUG_TRACE, ("%s::Remove all keys!(encoding->flags = %x)\n", __FUNCTION__, encoding->flags));
+    }
+                                       else
+    {
+        // Get Key Index and convet to our own defined key index
+       keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1;
+       if((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS))
+               return -EINVAL;
+
+        if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+        {
+            pAdapter->StaCfg.DefaultKeyId = keyIdx;
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::DefaultKeyId = %d\n", __FUNCTION__, pAdapter->StaCfg.DefaultKeyId));
+        }
+
+        switch (alg) {
+               case IW_ENCODE_ALG_NONE:
+                DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_NONE\n", __FUNCTION__));
+                       break;
+               case IW_ENCODE_ALG_WEP:
+                DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_WEP - ext->key_len = %d, keyIdx = %d\n", __FUNCTION__, ext->key_len, keyIdx));
+                       if (ext->key_len == MAX_WEP_KEY_SIZE)
+                {
+                               pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE;
+                    pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128;
+                               }
+                       else if (ext->key_len == MIN_WEP_KEY_SIZE)
+                {
+                    pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE;
+                    pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64;
+                       }
+                       else
+                    return -EINVAL;
+
+                NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key,  16);
+                           NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, ext->key_len);
+                       break;
+            case IW_ENCODE_ALG_TKIP:
+                DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_TKIP - keyIdx = %d, ext->key_len = %d\n", __FUNCTION__, keyIdx, ext->key_len));
+                if (ext->key_len == 32)
+                {
+                    if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+                    {
+                        fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, FALSE, ext);
+                        if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2)
+                        {
+                            //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                            STA_PORT_SECURED(pAdapter);
+                        }
+               }
+                    else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+                    {
+                        fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, TRUE, ext);
+
+                        // set 802.1x port control
+                       //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAdapter);
+                    }
+                }
+                else
+                    return -EINVAL;
+                break;
+            case IW_ENCODE_ALG_CCMP:
+                if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+               {
+                    fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, FALSE, ext);
+                    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2)
+                       //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAdapter);
+                }
+                else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+                {
+                    fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, TRUE, ext);
+
+                    // set 802.1x port control
+                       //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAdapter);
+                }
+                break;
+               default:
+                       return -EINVAL;
+               }
+    }
+
+    return 0;
+}
+
+int
+rt_ioctl_giwencodeext(struct net_device *dev,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) dev->priv;
+       PCHAR pKey = NULL;
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+       int idx, max_key_len;
+
+       DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_giwencodeext\n"));
+
+       max_key_len = encoding->length - sizeof(*ext);
+       if (max_key_len < 0)
+               return -EINVAL;
+
+       idx = encoding->flags & IW_ENCODE_INDEX;
+       if (idx)
+       {
+               if (idx < 1 || idx > 4)
+                       return -EINVAL;
+               idx--;
+
+               if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
+                       (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled))
+               {
+                       if (idx != pAd->StaCfg.DefaultKeyId)
+                       {
+                               ext->key_len = 0;
+                               return 0;
+                       }
+               }
+       }
+       else
+               idx = pAd->StaCfg.DefaultKeyId;
+
+       encoding->flags = idx + 1;
+       memset(ext, 0, sizeof(*ext));
+
+       ext->key_len = 0;
+       switch(pAd->StaCfg.WepStatus) {
+               case Ndis802_11WEPDisabled:
+                       ext->alg = IW_ENCODE_ALG_NONE;
+                       encoding->flags |= IW_ENCODE_DISABLED;
+                       break;
+               case Ndis802_11WEPEnabled:
+                       ext->alg = IW_ENCODE_ALG_WEP;
+                       if (pAd->SharedKey[BSS0][idx].KeyLen > max_key_len)
+                               return -E2BIG;
+                       else
+                       {
+                               ext->key_len = pAd->SharedKey[BSS0][idx].KeyLen;
+                               pKey = &(pAd->SharedKey[BSS0][idx].Key[0]);
+                       }
+                       break;
+               case Ndis802_11Encryption2Enabled:
+               case Ndis802_11Encryption3Enabled:
+                       if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)
+                               ext->alg = IW_ENCODE_ALG_TKIP;
+                       else
+                               ext->alg = IW_ENCODE_ALG_CCMP;
+
+                       if (max_key_len < 32)
+                               return -E2BIG;
+                       else
+                       {
+                               ext->key_len = 32;
+                               pKey = &pAd->StaCfg.PMK[0];
+                       }
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       if (ext->key_len && pKey)
+       {
+               encoding->flags |= IW_ENCODE_ENABLED;
+               memcpy(ext->key, pKey, ext->key_len);
+       }
+
+       return 0;
+}
+
+#ifdef SIOCSIWGENIE
+int rt_ioctl_siwgenie(struct net_device *dev,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+
+       if (wrqu->data.length > MAX_LEN_OF_RSNIE ||
+           (wrqu->data.length && extra == NULL))
+               return -EINVAL;
+
+       if (wrqu->data.length)
+       {
+               pAd->StaCfg.RSNIE_Len = wrqu->data.length;
+               NdisMoveMemory(&pAd->StaCfg.RSN_IE[0], extra, pAd->StaCfg.RSNIE_Len);
+       }
+       else
+       {
+               pAd->StaCfg.RSNIE_Len = 0;
+               NdisZeroMemory(&pAd->StaCfg.RSN_IE[0], MAX_LEN_OF_RSNIE);
+       }
+
+       return 0;
+}
+#endif // SIOCSIWGENIE //
+
+int rt_ioctl_giwgenie(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+
+       if ((pAd->StaCfg.RSNIE_Len == 0) ||
+               (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA))
+       {
+               wrqu->data.length = 0;
+               return 0;
+       }
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+#ifdef SIOCSIWGENIE
+       if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE)
+       {
+       if (wrqu->data.length < pAd->StaCfg.RSNIE_Len)
+               return -E2BIG;
+
+       wrqu->data.length = pAd->StaCfg.RSNIE_Len;
+       memcpy(extra, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len);
+       }
+       else
+#endif // SIOCSIWGENIE //
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+       {
+               UCHAR RSNIe = IE_WPA;
+
+               if (wrqu->data.length < (pAd->StaCfg.RSNIE_Len + 2)) // ID, Len
+                       return -E2BIG;
+               wrqu->data.length = pAd->StaCfg.RSNIE_Len + 2;
+
+               if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
+            (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2))
+                       RSNIe = IE_RSN;
+
+               extra[0] = (char)RSNIe;
+               extra[1] = pAd->StaCfg.RSNIE_Len;
+               memcpy(extra+2, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len);
+       }
+
+       return 0;
+}
+
+int rt_ioctl_siwpmksa(struct net_device *dev,
+                          struct iw_request_info *info,
+                          union iwreq_data *wrqu,
+                          char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+       struct iw_pmksa *pPmksa = (struct iw_pmksa *)wrqu->data.pointer;
+       INT     CachedIdx = 0, idx = 0;
+
+       if (pPmksa == NULL)
+               return -EINVAL;
+
+       DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_siwpmksa\n"));
+       switch(pPmksa->cmd)
+       {
+               case IW_PMKSA_FLUSH:
+                       NdisZeroMemory(pAd->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO);
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_FLUSH\n"));
+                       break;
+               case IW_PMKSA_REMOVE:
+                       for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++)
+                       {
+                       // compare the BSSID
+                       if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN))
+                       {
+                               NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN);
+                                       NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].PMKID, 16);
+                                       for (idx = CachedIdx; idx < (pAd->StaCfg.SavedPMKNum - 1); idx++)
+                                       {
+                                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].BSSID[0], &pAd->StaCfg.SavedPMK[idx+1].BSSID[0], MAC_ADDR_LEN);
+                                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].PMKID[0], &pAd->StaCfg.SavedPMK[idx+1].PMKID[0], 16);
+                                       }
+                                       pAd->StaCfg.SavedPMKNum--;
+                               break;
+                       }
+               }
+
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_REMOVE\n"));
+                       break;
+               case IW_PMKSA_ADD:
+                       for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++)
+                       {
+                       // compare the BSSID
+                       if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN))
+                               break;
+               }
+
+               // Found, replace it
+               if (CachedIdx < PMKID_NO)
+               {
+                       DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx));
+                       NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN);
+                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16);
+                       pAd->StaCfg.SavedPMKNum++;
+               }
+               // Not found, replace the last one
+               else
+               {
+                       // Randomly replace one
+                       CachedIdx = (pPmksa->bssid.sa_data[5] % PMKID_NO);
+                       DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx));
+                       NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN);
+                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16);
+               }
+
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_ADD\n"));
+                       break;
+               default:
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - Unknow Command!!\n"));
+                       break;
+       }
+
+       return 0;
+}
+#endif // #if WIRELESS_EXT > 17
+
+#ifdef DBG
+static int
+rt_private_ioctl_bbp(struct net_device *dev, struct iw_request_info *info,
+               struct iw_point *wrq, char *extra)
+                       {
+       CHAR                            *this_char;
+       CHAR                            *value = NULL;
+       UCHAR                           regBBP = 0;
+//     CHAR                            arg[255]={0};
+       UINT32                          bbpId;
+       UINT32                          bbpValue;
+       BOOLEAN                         bIsPrintAllBBP = FALSE;
+       INT                                     Status = 0;
+    PRTMP_ADAPTER       pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+
+       memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+
+       if (wrq->length > 1) //No parameters.
+                               {
+               sprintf(extra, "\n");
+
+               //Parsing Read or Write
+               this_char = wrq->pointer;
+               DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s\n", this_char));
+               if (!*this_char)
+                       goto next;
+
+               if ((value = rtstrchr(this_char, '=')) != NULL)
+                       *value++ = 0;
+
+               if (!value || !*value)
+               { //Read
+                       DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s, value=%s\n", this_char, value));
+                       if (sscanf(this_char, "%d", &(bbpId)) == 1)
+                       {
+                               if (bbpId <= 136)
+                               {
+#ifdef RALINK_ATE
+                                       if (ATE_ON(pAdapter))
+                                       {
+                                               ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                                       }
+                                       else
+#endif // RALINK_ATE //
+                                       {
+                                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                                       }
+                                       sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId*2, regBBP);
+                    wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                                       DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra));
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       bIsPrintAllBBP = TRUE;
+                                       goto next;
+                               }
+                       }
+                       else
+                       { //Invalid parametes, so default printk all bbp
+                               bIsPrintAllBBP = TRUE;
+                               goto next;
+                       }
+               }
+               else
+               { //Write
+                       if ((sscanf(this_char, "%d", &(bbpId)) == 1) && (sscanf(value, "%x", &(bbpValue)) == 1))
+                       {
+                               if (bbpId <= 136)
+                               {
+#ifdef RALINK_ATE
+                                       if (ATE_ON(pAdapter))
+                                       {
+                                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue);
+                                               //Read it back for showing
+                                               ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                                       }
+                                       else
+#endif // RALINK_ATE //
+                                       {
+                                           RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue);
+                                       //Read it back for showing
+                                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                       }
+                                       sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId*2, regBBP);
+                    wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                                       DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra));
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       bIsPrintAllBBP = TRUE;
+                                       goto next;
+                               }
+                       }
+                       else
+                       { //Invalid parametes, so default printk all bbp
+                               bIsPrintAllBBP = TRUE;
+                               goto next;
+                       }
+               }
+               }
+       else
+               bIsPrintAllBBP = TRUE;
+
+next:
+       if (bIsPrintAllBBP)
+       {
+               memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+               sprintf(extra, "\n");
+               for (bbpId = 0; bbpId <= 136; bbpId++)
+               {
+                   if (strlen(extra) >= (IW_PRIV_SIZE_MASK - 10))
+                break;
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                       }
+                       else
+#endif // RALINK_ATE //
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                       sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X    ", bbpId, bbpId*2, regBBP);
+                       if (bbpId%5 == 4)
+                               sprintf(extra+strlen(extra), "\n");
+               }
+
+        wrq->length = strlen(extra) + 1; // 1: size of '\0'
+        DBGPRINT(RT_DEBUG_TRACE, ("wrq->length = %d\n", wrq->length));
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<==rt_private_ioctl_bbp\n\n"));
+
+    return Status;
+}
+#endif // DBG //
+
+int rt_ioctl_siwrate(struct net_device *dev,
+                       struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
+{
+    PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+    UINT32          rate = wrqu->bitrate.value, fixed = wrqu->bitrate.fixed;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+    DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(rate = %d, fixed = %d)\n", rate, fixed));
+    /* rate = -1 => auto rate
+       rate = X, fixed = 1 => (fixed rate X)
+    */
+    if (rate == -1)
+    {
+               //Auto Rate
+               pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+               pAd->StaCfg.bAutoTxRateSwitch = TRUE;
+               if ((pAd->CommonCfg.PhyMode <= PHY_11G) ||
+                   (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))
+                       RTMPSetDesiredRates(pAd, -1);
+
+#ifdef DOT11_N_SUPPORT
+               SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+    }
+    else
+    {
+        if (fixed)
+        {
+               pAd->StaCfg.bAutoTxRateSwitch = FALSE;
+            if ((pAd->CommonCfg.PhyMode <= PHY_11G) ||
+                (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))
+                RTMPSetDesiredRates(pAd, rate);
+            else
+            {
+                pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+#ifdef DOT11_N_SUPPORT
+                SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(HtMcs=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.MCS));
+        }
+        else
+        {
+            // TODO: rate = X, fixed = 0 => (rates <= X)
+            return -EOPNOTSUPP;
+        }
+    }
+
+    return 0;
+}
+
+int rt_ioctl_giwrate(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+    PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+    int rate_index = 0, rate_count = 0;
+    HTTRANSMIT_SETTING ht_setting;
+    __s32 ralinkrate[] =
+       {2,  4,   11,  22, // CCK
+       12, 18,   24,  36, 48, 72, 96, 108, // OFDM
+       13, 26,   39,  52,  78, 104, 117, 130, 26,  52,  78, 104, 156, 208, 234, 260, // 20MHz, 800ns GI, MCS: 0 ~ 15
+       39, 78,  117, 156, 234, 312, 351, 390,                                                                            // 20MHz, 800ns GI, MCS: 16 ~ 23
+       27, 54,   81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, // 40MHz, 800ns GI, MCS: 0 ~ 15
+       81, 162, 243, 324, 486, 648, 729, 810,                                                                            // 40MHz, 800ns GI, MCS: 16 ~ 23
+       14, 29,   43,  57,  87, 115, 130, 144, 29, 59,   87, 115, 173, 230, 260, 288, // 20MHz, 400ns GI, MCS: 0 ~ 15
+       43, 87,  130, 173, 260, 317, 390, 433,                                                                            // 20MHz, 400ns GI, MCS: 16 ~ 23
+       30, 60,   90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, // 40MHz, 400ns GI, MCS: 0 ~ 15
+       90, 180, 270, 360, 540, 720, 810, 900};                                                                           // 40MHz, 400ns GI, MCS: 16 ~ 23
+
+    rate_count = sizeof(ralinkrate)/sizeof(__s32);
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+    if ((pAd->StaCfg.bAutoTxRateSwitch == FALSE) &&
+        (INFRA_ON(pAd)) &&
+        ((pAd->CommonCfg.PhyMode <= PHY_11G) || (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)))
+        ht_setting.word = pAd->StaCfg.HTPhyMode.word;
+    else
+        ht_setting.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word;
+
+#ifdef DOT11_N_SUPPORT
+    if (ht_setting.field.MODE >= MODE_HTMIX)
+    {
+//     rate_index = 12 + ((UCHAR)ht_setting.field.BW *16) + ((UCHAR)ht_setting.field.ShortGI *32) + ((UCHAR)ht_setting.field.MCS);
+       rate_index = 12 + ((UCHAR)ht_setting.field.BW *24) + ((UCHAR)ht_setting.field.ShortGI *48) + ((UCHAR)ht_setting.field.MCS);
+    }
+    else
+#endif // DOT11_N_SUPPORT //
+    if (ht_setting.field.MODE == MODE_OFDM)
+       rate_index = (UCHAR)(ht_setting.field.MCS) + 4;
+    else if (ht_setting.field.MODE == MODE_CCK)
+       rate_index = (UCHAR)(ht_setting.field.MCS);
+
+    if (rate_index < 0)
+        rate_index = 0;
+
+    if (rate_index > rate_count)
+        rate_index = rate_count;
+
+    wrqu->bitrate.value = ralinkrate[rate_index] * 500000;
+    wrqu->bitrate.disabled = 0;
+
+    return 0;
+}
+
+static const iw_handler rt_handler[] =
+{
+       (iw_handler) NULL,                                  /* SIOCSIWCOMMIT */
+       (iw_handler) rt_ioctl_giwname,                  /* SIOCGIWNAME   */
+       (iw_handler) NULL,                                  /* SIOCSIWNWID   */
+       (iw_handler) NULL,                                  /* SIOCGIWNWID   */
+       (iw_handler) rt_ioctl_siwfreq,              /* SIOCSIWFREQ   */
+       (iw_handler) rt_ioctl_giwfreq,              /* SIOCGIWFREQ   */
+       (iw_handler) rt_ioctl_siwmode,              /* SIOCSIWMODE   */
+       (iw_handler) rt_ioctl_giwmode,              /* SIOCGIWMODE   */
+       (iw_handler) NULL,                              /* SIOCSIWSENS   */
+       (iw_handler) NULL,                              /* SIOCGIWSENS   */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWRANGE  */
+       (iw_handler) rt_ioctl_giwrange,             /* SIOCGIWRANGE  */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWPRIV   */
+       (iw_handler) NULL /* kernel code */,    /* SIOCGIWPRIV   */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWSTATS  */
+       (iw_handler) rt28xx_get_wireless_stats /* kernel code */,    /* SIOCGIWSTATS  */
+       (iw_handler) NULL,                              /* SIOCSIWSPY    */
+       (iw_handler) NULL,                              /* SIOCGIWSPY    */
+       (iw_handler) NULL,                                      /* SIOCSIWTHRSPY */
+       (iw_handler) NULL,                                      /* SIOCGIWTHRSPY */
+       (iw_handler) rt_ioctl_siwap,            /* SIOCSIWAP     */
+       (iw_handler) rt_ioctl_giwap,                /* SIOCGIWAP     */
+#ifdef SIOCSIWMLME
+       (iw_handler) rt_ioctl_siwmlme,          /* SIOCSIWMLME   */
+#else
+       (iw_handler) NULL,                                      /* SIOCSIWMLME */
+#endif // SIOCSIWMLME //
+       (iw_handler) rt_ioctl_iwaplist,             /* SIOCGIWAPLIST */
+#ifdef SIOCGIWSCAN
+       (iw_handler) rt_ioctl_siwscan,              /* SIOCSIWSCAN   */
+       (iw_handler) rt_ioctl_giwscan,              /* SIOCGIWSCAN   */
+#else
+       (iw_handler) NULL,                                      /* SIOCSIWSCAN   */
+       (iw_handler) NULL,                                      /* SIOCGIWSCAN   */
+#endif /* SIOCGIWSCAN */
+       (iw_handler) rt_ioctl_siwessid,             /* SIOCSIWESSID  */
+       (iw_handler) rt_ioctl_giwessid,             /* SIOCGIWESSID  */
+       (iw_handler) rt_ioctl_siwnickn,             /* SIOCSIWNICKN  */
+       (iw_handler) rt_ioctl_giwnickn,             /* SIOCGIWNICKN  */
+       (iw_handler) NULL,                                      /* -- hole --    */
+       (iw_handler) NULL,                                      /* -- hole --    */
+       (iw_handler) rt_ioctl_siwrate,          /* SIOCSIWRATE   */
+       (iw_handler) rt_ioctl_giwrate,          /* SIOCGIWRATE   */
+       (iw_handler) rt_ioctl_siwrts,               /* SIOCSIWRTS    */
+       (iw_handler) rt_ioctl_giwrts,               /* SIOCGIWRTS    */
+       (iw_handler) rt_ioctl_siwfrag,              /* SIOCSIWFRAG   */
+       (iw_handler) rt_ioctl_giwfrag,              /* SIOCGIWFRAG   */
+       (iw_handler) NULL,                              /* SIOCSIWTXPOW  */
+       (iw_handler) NULL,                              /* SIOCGIWTXPOW  */
+       (iw_handler) NULL,                              /* SIOCSIWRETRY  */
+       (iw_handler) NULL,                              /* SIOCGIWRETRY  */
+       (iw_handler) rt_ioctl_siwencode,                /* SIOCSIWENCODE */
+       (iw_handler) rt_ioctl_giwencode,                /* SIOCGIWENCODE */
+       (iw_handler) NULL,                              /* SIOCSIWPOWER  */
+       (iw_handler) NULL,                              /* SIOCGIWPOWER  */
+       (iw_handler) NULL,                                              /* -- hole -- */
+       (iw_handler) NULL,                                              /* -- hole -- */
+#if WIRELESS_EXT > 17
+    (iw_handler) rt_ioctl_siwgenie,         /* SIOCSIWGENIE  */
+       (iw_handler) rt_ioctl_giwgenie,         /* SIOCGIWGENIE  */
+       (iw_handler) rt_ioctl_siwauth,              /* SIOCSIWAUTH   */
+       (iw_handler) rt_ioctl_giwauth,              /* SIOCGIWAUTH   */
+       (iw_handler) rt_ioctl_siwencodeext,         /* SIOCSIWENCODEEXT */
+       (iw_handler) rt_ioctl_giwencodeext,             /* SIOCGIWENCODEEXT */
+       (iw_handler) rt_ioctl_siwpmksa,         /* SIOCSIWPMKSA  */
+#endif
+};
+
+static const iw_handler rt_priv_handlers[] = {
+       (iw_handler) NULL, /* + 0x00 */
+       (iw_handler) NULL, /* + 0x01 */
+#ifndef CONFIG_AP_SUPPORT
+       (iw_handler) rt_ioctl_setparam, /* + 0x02 */
+#else
+       (iw_handler) NULL, /* + 0x02 */
+#endif // CONFIG_AP_SUPPORT //
+#ifdef DBG
+       (iw_handler) rt_private_ioctl_bbp, /* + 0x03 */
+#else
+       (iw_handler) NULL, /* + 0x03 */
+#endif
+       (iw_handler) NULL, /* + 0x04 */
+       (iw_handler) NULL, /* + 0x05 */
+       (iw_handler) NULL, /* + 0x06 */
+       (iw_handler) NULL, /* + 0x07 */
+       (iw_handler) NULL, /* + 0x08 */
+       (iw_handler) rt_private_get_statistics, /* + 0x09 */
+       (iw_handler) NULL, /* + 0x0A */
+       (iw_handler) NULL, /* + 0x0B */
+       (iw_handler) NULL, /* + 0x0C */
+       (iw_handler) NULL, /* + 0x0D */
+       (iw_handler) NULL, /* + 0x0E */
+       (iw_handler) NULL, /* + 0x0F */
+       (iw_handler) NULL, /* + 0x10 */
+       (iw_handler) rt_private_show, /* + 0x11 */
+    (iw_handler) NULL, /* + 0x12 */
+       (iw_handler) NULL, /* + 0x13 */
+       (iw_handler) NULL, /* + 0x15 */
+       (iw_handler) NULL, /* + 0x17 */
+       (iw_handler) NULL, /* + 0x18 */
+};
+
+const struct iw_handler_def rt28xx_iw_handler_def =
+{
+#define        N(a)    (sizeof (a) / sizeof (a[0]))
+       .standard       = (iw_handler *) rt_handler,
+       .num_standard   = sizeof(rt_handler) / sizeof(iw_handler),
+       .private        = (iw_handler *) rt_priv_handlers,
+       .num_private            = N(rt_priv_handlers),
+       .private_args   = (struct iw_priv_args *) privtab,
+       .num_private_args       = N(privtab),
+#if IW_HANDLER_VERSION >= 7
+    .get_wireless_stats = rt28xx_get_wireless_stats,
+#endif
+};
+
+INT RTMPSetInformation(
+    IN  PRTMP_ADAPTER pAdapter,
+    IN  OUT struct ifreq    *rq,
+    IN  INT                 cmd)
+{
+    struct iwreq                        *wrq = (struct iwreq *) rq;
+    NDIS_802_11_SSID                    Ssid;
+    NDIS_802_11_MAC_ADDRESS             Bssid;
+    RT_802_11_PHY_MODE                  PhyMode;
+    RT_802_11_STA_CONFIG                StaConfig;
+    NDIS_802_11_RATES                   aryRates;
+    RT_802_11_PREAMBLE                  Preamble;
+    NDIS_802_11_WEP_STATUS              WepStatus;
+    NDIS_802_11_AUTHENTICATION_MODE     AuthMode = Ndis802_11AuthModeMax;
+    NDIS_802_11_NETWORK_INFRASTRUCTURE  BssType;
+    NDIS_802_11_RTS_THRESHOLD           RtsThresh;
+    NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh;
+    NDIS_802_11_POWER_MODE              PowerMode;
+    PNDIS_802_11_KEY                    pKey = NULL;
+    PNDIS_802_11_WEP                           pWepKey =NULL;
+    PNDIS_802_11_REMOVE_KEY             pRemoveKey = NULL;
+    NDIS_802_11_CONFIGURATION           Config, *pConfig = NULL;
+    NDIS_802_11_NETWORK_TYPE            NetType;
+    ULONG                               Now;
+    UINT                                KeyIdx = 0;
+    INT                                 Status = NDIS_STATUS_SUCCESS, MaxPhyMode = PHY_11G;
+    ULONG                               PowerTemp;
+    BOOLEAN                             RadioState;
+    BOOLEAN                             StateMachineTouched = FALSE;
+#ifdef DOT11_N_SUPPORT
+       OID_SET_HT_PHYMODE                                      HT_PhyMode;     //11n ,kathy
+#endif // DOT11_N_SUPPORT //
+#ifdef WPA_SUPPLICANT_SUPPORT
+    PNDIS_802_11_PMKID                  pPmkId = NULL;
+    BOOLEAN                                            IEEE8021xState = FALSE;
+    BOOLEAN                                            IEEE8021x_required_keys = FALSE;
+    UCHAR                               wpa_supplicant_enable = 0;
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef SNMP_SUPPORT
+       TX_RTY_CFG_STRUC                        tx_rty_cfg;
+       ULONG                                           ShortRetryLimit, LongRetryLimit;
+       UCHAR                                           ctmp;
+#endif // SNMP_SUPPORT //
+
+
+
+#ifdef DOT11_N_SUPPORT
+       MaxPhyMode = PHY_11N_5G;
+#endif // DOT11_N_SUPPORT //
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("-->RTMPSetInformation(),     0x%08x\n", cmd&0x7FFF));
+    switch(cmd & 0x7FFF) {
+        case RT_OID_802_11_COUNTRY_REGION:
+            if (wrq->u.data.length < sizeof(UCHAR))
+                Status = -EINVAL;
+                       // Only avaliable when EEPROM not programming
+            else if (!(pAdapter->CommonCfg.CountryRegion & 0x80) && !(pAdapter->CommonCfg.CountryRegionForABand & 0x80))
+            {
+                ULONG   Country;
+                UCHAR  TmpPhy;
+
+                               Status = copy_from_user(&Country, wrq->u.data.pointer, wrq->u.data.length);
+                               pAdapter->CommonCfg.CountryRegion = (UCHAR)(Country & 0x000000FF);
+                               pAdapter->CommonCfg.CountryRegionForABand = (UCHAR)((Country >> 8) & 0x000000FF);
+                TmpPhy = pAdapter->CommonCfg.PhyMode;
+                               pAdapter->CommonCfg.PhyMode = 0xff;
+                               // Build all corresponding channel information
+                               RTMPSetPhyMode(pAdapter, TmpPhy);
+#ifdef DOT11_N_SUPPORT
+                               SetCommonHT(pAdapter);
+#endif // DOT11_N_SUPPORT //
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_COUNTRY_REGION (A:%d  B/G:%d)\n", pAdapter->CommonCfg.CountryRegionForABand,
+                                   pAdapter->CommonCfg.CountryRegion));
+            }
+            break;
+        case OID_802_11_BSSID_LIST_SCAN:
+ #ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               break;
+                       }
+#endif // RALINK_ATE //
+            Now = jiffies;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID_LIST_SCAN, TxCnt = %d \n", pAdapter->RalinkCounters.LastOneSecTotalTxCount));
+
+            if (MONITOR_ON(pAdapter))
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n"));
+                break;
+            }
+
+                       //Benson add 20080527, when radio off, sta don't need to scan
+                       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF))
+                               break;
+
+                       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+                       {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is scanning now !!!\n"));
+                               pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE;
+                               Status = NDIS_STATUS_SUCCESS;
+                break;
+            }
+
+                       if (pAdapter->RalinkCounters.LastOneSecTotalTxCount > 100)
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, ignore this set::OID_802_11_BSSID_LIST_SCAN\n"));
+                               Status = NDIS_STATUS_SUCCESS;
+                               pAdapter->StaCfg.ScanCnt = 99;          // Prevent auto scan triggered by this OID
+                               break;
+            }
+
+            if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) &&
+                               ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+                               (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+                               (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
+                               (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) &&
+                (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n"));
+                               Status = NDIS_STATUS_SUCCESS;
+                               pAdapter->StaCfg.ScanCnt = 99;          // Prevent auto scan triggered by this OID
+                               break;
+            }
+
+
+            if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+            {
+                RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+            }
+
+            // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+            // this request, because this request is initiated by NDIS.
+            pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+            // Reset allowed scan retries
+            pAdapter->StaCfg.ScanCnt = 0;
+            pAdapter->StaCfg.LastScanTime = Now;
+
+                       pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE;
+            RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+            MlmeEnqueue(pAdapter,
+                        MLME_CNTL_STATE_MACHINE,
+                        OID_802_11_BSSID_LIST_SCAN,
+                        0,
+                        NULL);
+
+            Status = NDIS_STATUS_SUCCESS;
+            StateMachineTouched = TRUE;
+            break;
+        case OID_802_11_SSID:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_SSID))
+                Status = -EINVAL;
+            else
+            {
+               PCHAR pSsidString = NULL;
+                Status = copy_from_user(&Ssid, wrq->u.data.pointer, wrq->u.data.length);
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SSID (Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid));
+                if (Ssid.SsidLength > MAX_LEN_OF_SSID)
+                    Status = -EINVAL;
+                else
+                {
+                       if (Ssid.SsidLength == 0)
+                       {
+                               Set_SSID_Proc(pAdapter, "");
+                       }
+                                       else
+                       {
+                               pSsidString = (CHAR *) kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG);
+                                               if (pSsidString)
+                                               {
+                                                       NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1);
+                                                       NdisMoveMemory(pSsidString, Ssid.Ssid, Ssid.SsidLength);
+                                       Set_SSID_Proc(pAdapter, pSsidString);
+                                                       kfree(pSsidString);
+                                               }
+                                               else
+                                                       Status = -ENOMEM;
+                       }
+                }
+            }
+            break;
+        case OID_802_11_BSSID:
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               break;
+                       }
+#endif // RALINK_ATE //
+            if (wrq->u.data.length != sizeof(NDIS_802_11_MAC_ADDRESS))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&Bssid, wrq->u.data.pointer, wrq->u.data.length);
+
+                // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+                // this request, because this request is initiated by NDIS.
+                pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+
+                               // Prevent to connect AP again in STAMlmePeriodicExec
+                               pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+
+                // Reset allowed scan retries
+                               pAdapter->StaCfg.ScanCnt = 0;
+
+                if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+                {
+                    RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                    DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+                }
+                MlmeEnqueue(pAdapter,
+                            MLME_CNTL_STATE_MACHINE,
+                            OID_802_11_BSSID,
+                            sizeof(NDIS_802_11_MAC_ADDRESS),
+                            (VOID *)&Bssid);
+                Status = NDIS_STATUS_SUCCESS;
+                StateMachineTouched = TRUE;
+
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                        Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
+            }
+            break;
+        case RT_OID_802_11_RADIO:
+            if (wrq->u.data.length != sizeof(BOOLEAN))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&RadioState, wrq->u.data.pointer, wrq->u.data.length);
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RADIO (=%d)\n", RadioState));
+                if (pAdapter->StaCfg.bSwRadio != RadioState)
+                {
+                    pAdapter->StaCfg.bSwRadio = RadioState;
+                    if (pAdapter->StaCfg.bRadio != (pAdapter->StaCfg.bHwRadio && pAdapter->StaCfg.bSwRadio))
+                    {
+                        pAdapter->StaCfg.bRadio = (pAdapter->StaCfg.bHwRadio && pAdapter->StaCfg.bSwRadio);
+                        if (pAdapter->StaCfg.bRadio == TRUE)
+                        {
+                            MlmeRadioOn(pAdapter);
+                            // Update extra information
+                                                       pAdapter->ExtraInfo = EXTRA_INFO_CLEAR;
+                        }
+                        else
+                        {
+                            MlmeRadioOff(pAdapter);
+                            // Update extra information
+                                                       pAdapter->ExtraInfo = SW_RADIO_OFF;
+                        }
+                    }
+                }
+            }
+            break;
+        case RT_OID_802_11_PHY_MODE:
+            if (wrq->u.data.length != sizeof(RT_802_11_PHY_MODE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&PhyMode, wrq->u.data.pointer, wrq->u.data.length);
+                               if (PhyMode <= MaxPhyMode)
+                               {
+                       RTMPSetPhyMode(pAdapter, PhyMode);
+#ifdef DOT11_N_SUPPORT
+                                       SetCommonHT(pAdapter);
+#endif // DOT11_N_SUPPORT //
+                               }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PHY_MODE (=%d)\n", PhyMode));
+            }
+            break;
+        case RT_OID_802_11_STA_CONFIG:
+            if (wrq->u.data.length != sizeof(RT_802_11_STA_CONFIG))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&StaConfig, wrq->u.data.pointer, wrq->u.data.length);
+                pAdapter->CommonCfg.bEnableTxBurst = StaConfig.EnableTxBurst;
+                pAdapter->CommonCfg.UseBGProtection = StaConfig.UseBGProtection;
+                pAdapter->CommonCfg.bUseShortSlotTime = 1; // 2003-10-30 always SHORT SLOT capable
+                if ((pAdapter->CommonCfg.PhyMode != StaConfig.AdhocMode) &&
+                                       (StaConfig.AdhocMode <= MaxPhyMode))
+                {
+                    // allow dynamic change of "USE OFDM rate or not" in ADHOC mode
+                    // if setting changed, need to reset current TX rate as well as BEACON frame format
+                    if (pAdapter->StaCfg.BssType == BSS_ADHOC)
+                    {
+                                               pAdapter->CommonCfg.PhyMode = StaConfig.AdhocMode;
+                       RTMPSetPhyMode(pAdapter, PhyMode);
+                        MlmeUpdateTxRates(pAdapter, FALSE, 0);
+                        MakeIbssBeacon(pAdapter);           // re-build BEACON frame
+                        AsicEnableIbssSync(pAdapter);   // copy to on-chip memory
+                    }
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_STA_CONFIG (Burst=%d, Protection=%ld,ShortSlot=%d\n",
+                                        pAdapter->CommonCfg.bEnableTxBurst,
+                                        pAdapter->CommonCfg.UseBGProtection,
+                                        pAdapter->CommonCfg.bUseShortSlotTime));
+            }
+            break;
+        case OID_802_11_DESIRED_RATES:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_RATES))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&aryRates, wrq->u.data.pointer, wrq->u.data.length);
+                NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES);
+                NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES));
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DESIRED_RATES (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n",
+                    pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1],
+                    pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3],
+                    pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5],
+                    pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] ));
+                // Changing DesiredRate may affect the MAX TX rate we used to TX frames out
+                MlmeUpdateTxRates(pAdapter, FALSE, 0);
+            }
+            break;
+        case RT_OID_802_11_PREAMBLE:
+            if (wrq->u.data.length != sizeof(RT_802_11_PREAMBLE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&Preamble, wrq->u.data.pointer, wrq->u.data.length);
+                if (Preamble == Rt802_11PreambleShort)
+                {
+                    pAdapter->CommonCfg.TxPreamble = Preamble;
+                    MlmeSetTxPreamble(pAdapter, Rt802_11PreambleShort);
+                }
+                else if ((Preamble == Rt802_11PreambleLong) || (Preamble == Rt802_11PreambleAuto))
+                {
+                    // if user wants AUTO, initialize to LONG here, then change according to AP's
+                    // capability upon association.
+                    pAdapter->CommonCfg.TxPreamble = Preamble;
+                    MlmeSetTxPreamble(pAdapter, Rt802_11PreambleLong);
+                }
+                else
+                {
+                    Status = -EINVAL;
+                    break;
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PREAMBLE (=%d)\n", Preamble));
+            }
+            break;
+        case OID_802_11_WEP_STATUS:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_WEP_STATUS))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&WepStatus, wrq->u.data.pointer, wrq->u.data.length);
+                // Since TKIP, AES, WEP are all supported. It should not have any invalid setting
+                if (WepStatus <= Ndis802_11Encryption3KeyAbsent)
+                {
+                    if (pAdapter->StaCfg.WepStatus != WepStatus)
+                    {
+                        // Config has changed
+                        pAdapter->bConfigChanged = TRUE;
+                    }
+                    pAdapter->StaCfg.WepStatus     = WepStatus;
+                    pAdapter->StaCfg.OrigWepStatus = WepStatus;
+                    pAdapter->StaCfg.PairCipher    = WepStatus;
+                       pAdapter->StaCfg.GroupCipher   = WepStatus;
+                }
+                else
+                {
+                    Status  = -EINVAL;
+                    break;
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEP_STATUS (=%d)\n",WepStatus));
+            }
+            break;
+        case OID_802_11_AUTHENTICATION_MODE:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_AUTHENTICATION_MODE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&AuthMode, wrq->u.data.pointer, wrq->u.data.length);
+                if (AuthMode > Ndis802_11AuthModeMax)
+                {
+                    Status  = -EINVAL;
+                    break;
+                }
+                else
+                {
+                    if (pAdapter->StaCfg.AuthMode != AuthMode)
+                    {
+                        // Config has changed
+                        pAdapter->bConfigChanged = TRUE;
+                    }
+                    pAdapter->StaCfg.AuthMode = AuthMode;
+                }
+                pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n",pAdapter->StaCfg.AuthMode));
+            }
+            break;
+        case OID_802_11_INFRASTRUCTURE_MODE:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&BssType, wrq->u.data.pointer, wrq->u.data.length);
+
+                               if (BssType == Ndis802_11IBSS)
+                                       Set_NetworkType_Proc(pAdapter, "Adhoc");
+                               else if (BssType == Ndis802_11Infrastructure)
+                                       Set_NetworkType_Proc(pAdapter, "Infra");
+                               else if (BssType == Ndis802_11Monitor)
+                                       Set_NetworkType_Proc(pAdapter, "Monitor");
+                               else
+                               {
+                                       Status  = -EINVAL;
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_INFRASTRUCTURE_MODE (unknown)\n"));
+                               }
+                       }
+                       break;
+        case OID_802_11_REMOVE_WEP:
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_WEP\n"));
+            if (wrq->u.data.length != sizeof(NDIS_802_11_KEY_INDEX))
+            {
+                               Status = -EINVAL;
+            }
+            else
+            {
+                               KeyIdx = *(NDIS_802_11_KEY_INDEX *) wrq->u.data.pointer;
+
+                               if (KeyIdx & 0x80000000)
+                               {
+                                       // Should never set default bit when remove key
+                                       Status = -EINVAL;
+                               }
+                               else
+                               {
+                                       KeyIdx = KeyIdx & 0x0fffffff;
+                                       if (KeyIdx >= 4){
+                                               Status = -EINVAL;
+                                       }
+                                       else
+                                       {
+                                               pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = 0;
+                                               pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE;
+                                               AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)KeyIdx);
+                                       }
+                               }
+            }
+            break;
+        case RT_OID_802_11_RESET_COUNTERS:
+            NdisZeroMemory(&pAdapter->WlanCounters, sizeof(COUNTER_802_11));
+            NdisZeroMemory(&pAdapter->Counters8023, sizeof(COUNTER_802_3));
+            NdisZeroMemory(&pAdapter->RalinkCounters, sizeof(COUNTER_RALINK));
+            pAdapter->Counters8023.RxNoBuffer   = 0;
+                       pAdapter->Counters8023.GoodReceives = 0;
+                       pAdapter->Counters8023.RxNoBuffer   = 0;
+#ifdef RT2870
+                       pAdapter->BulkOutComplete       = 0;
+                       pAdapter->BulkOutCompleteOther= 0;
+                       pAdapter->BulkOutCompleteCancel = 0;
+                       pAdapter->BulkOutReq = 0;
+                       pAdapter->BulkInReq= 0;
+                       pAdapter->BulkInComplete = 0;
+                       pAdapter->BulkInCompleteFail = 0;
+#endif // RT2870 //
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RESET_COUNTERS \n"));
+            break;
+        case OID_802_11_RTS_THRESHOLD:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_RTS_THRESHOLD))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&RtsThresh, wrq->u.data.pointer, wrq->u.data.length);
+                if (RtsThresh > MAX_RTS_THRESHOLD)
+                    Status  = -EINVAL;
+                else
+                    pAdapter->CommonCfg.RtsThreshold = (USHORT)RtsThresh;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_RTS_THRESHOLD (=%ld)\n",RtsThresh));
+            break;
+        case OID_802_11_FRAGMENTATION_THRESHOLD:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_FRAGMENTATION_THRESHOLD))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&FragThresh, wrq->u.data.pointer, wrq->u.data.length);
+                pAdapter->CommonCfg.bUseZeroToDisableFragment = FALSE;
+                if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD)
+                {
+                    if (FragThresh == 0)
+                    {
+                        pAdapter->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;
+                        pAdapter->CommonCfg.bUseZeroToDisableFragment = TRUE;
+                    }
+                    else
+                        Status  = -EINVAL;
+                }
+                else
+                    pAdapter->CommonCfg.FragmentThreshold = (USHORT)FragThresh;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_FRAGMENTATION_THRESHOLD (=%ld) \n",FragThresh));
+            break;
+        case OID_802_11_POWER_MODE:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_POWER_MODE))
+                Status = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&PowerMode, wrq->u.data.pointer, wrq->u.data.length);
+                if (PowerMode == Ndis802_11PowerModeCAM)
+                       Set_PSMode_Proc(pAdapter, "CAM");
+                else if (PowerMode == Ndis802_11PowerModeMAX_PSP)
+                       Set_PSMode_Proc(pAdapter, "Max_PSP");
+                else if (PowerMode == Ndis802_11PowerModeFast_PSP)
+                                       Set_PSMode_Proc(pAdapter, "Fast_PSP");
+                else if (PowerMode == Ndis802_11PowerModeLegacy_PSP)
+                                       Set_PSMode_Proc(pAdapter, "Legacy_PSP");
+                else
+                    Status = -EINVAL;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_POWER_MODE (=%d)\n",PowerMode));
+            break;
+         case RT_OID_802_11_TX_POWER_LEVEL_1:
+                       if (wrq->u.data.length  < sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&PowerTemp, wrq->u.data.pointer, wrq->u.data.length);
+                               if (PowerTemp > 100)
+                                       PowerTemp = 0xffffffff;  // AUTO
+                               pAdapter->CommonCfg.TxPowerDefault = PowerTemp; //keep current setting.
+                                       pAdapter->CommonCfg.TxPowerPercentage = pAdapter->CommonCfg.TxPowerDefault;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAdapter->CommonCfg.TxPowerPercentage));
+                       }
+               break;
+               case OID_802_11_NETWORK_TYPE_IN_USE:
+                       if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_TYPE))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&NetType, wrq->u.data.pointer, wrq->u.data.length);
+
+                               if (NetType == Ndis802_11DS)
+                                       RTMPSetPhyMode(pAdapter, PHY_11B);
+                               else if (NetType == Ndis802_11OFDM24)
+                                       RTMPSetPhyMode(pAdapter, PHY_11BG_MIXED);
+                               else if (NetType == Ndis802_11OFDM5)
+                                       RTMPSetPhyMode(pAdapter, PHY_11A);
+                               else
+                                       Status = -EINVAL;
+#ifdef DOT11_N_SUPPORT
+                               if (Status == NDIS_STATUS_SUCCESS)
+                                       SetCommonHT(pAdapter);
+#endif // DOT11_N_SUPPORT //
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_NETWORK_TYPE_IN_USE (=%d)\n",NetType));
+                   }
+                       break;
+        // For WPA PSK PMK key
+        case RT_OID_802_11_ADD_WPA:
+            pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+            if(pKey == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+
+            Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (pKey->Length != wrq->u.data.length)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!!\n"));
+            }
+            else
+            {
+                if ((pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) &&
+                                   (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) &&
+                                   (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) )
+                {
+                    Status = -EOPNOTSUPP;
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!! [AuthMode != WPAPSK/WPA2PSK/WPANONE]\n"));
+                }
+                else if ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+                                                (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
+                                                (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) )     // Only for WPA PSK mode
+                               {
+                    NdisMoveMemory(pAdapter->StaCfg.PMK, &pKey->KeyMaterial, pKey->KeyLength);
+                    // Use RaConfig as PSK agent.
+                    // Start STA supplicant state machine
+                    if (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone)
+                        pAdapter->StaCfg.WpaState = SS_START;
+
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength));
+                }
+                else
+                {
+                    pAdapter->StaCfg.WpaState = SS_NOTUSE;
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength));
+                }
+            }
+            kfree(pKey);
+            break;
+        case OID_802_11_REMOVE_KEY:
+            pRemoveKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+            if(pRemoveKey == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+
+            Status = copy_from_user(pRemoveKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (pRemoveKey->Length != wrq->u.data.length)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!\n"));
+            }
+            else
+            {
+                if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+                {
+                    RTMPWPARemoveKeyProc(pAdapter, pRemoveKey);
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Remove WPA Key!!\n"));
+                }
+                else
+                {
+                    KeyIdx = pRemoveKey->KeyIndex;
+
+                    if (KeyIdx & 0x80000000)
+                    {
+                        // Should never set default bit when remove key
+                        Status  = -EINVAL;
+                        DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(Should never set default bit when remove key)\n"));
+                    }
+                    else
+                    {
+                        KeyIdx = KeyIdx & 0x0fffffff;
+                        if (KeyIdx > 3)
+                        {
+                            Status  = -EINVAL;
+                            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(KeyId[%d] out of range)\n", KeyIdx));
+                        }
+                        else
+                        {
+                            pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = 0;
+                            pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE;
+                            AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)KeyIdx);
+                            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY (id=0x%x, Len=%d-byte)\n", pRemoveKey->KeyIndex, pRemoveKey->Length));
+                        }
+                    }
+                }
+            }
+            kfree(pRemoveKey);
+            break;
+        // New for WPA
+        case OID_802_11_ADD_KEY:
+            pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+            if(pKey == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+            Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (pKey->Length != wrq->u.data.length)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY, Failed!!\n"));
+            }
+            else
+            {
+                RTMPAddKey(pAdapter, pKey);
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength));
+            }
+            kfree(pKey);
+            break;
+        case OID_802_11_CONFIGURATION:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_CONFIGURATION))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&Config, wrq->u.data.pointer, wrq->u.data.length);
+                pConfig = &Config;
+
+                if ((pConfig->BeaconPeriod >= 20) && (pConfig->BeaconPeriod <=400))
+                     pAdapter->CommonCfg.BeaconPeriod = (USHORT) pConfig->BeaconPeriod;
+
+                pAdapter->StaActive.AtimWin = (USHORT) pConfig->ATIMWindow;
+                MAP_KHZ_TO_CHANNEL_ID(pConfig->DSConfig, pAdapter->CommonCfg.Channel);
+                //
+                               // Save the channel on MlmeAux for CntlOidRTBssidProc used.
+                               //
+                               pAdapter->MlmeAux.Channel = pAdapter->CommonCfg.Channel;
+
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CONFIGURATION (BeacnPeriod=%ld,AtimW=%ld,Ch=%d)\n",
+                    pConfig->BeaconPeriod, pConfig->ATIMWindow, pAdapter->CommonCfg.Channel));
+                // Config has changed
+                pAdapter->bConfigChanged = TRUE;
+            }
+            break;
+#ifdef DOT11_N_SUPPORT
+               case RT_OID_802_11_SET_HT_PHYMODE:
+                       if (wrq->u.data.length  != sizeof(OID_SET_HT_PHYMODE))
+                               Status = -EINVAL;
+                       else
+                       {
+                           POID_SET_HT_PHYMODE pHTPhyMode = &HT_PhyMode;
+
+                               Status = copy_from_user(&HT_PhyMode, wrq->u.data.pointer, wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::pHTPhyMode      (PhyMode = %d,TransmitNo = %d, HtMode = %d,     ExtOffset =     %d , MCS = %d, BW =     %d,     STBC = %d, SHORTGI = %d) \n",
+                               pHTPhyMode->PhyMode, pHTPhyMode->TransmitNo,pHTPhyMode->HtMode,pHTPhyMode->ExtOffset,
+                               pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC,      pHTPhyMode->SHORTGI));
+                               if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+                                       RTMPSetHT(pAdapter,     pHTPhyMode);
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_HT_PHYMODE(MCS=%d,BW=%d,SGI=%d,STBC=%d)\n",
+                               pAdapter->StaCfg.HTPhyMode.field.MCS, pAdapter->StaCfg.HTPhyMode.field.BW, pAdapter->StaCfg.HTPhyMode.field.ShortGI,
+                               pAdapter->StaCfg.HTPhyMode.field.STBC));
+                       break;
+#endif // DOT11_N_SUPPORT //
+               case RT_OID_802_11_SET_APSD_SETTING:
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               ULONG apsd ;
+                               Status = copy_from_user(&apsd, wrq->u.data.pointer,     wrq->u.data.length);
+
+                               /*-------------------------------------------------------------------
+                               |B31~B7 |       B6~B5    |       B4      |       B3      |      B2       |      B1       |         B0           |
+                               ---------------------------------------------------------------------
+                               | Rsvd  | Max SP Len | AC_VO | AC_VI | AC_BK | AC_BE | APSD     Capable |
+                               ---------------------------------------------------------------------*/
+                               pAdapter->CommonCfg.bAPSDCapable = (apsd & 0x00000001) ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_BE = ((apsd & 0x00000002) >> 1)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_BK = ((apsd & 0x00000004) >> 2)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_VI = ((apsd & 0x00000008) >> 3)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_VO = ((apsd & 0x00000010) >> 4)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.MaxSPLength = (UCHAR)((apsd & 0x00000060) >> 5);
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_SETTING (apsd=0x%lx, APSDCap=%d, [BE,BK,VI,VO]=[%d/%d/%d/%d],    MaxSPLen=%d)\n", apsd, pAdapter->CommonCfg.bAPSDCapable,
+                                       pAdapter->CommonCfg.bAPSDAC_BE, pAdapter->CommonCfg.bAPSDAC_BK, pAdapter->CommonCfg.bAPSDAC_VI, pAdapter->CommonCfg.bAPSDAC_VO, pAdapter->CommonCfg.MaxSPLength));
+                       }
+                       break;
+
+               case RT_OID_802_11_SET_APSD_PSM:
+                       if (wrq->u.data.length  != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               // Driver needs to notify AP when PSM changes
+                               Status = copy_from_user(&pAdapter->CommonCfg.bAPSDForcePowerSave, wrq->u.data.pointer, wrq->u.data.length);
+                               if (pAdapter->CommonCfg.bAPSDForcePowerSave     != pAdapter->StaCfg.Psm)
+                               {
+                                       MlmeSetPsmBit(pAdapter, pAdapter->CommonCfg.bAPSDForcePowerSave);
+                                       RTMPSendNullFrame(pAdapter,     pAdapter->CommonCfg.TxRate,     TRUE);
+                               }
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_PSM (bAPSDForcePowerSave:%d)\n", pAdapter->CommonCfg.bAPSDForcePowerSave));
+                       }
+                       break;
+#ifdef QOS_DLS_SUPPORT
+               case RT_OID_802_11_SET_DLS:
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               BOOLEAN oldvalue = pAdapter->CommonCfg.bDLSCapable;
+                               Status = copy_from_user(&pAdapter->CommonCfg.bDLSCapable, wrq->u.data.pointer, wrq->u.data.length);
+                               if (oldvalue && !pAdapter->CommonCfg.bDLSCapable)
+                               {
+                                       int     i;
+                                       // tear down local dls table entry
+                                       for     (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+                                       {
+                                               if (pAdapter->StaCfg.DLSEntry[i].Valid && (pAdapter->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+                                               {
+                                                       pAdapter->StaCfg.DLSEntry[i].Status     = DLS_NONE;
+                                                       pAdapter->StaCfg.DLSEntry[i].Valid      = FALSE;
+                                                       RTMPSendDLSTearDownFrame(pAdapter, pAdapter->StaCfg.DLSEntry[i].MacAddr);
+                                               }
+                                       }
+
+                                       // tear down peer dls table     entry
+                                       for     (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+                                       {
+                                               if (pAdapter->StaCfg.DLSEntry[i].Valid && (pAdapter->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+                                               {
+                                                       pAdapter->StaCfg.DLSEntry[i].Status     = DLS_NONE;
+                                                       pAdapter->StaCfg.DLSEntry[i].Valid      = FALSE;
+                                                       RTMPSendDLSTearDownFrame(pAdapter, pAdapter->StaCfg.DLSEntry[i].MacAddr);
+                                               }
+                                       }
+                               }
+
+                               DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS (=%d)\n", pAdapter->CommonCfg.bDLSCapable));
+                       }
+                       break;
+
+               case RT_OID_802_11_SET_DLS_PARAM:
+                       if (wrq->u.data.length  != sizeof(RT_802_11_DLS_UI))
+                               Status = -EINVAL;
+                       else
+                       {
+                               RT_802_11_DLS   Dls;
+
+                               NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
+                               RTMPMoveMemory(&Dls, wrq->u.data.pointer, sizeof(RT_802_11_DLS_UI));
+                               MlmeEnqueue(pAdapter,
+                                                       MLME_CNTL_STATE_MACHINE,
+                                                       RT_OID_802_11_SET_DLS_PARAM,
+                                                       sizeof(RT_802_11_DLS),
+                                                       &Dls);
+                               DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS_PARAM \n"));
+                       }
+                       break;
+#endif // QOS_DLS_SUPPORT //
+               case RT_OID_802_11_SET_WMM:
+                       if (wrq->u.data.length  != sizeof(BOOLEAN))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&pAdapter->CommonCfg.bWmmCapable, wrq->u.data.pointer, wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_WMM (=%d)     \n", pAdapter->CommonCfg.bWmmCapable));
+                       }
+                       break;
+
+               case OID_802_11_DISASSOCIATE:
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               break;
+                       }
+#endif // RALINK_ATE //
+                       //
+                       // Set NdisRadioStateOff to     TRUE, instead of called MlmeRadioOff.
+                       // Later on, NDIS_802_11_BSSID_LIST_EX->NumberOfItems should be 0
+                       // when query OID_802_11_BSSID_LIST.
+                       //
+                       // TRUE:  NumberOfItems will set to     0.
+                       // FALSE: NumberOfItems no change.
+                       //
+                       pAdapter->CommonCfg.NdisRadioStateOff = TRUE;
+                       // Set to immediately send the media disconnect event
+                       pAdapter->MlmeAux.CurrReqIsFromNdis     = TRUE;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DISASSOCIATE \n"));
+
+                       if (INFRA_ON(pAdapter))
+                       {
+                               if (pAdapter->Mlme.CntlMachine.CurrState !=     CNTL_IDLE)
+                               {
+                                       RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME     busy, reset     MLME state machine !!!\n"));
+                               }
+
+                               MlmeEnqueue(pAdapter,
+                                       MLME_CNTL_STATE_MACHINE,
+                                       OID_802_11_DISASSOCIATE,
+                                       0,
+                                       NULL);
+
+                               StateMachineTouched     = TRUE;
+                       }
+                       break;
+
+#ifdef DOT11_N_SUPPORT
+               case RT_OID_802_11_SET_IMME_BA_CAP:
+                               if (wrq->u.data.length != sizeof(OID_BACAP_STRUC))
+                                       Status = -EINVAL;
+                               else
+                               {
+                                       OID_BACAP_STRUC Orde ;
+                                       Status = copy_from_user(&Orde, wrq->u.data.pointer, wrq->u.data.length);
+                                       if (Orde.Policy > BA_NOTUSE)
+                                       {
+                                               Status = NDIS_STATUS_INVALID_DATA;
+                                       }
+                                       else if (Orde.Policy == BA_NOTUSE)
+                                       {
+                                               pAdapter->CommonCfg.BACapability.field.Policy = BA_NOTUSE;
+                                               pAdapter->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MimoPs= Orde.MMPSmode;
+                                               pAdapter->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode;
+                                               // UPdata to HT IE
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode;
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize;
+                                               pAdapter->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity;
+                                       }
+                                       else
+                                       {
+                        pAdapter->CommonCfg.BACapability.field.AutoBA = Orde.AutoBA;
+                                               pAdapter->CommonCfg.BACapability.field.Policy = IMMED_BA; // we only support immediate BA.
+                                               pAdapter->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MimoPs = Orde.MMPSmode;
+                                               pAdapter->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode;
+
+                                               // UPdata to HT IE
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode;
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize;
+                                               pAdapter->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity;
+
+                                               if (pAdapter->CommonCfg.BACapability.field.RxBAWinLimit > MAX_RX_REORDERBUF)
+                                                       pAdapter->CommonCfg.BACapability.field.RxBAWinLimit = MAX_RX_REORDERBUF;
+
+                                       }
+
+                                       pAdapter->CommonCfg.REGBACapability.word = pAdapter->CommonCfg.BACapability.word;
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::(Orde.AutoBA = %d) (Policy=%d)(ReBAWinLimit=%d)(TxBAWinLimit=%d)(AutoMode=%d)\n",Orde.AutoBA, pAdapter->CommonCfg.BACapability.field.Policy,
+                                               pAdapter->CommonCfg.BACapability.field.RxBAWinLimit,pAdapter->CommonCfg.BACapability.field.TxBAWinLimit, pAdapter->CommonCfg.BACapability.field.AutoBA));
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::(MimoPs = %d)(AmsduEnable = %d) (AmsduSize=%d)(MpduDensity=%d)\n",pAdapter->CommonCfg.DesiredHtPhy.MimoPs, pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable,
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduSize, pAdapter->CommonCfg.DesiredHtPhy.MpduDensity));
+                               }
+
+                               break;
+               case RT_OID_802_11_ADD_IMME_BA:
+                       DBGPRINT(RT_DEBUG_TRACE, (" Set :: RT_OID_802_11_ADD_IMME_BA \n"));
+                       if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY))
+                                       Status = -EINVAL;
+                       else
+                       {
+                               UCHAR                   index;
+                               OID_ADD_BA_ENTRY    BA;
+                               MAC_TABLE_ENTRY     *pEntry;
+
+                               Status = copy_from_user(&BA, wrq->u.data.pointer, wrq->u.data.length);
+                               if (BA.TID > 15)
+                               {
+                                       Status = NDIS_STATUS_INVALID_DATA;
+                                       break;
+                               }
+                               else
+                               {
+                                       //BATableInsertEntry
+                                       //As ad-hoc mode, BA pair is not limited to only BSSID. so add via OID.
+                                       index = BA.TID;
+                                       // in ad hoc mode, when adding BA pair, we should insert this entry into MACEntry too
+                                       pEntry = MacTableLookup(pAdapter, BA.MACAddr);
+                                       if (!pEntry)
+                                       {
+                                               DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_802_11_ADD_IMME_BA. break on no connection.----:%x:%x\n", BA.MACAddr[4], BA.MACAddr[5]));
+                                               break;
+                                       }
+                                       if (BA.IsRecipient == FALSE)
+                                       {
+                                           if (pEntry->bIAmBadAtheros == TRUE)
+                                                       pAdapter->CommonCfg.BACapability.field.RxBAWinLimit = 0x10;
+
+                                               BAOriSessionSetUp(pAdapter, pEntry, index, 0, 100, TRUE);
+                                       }
+                                       else
+                                       {
+                                               //BATableInsertEntry(pAdapter, pEntry->Aid, BA.MACAddr, 0, 0xffff, BA.TID, BA.nMSDU, BA.IsRecipient);
+                                       }
+
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_IMME_BA. Rec = %d. Mac = %x:%x:%x:%x:%x:%x . \n",
+                                               BA.IsRecipient, BA.MACAddr[0], BA.MACAddr[1], BA.MACAddr[2], BA.MACAddr[2]
+                                               , BA.MACAddr[4], BA.MACAddr[5]));
+                               }
+                       }
+                       break;
+
+               case RT_OID_802_11_TEAR_IMME_BA:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA \n"));
+                       if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY))
+                                       Status = -EINVAL;
+                       else
+                       {
+                               POID_ADD_BA_ENTRY       pBA;
+                               MAC_TABLE_ENTRY *pEntry;
+
+                               pBA = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+
+                               if (pBA == NULL)
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA kmalloc() can't allocate enough memory\n"));
+                                       Status = NDIS_STATUS_FAILURE;
+                               }
+                               else
+                               {
+                                       Status = copy_from_user(pBA, wrq->u.data.pointer, wrq->u.data.length);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA(TID=%d, bAllTid=%d)\n", pBA->TID, pBA->bAllTid));
+
+                                       if (!pBA->bAllTid && (pBA->TID > NUM_OF_TID))
+                                       {
+                                               Status = NDIS_STATUS_INVALID_DATA;
+                                               break;
+                                       }
+
+                                       if (pBA->IsRecipient == FALSE)
+                                       {
+                                               pEntry = MacTableLookup(pAdapter, pBA->MACAddr);
+                                               DBGPRINT(RT_DEBUG_TRACE, (" pBA->IsRecipient == FALSE\n"));
+                                               if (pEntry)
+                                               {
+                                                       DBGPRINT(RT_DEBUG_TRACE, (" pBA->pEntry\n"));
+                                                       BAOriSessionTearDown(pAdapter, pEntry->Aid, pBA->TID, FALSE, TRUE);
+                                               }
+                                               else
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n"));
+                                       }
+                                       else
+                                       {
+                                               pEntry = MacTableLookup(pAdapter, pBA->MACAddr);
+                                               if (pEntry)
+                                               {
+                                                       BARecSessionTearDown( pAdapter, (UCHAR)pEntry->Aid, pBA->TID, TRUE);
+                                               }
+                                               else
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n"));
+                                       }
+                                       kfree(pBA);
+                               }
+            }
+            break;
+#endif // DOT11_N_SUPPORT //
+
+        // For WPA_SUPPLICANT to set static wep key
+       case OID_802_11_ADD_WEP:
+           pWepKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+
+           if(pWepKey == NULL)
+            {
+                Status = -ENOMEM;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed!!\n"));
+                break;
+            }
+            Status = copy_from_user(pWepKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (Status)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (length mismatch)!!\n"));
+            }
+            else
+            {
+                       KeyIdx = pWepKey->KeyIndex & 0x0fffffff;
+                // KeyIdx must be 0 ~ 3
+                if (KeyIdx > 4)
+                       {
+                    Status  = -EINVAL;
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (KeyIdx must be smaller than 4)!!\n"));
+                }
+                else
+                {
+                    UCHAR CipherAlg = 0;
+                    PUCHAR Key;
+
+                    // set key material and key length
+                    NdisZeroMemory(pAdapter->SharedKey[BSS0][KeyIdx].Key, 16);
+                    pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength;
+                    NdisMoveMemory(pAdapter->SharedKey[BSS0][KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength);
+
+                    switch(pWepKey->KeyLength)
+                    {
+                        case 5:
+                            CipherAlg = CIPHER_WEP64;
+                            break;
+                        case 13:
+                            CipherAlg = CIPHER_WEP128;
+                            break;
+                        default:
+                            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, only support CIPHER_WEP64(len:5) & CIPHER_WEP128(len:13)!!\n"));
+                            Status = -EINVAL;
+                            break;
+                    }
+                    pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CipherAlg;
+
+                    // Default key for tx (shared key)
+                    if (pWepKey->KeyIndex & 0x80000000)
+                    {
+#ifdef WPA_SUPPLICANT_SUPPORT
+                        // set key material and key length
+                        NdisZeroMemory(pAdapter->StaCfg.DesireSharedKey[KeyIdx].Key, 16);
+                        pAdapter->StaCfg.DesireSharedKey[KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength;
+                        NdisMoveMemory(pAdapter->StaCfg.DesireSharedKey[KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength);
+                        pAdapter->StaCfg.DesireSharedKeyId = KeyIdx;
+                        pAdapter->StaCfg.DesireSharedKey[KeyIdx].CipherAlg = CipherAlg;
+#endif // WPA_SUPPLICANT_SUPPORT //
+                        pAdapter->StaCfg.DefaultKeyId = (UCHAR) KeyIdx;
+                    }
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+                    if (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)
+#endif // WPA_SUPPLICANT_SUPPORT
+                    {
+                        Key = pAdapter->SharedKey[BSS0][KeyIdx].Key;
+
+                        // Set key material and cipherAlg to Asic
+                                       AsicAddSharedKeyEntry(pAdapter, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL);
+
+                        if (pWepKey->KeyIndex & 0x80000000)
+                        {
+                            PMAC_TABLE_ENTRY pEntry = &pAdapter->MacTab.Content[BSSID_WCID];
+                            // Assign group key info
+                                               RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, NULL);
+                                               // Assign pairwise key info
+                                               RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, pEntry);
+                        }
+                    }
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP (id=0x%x, Len=%d-byte), %s\n", pWepKey->KeyIndex, pWepKey->KeyLength, (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) ? "Port Secured":"Port NOT Secured"));
+                               }
+            }
+            kfree(pWepKey);
+            break;
+#ifdef WPA_SUPPLICANT_SUPPORT
+           case OID_SET_COUNTERMEASURES:
+            if (wrq->u.data.length != sizeof(int))
+                Status  = -EINVAL;
+            else
+            {
+                int enabled = 0;
+                Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length);
+                if (enabled == 1)
+                    pAdapter->StaCfg.bBlockAssoc = TRUE;
+                else
+                    // WPA MIC error should block association attempt for 60 seconds
+                    pAdapter->StaCfg.bBlockAssoc = FALSE;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_SET_COUNTERMEASURES bBlockAssoc=%s\n", pAdapter->StaCfg.bBlockAssoc ? "TRUE":"FALSE"));
+            }
+               break;
+        case RT_OID_WPA_SUPPLICANT_SUPPORT:
+                       if (wrq->u.data.length != sizeof(UCHAR))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&wpa_supplicant_enable, wrq->u.data.pointer, wrq->u.data.length);
+                       pAdapter->StaCfg.WpaSupplicantUP = wpa_supplicant_enable;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAdapter->StaCfg.WpaSupplicantUP));
+                       }
+            break;
+        case OID_802_11_DEAUTHENTICATION:
+            if (wrq->u.data.length != sizeof(MLME_DEAUTH_REQ_STRUCT))
+                Status  = -EINVAL;
+            else
+            {
+                MLME_DEAUTH_REQ_STRUCT      *pInfo;
+                               MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+
+                pInfo = (MLME_DEAUTH_REQ_STRUCT *) MsgElem->Msg;
+                Status = copy_from_user(pInfo, wrq->u.data.pointer, wrq->u.data.length);
+                MlmeDeauthReqAction(pAdapter, MsgElem);
+                               kfree(MsgElem);
+
+                if (INFRA_ON(pAdapter))
+                {
+                    LinkDown(pAdapter, FALSE);
+                    pAdapter->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION (Reason=%d)\n", pInfo->Reason));
+            }
+            break;
+        case OID_802_11_DROP_UNENCRYPTED:
+            if (wrq->u.data.length != sizeof(int))
+                Status  = -EINVAL;
+            else
+            {
+                int enabled = 0;
+                Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length);
+                if (enabled == 1)
+                    pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                else
+                    pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               NdisAcquireSpinLock(&pAdapter->MacTabLock);
+                               pAdapter->MacTab.Content[BSSID_WCID].PortSecured = pAdapter->StaCfg.PortSecured;
+                               NdisReleaseSpinLock(&pAdapter->MacTabLock);
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DROP_UNENCRYPTED (=%d)\n", enabled));
+            }
+            break;
+        case OID_802_11_SET_IEEE8021X:
+            if (wrq->u.data.length != sizeof(BOOLEAN))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&IEEE8021xState, wrq->u.data.pointer, wrq->u.data.length);
+                       pAdapter->StaCfg.IEEE8021X = IEEE8021xState;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X (=%d)\n", IEEE8021xState));
+            }
+            break;
+        case OID_802_11_SET_IEEE8021X_REQUIRE_KEY:
+                       if (wrq->u.data.length != sizeof(BOOLEAN))
+                                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&IEEE8021x_required_keys, wrq->u.data.pointer, wrq->u.data.length);
+                               pAdapter->StaCfg.IEEE8021x_required_keys = IEEE8021x_required_keys;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X_REQUIRE_KEY (%d)\n", IEEE8021x_required_keys));
+                       }
+                       break;
+        case OID_802_11_PMKID:
+               pPmkId = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+
+               if(pPmkId == NULL) {
+                Status = -ENOMEM;
+                break;
+            }
+            Status = copy_from_user(pPmkId, wrq->u.data.pointer, wrq->u.data.length);
+
+               // check the PMKID information
+               if (pPmkId->BSSIDInfoCount == 0)
+                NdisZeroMemory(pAdapter->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO);
+               else
+               {
+                       PBSSID_INFO     pBssIdInfo;
+                       UINT            BssIdx;
+                       UINT            CachedIdx;
+
+                       for (BssIdx = 0; BssIdx < pPmkId->BSSIDInfoCount; BssIdx++)
+                       {
+                               // point to the indexed BSSID_INFO structure
+                               pBssIdInfo = (PBSSID_INFO) ((PUCHAR) pPmkId + 2 * sizeof(UINT) + BssIdx * sizeof(BSSID_INFO));
+                               // Find the entry in the saved data base.
+                               for (CachedIdx = 0; CachedIdx < pAdapter->StaCfg.SavedPMKNum; CachedIdx++)
+                               {
+                                       // compare the BSSID
+                                       if (NdisEqualMemory(pBssIdInfo->BSSID, pAdapter->StaCfg.SavedPMK[CachedIdx].BSSID, sizeof(NDIS_802_11_MAC_ADDRESS)))
+                                               break;
+                               }
+
+                               // Found, replace it
+                               if (CachedIdx < PMKID_NO)
+                               {
+                                       DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx));
+                                       NdisMoveMemory(&pAdapter->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO));
+                                       pAdapter->StaCfg.SavedPMKNum++;
+                               }
+                               // Not found, replace the last one
+                               else
+                               {
+                                       // Randomly replace one
+                                       CachedIdx = (pBssIdInfo->BSSID[5] % PMKID_NO);
+                                       DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx));
+                                       NdisMoveMemory(&pAdapter->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO));
+                               }
+                       }
+                       }
+                       if(pPmkId)
+                               kfree(pPmkId);
+               break;
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+
+
+#ifdef SNMP_SUPPORT
+               case OID_802_11_SHORTRETRYLIMIT:
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&ShortRetryLimit, wrq->u.data.pointer, wrq->u.data.length);
+                               RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                               tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit;
+                               RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SHORTRETRYLIMIT (tx_rty_cfg.field.ShortRetryLimit=%d, ShortRetryLimit=%ld)\n", tx_rty_cfg.field.ShortRtyLimit, ShortRetryLimit));
+                       }
+                       break;
+
+               case OID_802_11_LONGRETRYLIMIT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT \n"));
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&LongRetryLimit, wrq->u.data.pointer, wrq->u.data.length);
+                               RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                               tx_rty_cfg.field.LongRtyLimit = LongRetryLimit;
+                               RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT (tx_rty_cfg.field.LongRetryLimit= %d,LongRetryLimit=%ld)\n", tx_rty_cfg.field.LongRtyLimit, LongRetryLimit));
+                       }
+                       break;
+
+               case OID_802_11_WEPDEFAULTKEYVALUE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE\n"));
+                       pKey = kmalloc(wrq->u.data.length, GFP_KERNEL);
+                       Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length);
+                       //pKey = &WepKey;
+
+                       if ( pKey->Length != wrq->u.data.length)
+                       {
+                               Status = -EINVAL;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE, Failed!!\n"));
+                       }
+                       KeyIdx = pKey->KeyIndex & 0x0fffffff;
+                       DBGPRINT(RT_DEBUG_TRACE,("pKey->KeyIndex =%d, pKey->KeyLength=%d\n", pKey->KeyIndex, pKey->KeyLength));
+
+                       // it is a shared key
+                       if (KeyIdx > 4)
+                               Status = -EINVAL;
+                       else
+                       {
+                               pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen = (UCHAR) pKey->KeyLength;
+                               NdisMoveMemory(&pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, &pKey->KeyMaterial, pKey->KeyLength);
+                               if (pKey->KeyIndex & 0x80000000)
+                               {
+                                       // Default key for tx (shared key)
+                                       pAdapter->StaCfg.DefaultKeyId = (UCHAR) KeyIdx;
+                               }
+                               //RestartAPIsRequired = TRUE;
+                       }
+                       break;
+
+
+               case OID_802_11_WEPDEFAULTKEYID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYID \n"));
+
+                       if (wrq->u.data.length != sizeof(UCHAR))
+                               Status = -EINVAL;
+                       else
+                               Status = copy_from_user(&pAdapter->StaCfg.DefaultKeyId, wrq->u.data.pointer, wrq->u.data.length);
+
+                       break;
+
+
+               case OID_802_11_CURRENTCHANNEL:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CURRENTCHANNEL \n"));
+                       if (wrq->u.data.length != sizeof(UCHAR))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&ctmp, wrq->u.data.pointer, wrq->u.data.length);
+                               sprintf(&ctmp,"%d", ctmp);
+                               Set_Channel_Proc(pAdapter, &ctmp);
+                       }
+                       break;
+#endif
+
+
+
+        default:
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd));
+            Status = -EOPNOTSUPP;
+            break;
+    }
+
+
+    return Status;
+}
+
+INT RTMPQueryInformation(
+    IN  PRTMP_ADAPTER pAdapter,
+    IN  OUT struct ifreq    *rq,
+    IN  INT                 cmd)
+{
+    struct iwreq                        *wrq = (struct iwreq *) rq;
+    NDIS_802_11_BSSID_LIST_EX           *pBssidList = NULL;
+    PNDIS_WLAN_BSSID_EX                 pBss;
+    NDIS_802_11_SSID                    Ssid;
+    NDIS_802_11_CONFIGURATION           *pConfiguration = NULL;
+    RT_802_11_LINK_STATUS               *pLinkStatus = NULL;
+    RT_802_11_STA_CONFIG                *pStaConfig = NULL;
+    NDIS_802_11_STATISTICS              *pStatistics = NULL;
+    NDIS_802_11_RTS_THRESHOLD           RtsThresh;
+    NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh;
+    NDIS_802_11_POWER_MODE              PowerMode;
+    NDIS_802_11_NETWORK_INFRASTRUCTURE  BssType;
+    RT_802_11_PREAMBLE                  PreamType;
+    NDIS_802_11_AUTHENTICATION_MODE     AuthMode;
+    NDIS_802_11_WEP_STATUS              WepStatus;
+    NDIS_MEDIA_STATE                    MediaState;
+    ULONG                               BssBufSize, ulInfo=0, NetworkTypeList[4], apsd = 0;
+    USHORT                              BssLen = 0;
+    PUCHAR                              pBuf = NULL, pPtr;
+    INT                                 Status = NDIS_STATUS_SUCCESS;
+    UINT                                we_version_compiled;
+    UCHAR                               i, Padding = 0;
+    BOOLEAN                             RadioState;
+       UCHAR   driverVersion[8];
+    OID_SET_HT_PHYMODE                         *pHTPhyMode = NULL;
+
+
+#ifdef SNMP_SUPPORT
+       //for snmp, kathy
+       DefaultKeyIdxValue                      *pKeyIdxValue;
+       INT                                                     valueLen;
+       TX_RTY_CFG_STRUC                        tx_rty_cfg;
+       ULONG                                           ShortRetryLimit, LongRetryLimit;
+       UCHAR                                           tmp[64];
+#endif //SNMP
+
+    switch(cmd)
+    {
+        case RT_OID_DEVICE_NAME:
+            wrq->u.data.length = sizeof(STA_NIC_DEVICE_NAME);
+            Status = copy_to_user(wrq->u.data.pointer, STA_NIC_DEVICE_NAME, wrq->u.data.length);
+            break;
+        case RT_OID_VERSION_INFO:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_VERSION_INFO \n"));
+                       wrq->u.data.length = 8*sizeof(UCHAR);
+                       sprintf(&driverVersion[0], "%s", STA_DRIVER_VERSION);
+                       driverVersion[7] = '\0';
+                       if (copy_to_user(wrq->u.data.pointer, &driverVersion, wrq->u.data.length))
+            {
+                               Status = -EFAULT;
+            }
+            break;
+#ifdef RALINK_ATE
+               case RT_QUERY_ATE_TXDONE_COUNT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_QUERY_ATE_TXDONE_COUNT \n"));
+                       wrq->u.data.length = sizeof(UINT32);
+                       if (copy_to_user(wrq->u.data.pointer, &pAdapter->ate.TxDoneCount, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+                       break;
+#endif // RALINK_ATE //
+        case OID_802_11_BSSID_LIST:
+            if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+            {
+               /*
+                * Still scanning, indicate the caller should try again.
+                */
+               DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (Still scanning)\n"));
+                               return -EAGAIN;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (%d BSS returned)\n",pAdapter->ScanTab.BssNr));
+                       pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE;
+            // Claculate total buffer size required
+            BssBufSize = sizeof(ULONG);
+
+            for (i = 0; i < pAdapter->ScanTab.BssNr; i++)
+            {
+                // Align pointer to 4 bytes boundary.
+                //Padding = 4 - (pAdapter->ScanTab.BssEntry[i].VarIELen & 0x0003);
+                //if (Padding == 4)
+                //    Padding = 0;
+                BssBufSize += (sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen + Padding);
+            }
+
+            // For safety issue, we add 256 bytes just in case
+            BssBufSize += 256;
+            // Allocate the same size as passed from higher layer
+            pBuf = kmalloc(BssBufSize, MEM_ALLOC_FLAG);
+            if(pBuf == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+            // Init 802_11_BSSID_LIST_EX structure
+            NdisZeroMemory(pBuf, BssBufSize);
+            pBssidList = (PNDIS_802_11_BSSID_LIST_EX) pBuf;
+            pBssidList->NumberOfItems = pAdapter->ScanTab.BssNr;
+
+            // Calculate total buffer length
+            BssLen = 4; // Consist of NumberOfItems
+            // Point to start of NDIS_WLAN_BSSID_EX
+            // pPtr = pBuf + sizeof(ULONG);
+            pPtr = (PUCHAR) &pBssidList->Bssid[0];
+            for (i = 0; i < pAdapter->ScanTab.BssNr; i++)
+            {
+                pBss = (PNDIS_WLAN_BSSID_EX) pPtr;
+                NdisMoveMemory(&pBss->MacAddress, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN);
+                if ((pAdapter->ScanTab.BssEntry[i].Hidden == 1) && (pAdapter->StaCfg.bShowHiddenSSID == FALSE))
+                {
+                    //
+                                       // We must return this SSID during 4way handshaking, otherwise Aegis will failed to parse WPA infomation
+                                       // and then failed to send EAPOl farame.
+                                       //
+                                       if ((pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAdapter->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED))
+                                       {
+                                               pBss->Ssid.SsidLength = pAdapter->ScanTab.BssEntry[i].SsidLen;
+                                               NdisMoveMemory(pBss->Ssid.Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen);
+                                       }
+                                       else
+                       pBss->Ssid.SsidLength = 0;
+                }
+                else
+                {
+                    pBss->Ssid.SsidLength = pAdapter->ScanTab.BssEntry[i].SsidLen;
+                    NdisMoveMemory(pBss->Ssid.Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen);
+                }
+                pBss->Privacy = pAdapter->ScanTab.BssEntry[i].Privacy;
+                pBss->Rssi = pAdapter->ScanTab.BssEntry[i].Rssi - pAdapter->BbpRssiToDbmDelta;
+                pBss->NetworkTypeInUse = NetworkTypeInUseSanity(&pAdapter->ScanTab.BssEntry[i]);
+                pBss->Configuration.Length = sizeof(NDIS_802_11_CONFIGURATION);
+                pBss->Configuration.BeaconPeriod = pAdapter->ScanTab.BssEntry[i].BeaconPeriod;
+                pBss->Configuration.ATIMWindow = pAdapter->ScanTab.BssEntry[i].AtimWin;
+
+                MAP_CHANNEL_ID_TO_KHZ(pAdapter->ScanTab.BssEntry[i].Channel, pBss->Configuration.DSConfig);
+
+                if (pAdapter->ScanTab.BssEntry[i].BssType == BSS_INFRA)
+                    pBss->InfrastructureMode = Ndis802_11Infrastructure;
+                else
+                    pBss->InfrastructureMode = Ndis802_11IBSS;
+
+                NdisMoveMemory(pBss->SupportedRates, pAdapter->ScanTab.BssEntry[i].SupRate, pAdapter->ScanTab.BssEntry[i].SupRateLen);
+                NdisMoveMemory(pBss->SupportedRates + pAdapter->ScanTab.BssEntry[i].SupRateLen,
+                               pAdapter->ScanTab.BssEntry[i].ExtRate,
+                               pAdapter->ScanTab.BssEntry[i].ExtRateLen);
+
+                if (pAdapter->ScanTab.BssEntry[i].VarIELen == 0)
+                {
+                    pBss->IELength = sizeof(NDIS_802_11_FIXED_IEs);
+                    NdisMoveMemory(pBss->IEs, &pAdapter->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs));
+                    pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs);
+                }
+                else
+                {
+                    pBss->IELength = (ULONG)(sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen);
+                    pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs);
+                    NdisMoveMemory(pBss->IEs, &pAdapter->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs));
+                    NdisMoveMemory(pBss->IEs + sizeof(NDIS_802_11_FIXED_IEs), pAdapter->ScanTab.BssEntry[i].VarIEs, pAdapter->ScanTab.BssEntry[i].VarIELen);
+                    pPtr += pAdapter->ScanTab.BssEntry[i].VarIELen;
+                }
+                pBss->Length = (ULONG)(sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen + Padding);
+
+#if WIRELESS_EXT < 17
+                if ((BssLen + pBss->Length) < wrq->u.data.length)
+                BssLen += pBss->Length;
+                else
+                {
+                    pBssidList->NumberOfItems = i;
+                    break;
+                }
+#else
+                BssLen += pBss->Length;
+#endif
+            }
+
+#if WIRELESS_EXT < 17
+            wrq->u.data.length = BssLen;
+#else
+            if (BssLen > wrq->u.data.length)
+            {
+                kfree(pBssidList);
+                return -E2BIG;
+            }
+            else
+                wrq->u.data.length = BssLen;
+#endif
+            Status = copy_to_user(wrq->u.data.pointer, pBssidList, BssLen);
+            kfree(pBssidList);
+            break;
+        case OID_802_3_CURRENT_ADDRESS:
+            wrq->u.data.length = MAC_ADDR_LEN;
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length);
+            break;
+        case OID_GEN_MEDIA_CONNECT_STATUS:
+            if (pAdapter->IndicateMediaState == NdisMediaStateConnected)
+                MediaState = NdisMediaStateConnected;
+            else
+                MediaState = NdisMediaStateDisconnected;
+
+            wrq->u.data.length = sizeof(NDIS_MEDIA_STATE);
+            Status = copy_to_user(wrq->u.data.pointer, &MediaState, wrq->u.data.length);
+            break;
+        case OID_802_11_BSSID:
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               Status = NDIS_STATUS_RESOURCES;
+                               break;
+                       }
+#endif // RALINK_ATE //
+            if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
+            {
+                Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Bssid, sizeof(NDIS_802_11_MAC_ADDRESS));
+
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID(=EMPTY)\n"));
+                Status = -ENOTCONN;
+            }
+            break;
+        case OID_802_11_SSID:
+                       NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID));
+                       NdisZeroMemory(Ssid.Ssid, MAX_LEN_OF_SSID);
+            Ssid.SsidLength = pAdapter->CommonCfg.SsidLen;
+                       memcpy(Ssid.Ssid, pAdapter->CommonCfg.Ssid,     Ssid.SsidLength);
+            wrq->u.data.length = sizeof(NDIS_802_11_SSID);
+            Status = copy_to_user(wrq->u.data.pointer, &Ssid, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SSID (Len=%d, ssid=%s)\n", Ssid.SsidLength,Ssid.Ssid));
+            break;
+        case RT_OID_802_11_QUERY_LINK_STATUS:
+            pLinkStatus = (RT_802_11_LINK_STATUS *) kmalloc(sizeof(RT_802_11_LINK_STATUS), MEM_ALLOC_FLAG);
+            if (pLinkStatus)
+            {
+                pLinkStatus->CurrTxRate = RateIdTo500Kbps[pAdapter->CommonCfg.TxRate];   // unit : 500 kbps
+                pLinkStatus->ChannelQuality = pAdapter->Mlme.ChannelQuality;
+                pLinkStatus->RxByteCount = pAdapter->RalinkCounters.ReceivedByteCount;
+                pLinkStatus->TxByteCount = pAdapter->RalinkCounters.TransmittedByteCount;
+                       pLinkStatus->CentralChannel = pAdapter->CommonCfg.CentralChannel;
+                wrq->u.data.length = sizeof(RT_802_11_LINK_STATUS);
+                Status = copy_to_user(wrq->u.data.pointer, pLinkStatus, wrq->u.data.length);
+                kfree(pLinkStatus);
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS\n"));
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case OID_802_11_CONFIGURATION:
+            pConfiguration = (NDIS_802_11_CONFIGURATION *) kmalloc(sizeof(NDIS_802_11_CONFIGURATION), MEM_ALLOC_FLAG);
+            if (pConfiguration)
+            {
+                pConfiguration->Length = sizeof(NDIS_802_11_CONFIGURATION);
+                pConfiguration->BeaconPeriod = pAdapter->CommonCfg.BeaconPeriod;
+                pConfiguration->ATIMWindow = pAdapter->StaActive.AtimWin;
+                MAP_CHANNEL_ID_TO_KHZ(pAdapter->CommonCfg.Channel, pConfiguration->DSConfig);
+                wrq->u.data.length = sizeof(NDIS_802_11_CONFIGURATION);
+                Status = copy_to_user(wrq->u.data.pointer, pConfiguration, wrq->u.data.length);
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(BeaconPeriod=%ld,AtimW=%ld,Channel=%d) \n",
+                                        pConfiguration->BeaconPeriod, pConfiguration->ATIMWindow, pAdapter->CommonCfg.Channel));
+                               kfree(pConfiguration);
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+               case RT_OID_802_11_SNR_0:
+                       if ((pAdapter->StaCfg.LastSNR0 > 0))
+                       {
+                               ulInfo = ((0xeb - pAdapter->StaCfg.LastSNR0) * 3) /     16 ;
+                               wrq->u.data.length = sizeof(ulInfo);
+                               Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_SNR_0(0x=%lx)\n", ulInfo));
+                       }
+            else
+                           Status = -EFAULT;
+                       break;
+               case RT_OID_802_11_SNR_1:
+                       if ((pAdapter->Antenna.field.RxPath     > 1) &&
+                (pAdapter->StaCfg.LastSNR1 > 0))
+                       {
+                               ulInfo = ((0xeb - pAdapter->StaCfg.LastSNR1) * 3) /     16 ;
+                               wrq->u.data.length = sizeof(ulInfo);
+                               Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(0x=%lx)\n",ulInfo));
+                       }
+                       else
+                               Status = -EFAULT;
+            DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(pAdapter->StaCfg.LastSNR1=%d)\n",pAdapter->StaCfg.LastSNR1));
+                       break;
+        case OID_802_11_RSSI_TRIGGER:
+            ulInfo = pAdapter->StaCfg.RssiSample.LastRssi0 - pAdapter->BbpRssiToDbmDelta;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RSSI_TRIGGER(=%ld)\n", ulInfo));
+            break;
+               case OID_802_11_RSSI:
+        case RT_OID_802_11_RSSI:
+                       ulInfo = pAdapter->StaCfg.RssiSample.LastRssi0;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       break;
+               case RT_OID_802_11_RSSI_1:
+            ulInfo = pAdapter->StaCfg.RssiSample.LastRssi1;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       break;
+        case RT_OID_802_11_RSSI_2:
+            ulInfo = pAdapter->StaCfg.RssiSample.LastRssi2;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       break;
+        case OID_802_11_STATISTICS:
+            pStatistics = (NDIS_802_11_STATISTICS *) kmalloc(sizeof(NDIS_802_11_STATISTICS), MEM_ALLOC_FLAG);
+            if (pStatistics)
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS \n"));
+                // add the most up-to-date h/w raw counters into software counters
+                           NICUpdateRawCounters(pAdapter);
+
+                // Sanity check for calculation of sucessful count
+                if (pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart < pAdapter->WlanCounters.RetryCount.QuadPart)
+                    pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart;
+
+                pStatistics->TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart;
+                pStatistics->MulticastTransmittedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastTransmittedFrameCount.QuadPart;
+                pStatistics->FailedCount.QuadPart = pAdapter->WlanCounters.FailedCount.QuadPart;
+                pStatistics->RetryCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart;
+                pStatistics->MultipleRetryCount.QuadPart = pAdapter->WlanCounters.MultipleRetryCount.QuadPart;
+                pStatistics->RTSSuccessCount.QuadPart = pAdapter->WlanCounters.RTSSuccessCount.QuadPart;
+                pStatistics->RTSFailureCount.QuadPart = pAdapter->WlanCounters.RTSFailureCount.QuadPart;
+                pStatistics->ACKFailureCount.QuadPart = pAdapter->WlanCounters.ACKFailureCount.QuadPart;
+                pStatistics->FrameDuplicateCount.QuadPart = pAdapter->WlanCounters.FrameDuplicateCount.QuadPart;
+                pStatistics->ReceivedFragmentCount.QuadPart = pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart;
+                pStatistics->MulticastReceivedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastReceivedFrameCount.QuadPart;
+#ifdef DBG
+                pStatistics->FCSErrorCount = pAdapter->RalinkCounters.RealFcsErrCount;
+#else
+                pStatistics->FCSErrorCount.QuadPart = pAdapter->WlanCounters.FCSErrorCount.QuadPart;
+                pStatistics->FrameDuplicateCount.u.LowPart = pAdapter->WlanCounters.FrameDuplicateCount.u.LowPart / 100;
+#endif
+                wrq->u.data.length = sizeof(NDIS_802_11_STATISTICS);
+                Status = copy_to_user(wrq->u.data.pointer, pStatistics, wrq->u.data.length);
+                kfree(pStatistics);
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case OID_GEN_RCV_OK:
+            ulInfo = pAdapter->Counters8023.GoodReceives;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            break;
+        case OID_GEN_RCV_NO_BUFFER:
+            ulInfo = pAdapter->Counters8023.RxNoBuffer;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            break;
+        case RT_OID_802_11_PHY_MODE:
+            ulInfo = (ULONG)pAdapter->CommonCfg.PhyMode;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PHY_MODE (=%ld)\n", ulInfo));
+            break;
+        case RT_OID_802_11_STA_CONFIG:
+            pStaConfig = (RT_802_11_STA_CONFIG *) kmalloc(sizeof(RT_802_11_STA_CONFIG), MEM_ALLOC_FLAG);
+            if (pStaConfig)
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG\n"));
+                pStaConfig->EnableTxBurst = pAdapter->CommonCfg.bEnableTxBurst;
+                pStaConfig->EnableTurboRate = 0;
+                pStaConfig->UseBGProtection = pAdapter->CommonCfg.UseBGProtection;
+                pStaConfig->UseShortSlotTime = pAdapter->CommonCfg.bUseShortSlotTime;
+                //pStaConfig->AdhocMode = pAdapter->StaCfg.AdhocMode;
+                pStaConfig->HwRadioStatus = (pAdapter->StaCfg.bHwRadio == TRUE) ? 1 : 0;
+                pStaConfig->Rsv1 = 0;
+                pStaConfig->SystemErrorBitmap = pAdapter->SystemErrorBitmap;
+                wrq->u.data.length = sizeof(RT_802_11_STA_CONFIG);
+                Status = copy_to_user(wrq->u.data.pointer, pStaConfig, wrq->u.data.length);
+                kfree(pStaConfig);
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case OID_802_11_RTS_THRESHOLD:
+            RtsThresh = pAdapter->CommonCfg.RtsThreshold;
+            wrq->u.data.length = sizeof(RtsThresh);
+            Status = copy_to_user(wrq->u.data.pointer, &RtsThresh, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RTS_THRESHOLD(=%ld)\n", RtsThresh));
+            break;
+        case OID_802_11_FRAGMENTATION_THRESHOLD:
+            FragThresh = pAdapter->CommonCfg.FragmentThreshold;
+            if (pAdapter->CommonCfg.bUseZeroToDisableFragment == TRUE)
+                FragThresh = 0;
+            wrq->u.data.length = sizeof(FragThresh);
+            Status = copy_to_user(wrq->u.data.pointer, &FragThresh, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_FRAGMENTATION_THRESHOLD(=%ld)\n", FragThresh));
+            break;
+        case OID_802_11_POWER_MODE:
+            PowerMode = pAdapter->StaCfg.WindowsPowerMode;
+            wrq->u.data.length = sizeof(PowerMode);
+            Status = copy_to_user(wrq->u.data.pointer, &PowerMode, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_POWER_MODE(=%d)\n", PowerMode));
+            break;
+        case RT_OID_802_11_RADIO:
+            RadioState = (BOOLEAN) pAdapter->StaCfg.bSwRadio;
+            wrq->u.data.length = sizeof(RadioState);
+            Status = copy_to_user(wrq->u.data.pointer, &RadioState, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_RADIO (=%d)\n", RadioState));
+            break;
+        case OID_802_11_INFRASTRUCTURE_MODE:
+            if (pAdapter->StaCfg.BssType == BSS_ADHOC)
+                BssType = Ndis802_11IBSS;
+            else if (pAdapter->StaCfg.BssType == BSS_INFRA)
+                BssType = Ndis802_11Infrastructure;
+            else if (pAdapter->StaCfg.BssType == BSS_MONITOR)
+                BssType = Ndis802_11Monitor;
+            else
+                BssType = Ndis802_11AutoUnknown;
+
+            wrq->u.data.length = sizeof(BssType);
+            Status = copy_to_user(wrq->u.data.pointer, &BssType, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_INFRASTRUCTURE_MODE(=%d)\n", BssType));
+            break;
+        case RT_OID_802_11_PREAMBLE:
+            PreamType = pAdapter->CommonCfg.TxPreamble;
+            wrq->u.data.length = sizeof(PreamType);
+            Status = copy_to_user(wrq->u.data.pointer, &PreamType, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PREAMBLE(=%d)\n", PreamType));
+            break;
+        case OID_802_11_AUTHENTICATION_MODE:
+            AuthMode = pAdapter->StaCfg.AuthMode;
+            wrq->u.data.length = sizeof(AuthMode);
+            Status = copy_to_user(wrq->u.data.pointer, &AuthMode, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_AUTHENTICATION_MODE(=%d)\n", AuthMode));
+            break;
+        case OID_802_11_WEP_STATUS:
+            WepStatus = pAdapter->StaCfg.WepStatus;
+            wrq->u.data.length = sizeof(WepStatus);
+            Status = copy_to_user(wrq->u.data.pointer, &WepStatus, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEP_STATUS(=%d)\n", WepStatus));
+            break;
+        case OID_802_11_TX_POWER_LEVEL:
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.TxPower, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_TX_POWER_LEVEL %x\n",pAdapter->CommonCfg.TxPower));
+                       break;
+        case RT_OID_802_11_TX_POWER_LEVEL_1:
+            wrq->u.data.length = sizeof(ULONG);
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.TxPowerPercentage, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAdapter->CommonCfg.TxPowerPercentage));
+                       break;
+        case OID_802_11_NETWORK_TYPES_SUPPORTED:
+                       if ((pAdapter->RfIcType == RFIC_2850) || (pAdapter->RfIcType == RFIC_2750))
+                       {
+                               NetworkTypeList[0] = 3;                 // NumberOfItems = 3
+                               NetworkTypeList[1] = Ndis802_11DS;      // NetworkType[1] = 11b
+                               NetworkTypeList[2] = Ndis802_11OFDM24;  // NetworkType[2] = 11g
+                               NetworkTypeList[3] = Ndis802_11OFDM5;   // NetworkType[3] = 11a
+                wrq->u.data.length = 16;
+                               Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length);
+                       }
+                       else
+                       {
+                               NetworkTypeList[0] = 2;                 // NumberOfItems = 2
+                               NetworkTypeList[1] = Ndis802_11DS;      // NetworkType[1] = 11b
+                               NetworkTypeList[2] = Ndis802_11OFDM24;  // NetworkType[2] = 11g
+                           wrq->u.data.length = 12;
+                               Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length);
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_NETWORK_TYPES_SUPPORTED\n"));
+                               break;
+           case OID_802_11_NETWORK_TYPE_IN_USE:
+            wrq->u.data.length = sizeof(ULONG);
+                       if (pAdapter->CommonCfg.PhyMode == PHY_11A)
+                               ulInfo = Ndis802_11OFDM5;
+                       else if ((pAdapter->CommonCfg.PhyMode == PHY_11BG_MIXED) || (pAdapter->CommonCfg.PhyMode == PHY_11G))
+                               ulInfo = Ndis802_11OFDM24;
+                       else
+                               ulInfo = Ndis802_11DS;
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       break;
+        case RT_OID_802_11_QUERY_LAST_RX_RATE:
+            ulInfo = (ULONG)pAdapter->LastRxRate;
+            wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_RX_RATE (=%ld)\n", ulInfo));
+                       break;
+               case RT_OID_802_11_QUERY_LAST_TX_RATE:
+                       //ulInfo = (ULONG)pAdapter->LastTxRate;
+                       ulInfo = (ULONG)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_TX_RATE (=%lx)\n", ulInfo));
+                       break;
+        case RT_OID_802_11_QUERY_EEPROM_VERSION:
+            wrq->u.data.length = sizeof(ULONG);
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->EepromVersion, wrq->u.data.length);
+            break;
+        case RT_OID_802_11_QUERY_FIRMWARE_VERSION:
+            wrq->u.data.length = sizeof(ULONG);
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->FirmwareVersion, wrq->u.data.length);
+                       break;
+           case RT_OID_802_11_QUERY_NOISE_LEVEL:
+                       wrq->u.data.length = sizeof(UCHAR);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->BbpWriteLatch[66], wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_NOISE_LEVEL (=%d)\n", pAdapter->BbpWriteLatch[66]));
+                       break;
+           case RT_OID_802_11_EXTRA_INFO:
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->ExtraInfo, wrq->u.data.length);
+               DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_EXTRA_INFO (=%ld)\n", pAdapter->ExtraInfo));
+               break;
+           case RT_OID_WE_VERSION_COMPILED:
+               wrq->u.data.length = sizeof(UINT);
+               we_version_compiled = WIRELESS_EXT;
+               Status = copy_to_user(wrq->u.data.pointer, &we_version_compiled, wrq->u.data.length);
+               break;
+               case RT_OID_802_11_QUERY_APSD_SETTING:
+                       apsd = (pAdapter->CommonCfg.bAPSDCapable | (pAdapter->CommonCfg.bAPSDAC_BE << 1) | (pAdapter->CommonCfg.bAPSDAC_BK << 2)
+                               | (pAdapter->CommonCfg.bAPSDAC_VI << 3) | (pAdapter->CommonCfg.bAPSDAC_VO << 4) | (pAdapter->CommonCfg.MaxSPLength << 5));
+
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &apsd, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_SETTING (=0x%lx,APSDCap=%d,AC_BE=%d,AC_BK=%d,AC_VI=%d,AC_VO=%d,MAXSPLen=%d)\n",
+                               apsd,pAdapter->CommonCfg.bAPSDCapable,pAdapter->CommonCfg.bAPSDAC_BE,pAdapter->CommonCfg.bAPSDAC_BK,pAdapter->CommonCfg.bAPSDAC_VI,pAdapter->CommonCfg.bAPSDAC_VO,pAdapter->CommonCfg.MaxSPLength));
+                       break;
+               case RT_OID_802_11_QUERY_APSD_PSM:
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bAPSDForcePowerSave, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_PSM (=%d)\n", pAdapter->CommonCfg.bAPSDForcePowerSave));
+                       break;
+               case RT_OID_802_11_QUERY_WMM:
+                       wrq->u.data.length = sizeof(BOOLEAN);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bWmmCapable, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_WMM (=%d)\n",     pAdapter->CommonCfg.bWmmCapable));
+                       break;
+#ifdef WPA_SUPPLICANT_SUPPORT
+        case RT_OID_NEW_DRIVER:
+            {
+                UCHAR enabled = 1;
+               wrq->u.data.length = sizeof(UCHAR);
+               Status = copy_to_user(wrq->u.data.pointer, &enabled, wrq->u.data.length);
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_NEW_DRIVER (=%d)\n", enabled));
+            }
+               break;
+        case RT_OID_WPA_SUPPLICANT_SUPPORT:
+               wrq->u.data.length = sizeof(UCHAR);
+               Status = copy_to_user(wrq->u.data.pointer, &pAdapter->StaCfg.WpaSupplicantUP, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAdapter->StaCfg.WpaSupplicantUP));
+               break;
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+        case RT_OID_DRIVER_DEVICE_NAME:
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_DRIVER_DEVICE_NAME \n"));
+                       wrq->u.data.length = 16;
+                       if (copy_to_user(wrq->u.data.pointer, pAdapter->StaCfg.dev_name, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+            break;
+        case RT_OID_802_11_QUERY_HT_PHYMODE:
+            pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG);
+            if (pHTPhyMode)
+            {
+                pHTPhyMode->PhyMode = pAdapter->CommonCfg.PhyMode;
+                       pHTPhyMode->HtMode = (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE;
+                       pHTPhyMode->BW = (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.BW;
+                       pHTPhyMode->MCS= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS;
+                       pHTPhyMode->SHORTGI= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI;
+                       pHTPhyMode->STBC= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC;
+
+                       pHTPhyMode->ExtOffset = ((pAdapter->CommonCfg.CentralChannel < pAdapter->CommonCfg.Channel) ? (EXTCHA_BELOW) : (EXTCHA_ABOVE));
+                wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE);
+                if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n",
+                               pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset));
+                       DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word));
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case RT_OID_802_11_COUNTRY_REGION:
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_COUNTRY_REGION \n"));
+                       wrq->u.data.length = sizeof(ulInfo);
+            ulInfo = pAdapter->CommonCfg.CountryRegionForABand;
+            ulInfo = (ulInfo << 8)|(pAdapter->CommonCfg.CountryRegion);
+                       if (copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length))
+            {
+                               Status = -EFAULT;
+            }
+            break;
+        case RT_OID_802_11_QUERY_DAT_HT_PHYMODE:
+            pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG);
+            if (pHTPhyMode)
+            {
+                pHTPhyMode->PhyMode = pAdapter->CommonCfg.PhyMode;
+                       pHTPhyMode->HtMode = (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.HTMODE;
+                       pHTPhyMode->BW = (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.BW;
+                       pHTPhyMode->MCS= (UCHAR)pAdapter->StaCfg.DesiredTransmitSetting.field.MCS;
+                       pHTPhyMode->SHORTGI= (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.ShortGI;
+                       pHTPhyMode->STBC= (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.STBC;
+
+                wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE);
+                if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n",
+                               pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset));
+                       DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word));
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case RT_OID_QUERY_MULTIPLE_CARD_SUPPORT:
+                       wrq->u.data.length = sizeof(UCHAR);
+            i = 0;
+#ifdef MULTIPLE_CARD_SUPPORT
+            i = 1;
+#endif // MULTIPLE_CARD_SUPPORT //
+                       if (copy_to_user(wrq->u.data.pointer, &i, wrq->u.data.length))
+            {
+                               Status = -EFAULT;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_QUERY_MULTIPLE_CARD_SUPPORT(=%d) \n", i));
+            break;
+#ifdef SNMP_SUPPORT
+               case RT_OID_802_11_MAC_ADDRESS:
+            wrq->u.data.length = MAC_ADDR_LEN;
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_MANUFACTUREROUI:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREROUI \n"));
+                       wrq->u.data.length = ManufacturerOUI_LEN;
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_MANUFACTURERNAME:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTURERNAME \n"));
+                       wrq->u.data.length = strlen(ManufacturerNAME);
+                       Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_RESOURCETYPEIDNAME:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_RESOURCETYPEIDNAME \n"));
+                       wrq->u.data.length = strlen(ResourceTypeIdName);
+                       Status = copy_to_user(wrq->u.data.pointer, ResourceTypeIdName, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED \n"));
+                       ulInfo = 1; // 1 is support wep else 2 is not support.
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_POWERMANAGEMENTMODE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_POWERMANAGEMENTMODE \n"));
+                       if (pAdapter->StaCfg.Psm == PSMP_ACTION)
+                               ulInfo = 1; // 1 is power active else 2 is power save.
+                       else
+                               ulInfo = 2;
+
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       break;
+
+               case OID_802_11_WEPDEFAULTKEYVALUE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEPDEFAULTKEYVALUE \n"));
+                       //KeyIdxValue.KeyIdx = pAd->PortCfg.MBSSID[pAd->IoctlIF].DefaultKeyId;
+                       pKeyIdxValue = wrq->u.data.pointer;
+                       DBGPRINT(RT_DEBUG_TRACE,("KeyIdxValue.KeyIdx = %d, \n",pKeyIdxValue->KeyIdx));
+                       valueLen = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen;
+                       NdisMoveMemory(pKeyIdxValue->Value,
+                                                  &pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key,
+                                                  valueLen);
+                       pKeyIdxValue->Value[valueLen]='\0';
+
+                       wrq->u.data.length = sizeof(DefaultKeyIdxValue);
+
+                       Status = copy_to_user(wrq->u.data.pointer, pKeyIdxValue, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE,("DefaultKeyId = %d, total len = %d, str len=%d, KeyValue= %02x %02x %02x %02x \n", pAdapter->StaCfg.DefaultKeyId, wrq->u.data.length, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen,
+                       pAdapter->SharedKey[BSS0][0].Key[0],
+                       pAdapter->SharedKey[BSS0][1].Key[0],
+                       pAdapter->SharedKey[BSS0][2].Key[0],
+                       pAdapter->SharedKey[BSS0][3].Key[0]));
+                       break;
+
+               case OID_802_11_WEPDEFAULTKEYID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPDEFAULTKEYID \n"));
+                       wrq->u.data.length = sizeof(UCHAR);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->StaCfg.DefaultKeyId, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyId =%d \n", pAdapter->StaCfg.DefaultKeyId));
+                       break;
+
+               case RT_OID_802_11_WEPKEYMAPPINGLENGTH:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPKEYMAPPINGLENGTH \n"));
+                       wrq->u.data.length = sizeof(UCHAR);
+                       Status = copy_to_user(wrq->u.data.pointer,
+                                                                       &pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen,
+                                                                       wrq->u.data.length);
+                       break;
+
+               case OID_802_11_SHORTRETRYLIMIT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SHORTRETRYLIMIT \n"));
+                       wrq->u.data.length = sizeof(ULONG);
+                       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                       ShortRetryLimit = tx_rty_cfg.field.ShortRtyLimit;
+                       DBGPRINT(RT_DEBUG_TRACE, ("ShortRetryLimit =%ld,  tx_rty_cfg.field.ShortRetryLimit=%d\n", ShortRetryLimit, tx_rty_cfg.field.ShortRtyLimit));
+                       Status = copy_to_user(wrq->u.data.pointer, &ShortRetryLimit, wrq->u.data.length);
+                       break;
+
+               case OID_802_11_LONGRETRYLIMIT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_LONGRETRYLIMIT \n"));
+                       wrq->u.data.length = sizeof(ULONG);
+                       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                       LongRetryLimit = tx_rty_cfg.field.LongRtyLimit;
+                       DBGPRINT(RT_DEBUG_TRACE, ("LongRetryLimit =%ld,  tx_rty_cfg.field.LongRtyLimit=%d\n", LongRetryLimit, tx_rty_cfg.field.LongRtyLimit));
+                       Status = copy_to_user(wrq->u.data.pointer, &LongRetryLimit, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_PRODUCTID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRODUCTID \n"));
+
+#ifdef RT2870
+                       sprintf(tmp, "%04x %04x\n", ((POS_COOKIE)pAdapter->OS_Cookie)->pUsb_Dev->descriptor.idVendor ,((POS_COOKIE)pAdapter->OS_Cookie)->pUsb_Dev->descriptor.idProduct);
+
+#endif // RT2870 //
+                       wrq->u.data.length = strlen(tmp);
+                       Status = copy_to_user(wrq->u.data.pointer, tmp, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_MANUFACTUREID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREID \n"));
+                       wrq->u.data.length = strlen(ManufacturerNAME);
+                       Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length);
+                       break;
+
+               case OID_802_11_CURRENTCHANNEL:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CURRENTCHANNEL \n"));
+                       wrq->u.data.length = sizeof(UCHAR);
+                       DBGPRINT(RT_DEBUG_TRACE, ("sizeof UCHAR=%d, channel=%d \n", sizeof(UCHAR), pAdapter->CommonCfg.Channel));
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Channel, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       break;
+#endif //SNMP_SUPPORT
+
+               case OID_802_11_BUILD_CHANNEL_EX:
+                       {
+                               UCHAR value;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BUILD_CHANNEL_EX \n"));
+                               wrq->u.data.length = sizeof(UCHAR);
+#ifdef EXT_BUILD_CHANNEL_LIST
+                               DBGPRINT(RT_DEBUG_TRACE, ("Support EXT_BUILD_CHANNEL_LIST.\n"));
+                               value = 1;
+#else
+                               DBGPRINT(RT_DEBUG_TRACE, ("Doesn't support EXT_BUILD_CHANNEL_LIST.\n"));
+                               value = 0;
+#endif // EXT_BUILD_CHANNEL_LIST //
+                               Status = copy_to_user(wrq->u.data.pointer, &value, 1);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       }
+                       break;
+
+               case OID_802_11_GET_CH_LIST:
+                       {
+                               PRT_CHANNEL_LIST_INFO pChListBuf;
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CH_LIST \n"));
+                               if (pAdapter->ChannelListNum == 0)
+                               {
+                                       wrq->u.data.length = 0;
+                                       break;
+                               }
+
+                               pChListBuf = (RT_CHANNEL_LIST_INFO *) kmalloc(sizeof(RT_CHANNEL_LIST_INFO), MEM_ALLOC_FLAG);
+                               if (pChListBuf == NULL)
+                               {
+                                       wrq->u.data.length = 0;
+                                       break;
+                               }
+
+                               pChListBuf->ChannelListNum = pAdapter->ChannelListNum;
+                               for (i = 0; i < pChListBuf->ChannelListNum; i++)
+                                       pChListBuf->ChannelList[i] = pAdapter->ChannelList[i].Channel;
+
+                               wrq->u.data.length = sizeof(RT_CHANNEL_LIST_INFO);
+                               Status = copy_to_user(wrq->u.data.pointer, pChListBuf, sizeof(RT_CHANNEL_LIST_INFO));
+                               DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+
+                               if (pChListBuf)
+                                       kfree(pChListBuf);
+                       }
+                       break;
+
+               case OID_802_11_GET_COUNTRY_CODE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_COUNTRY_CODE \n"));
+                       wrq->u.data.length = 2;
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.CountryCode, 2);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       break;
+
+               case OID_802_11_GET_CHANNEL_GEOGRAPHY:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CHANNEL_GEOGRAPHY \n"));
+                       wrq->u.data.length = 1;
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Geography, 1);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       break;
+
+
+#ifdef QOS_DLS_SUPPORT
+               case RT_OID_802_11_QUERY_DLS:
+                       wrq->u.data.length = sizeof(BOOLEAN);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bDLSCapable, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS(=%d)\n", pAdapter->CommonCfg.bDLSCapable));
+                       break;
+
+               case RT_OID_802_11_QUERY_DLS_PARAM:
+                       {
+                               PRT_802_11_DLS_INFO     pDlsInfo = kmalloc(sizeof(RT_802_11_DLS_INFO), GFP_ATOMIC);
+                               if (pDlsInfo == NULL)
+                                       break;
+
+                               for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
+                               {
+                                       RTMPMoveMemory(&pDlsInfo->Entry[i], &pAdapter->StaCfg.DLSEntry[i], sizeof(RT_802_11_DLS_UI));
+                               }
+
+                               pDlsInfo->num = MAX_NUM_OF_DLS_ENTRY;
+                               wrq->u.data.length = sizeof(RT_802_11_DLS_INFO);
+                               Status = copy_to_user(wrq->u.data.pointer, pDlsInfo, wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS_PARAM\n"));
+
+                               if (pDlsInfo)
+                                       kfree(pDlsInfo);
+                       }
+                       break;
+#endif // QOS_DLS_SUPPORT //
+        default:
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::unknown IOCTL's subcmd = 0x%08x\n", cmd));
+            Status = -EOPNOTSUPP;
+            break;
+    }
+    return Status;
+}
+
+INT rt28xx_sta_ioctl(
+       IN      struct net_device       *net_dev,
+       IN      OUT     struct ifreq    *rq,
+       IN      INT                                     cmd)
+{
+       POS_COOKIE                      pObj;
+       VIRTUAL_ADAPTER         *pVirtualAd = NULL;
+       RTMP_ADAPTER        *pAd = NULL;
+       struct iwreq        *wrq = (struct iwreq *) rq;
+       BOOLEAN                         StateMachineTouched = FALSE;
+       INT                                     Status = NDIS_STATUS_SUCCESS;
+       USHORT                          subcmd;
+
+       if (net_dev->priv_flags == INT_MAIN)
+       {
+               pAd = net_dev->priv;
+       }
+       else
+       {
+               pVirtualAd = net_dev->priv;
+               pAd = pVirtualAd->RtmpDev->priv;
+       }
+       pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+       if (pAd == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+           if (wrq->u.data.pointer == NULL)
+           {
+                   return Status;
+           }
+
+           if (strstr(wrq->u.data.pointer, "OpMode") == NULL)
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+        {
+            DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+                   return -ENETDOWN;
+        }
+    }
+
+       {       // determine this ioctl command is comming from which interface.
+               pObj->ioctl_if_type = INT_MAIN;
+               pObj->ioctl_if = MAIN_MBSSID;
+       }
+
+       switch(cmd)
+       {
+#ifdef RALINK_ATE
+#ifdef RALINK_28xx_QA
+               case RTPRIV_IOCTL_ATE:
+                       {
+                               RtmpDoAte(pAd, wrq);
+                       }
+                       break;
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+        case SIOCGIFHWADDR:
+                       DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIFHWADDR\n"));
+                       memcpy(wrq->u.name, pAd->CurrentAddress, ETH_ALEN);
+                       break;
+               case SIOCGIWNAME:
+        {
+               char *name=&wrq->u.name[0];
+               rt_ioctl_giwname(net_dev, NULL, name, NULL);
+                       break;
+               }
+               case SIOCGIWESSID:  //Get ESSID
+        {
+               struct iw_point *essid=&wrq->u.essid;
+               rt_ioctl_giwessid(net_dev, NULL, essid, essid->pointer);
+                       break;
+               }
+               case SIOCSIWESSID:  //Set ESSID
+        {
+               struct iw_point *essid=&wrq->u.essid;
+               rt_ioctl_siwessid(net_dev, NULL, essid, essid->pointer);
+                       break;
+               }
+               case SIOCSIWNWID:   // set network id (the cell)
+               case SIOCGIWNWID:   // get network id
+                       Status = -EOPNOTSUPP;
+                       break;
+               case SIOCSIWFREQ:   //set channel/frequency (Hz)
+        {
+               struct iw_freq *freq=&wrq->u.freq;
+               rt_ioctl_siwfreq(net_dev, NULL, freq, NULL);
+                       break;
+               }
+               case SIOCGIWFREQ:   // get channel/frequency (Hz)
+        {
+               struct iw_freq *freq=&wrq->u.freq;
+               rt_ioctl_giwfreq(net_dev, NULL, freq, NULL);
+                       break;
+               }
+               case SIOCSIWNICKN: //set node name/nickname
+        {
+               struct iw_point *data=&wrq->u.data;
+               rt_ioctl_siwnickn(net_dev, NULL, data, NULL);
+                       break;
+               }
+               case SIOCGIWNICKN: //get node name/nickname
+        {
+               struct iw_point *data=&wrq->u.data;
+               rt_ioctl_giwnickn(net_dev, NULL, data, NULL);
+                       break;
+               }
+               case SIOCGIWRATE:   //get default bit rate (bps)
+                   rt_ioctl_giwrate(net_dev, NULL, &wrq->u, NULL);
+            break;
+           case SIOCSIWRATE:  //set default bit rate (bps)
+               rt_ioctl_siwrate(net_dev, NULL, &wrq->u, NULL);
+            break;
+        case SIOCGIWRTS:  // get RTS/CTS threshold (bytes)
+        {
+               struct iw_param *rts=&wrq->u.rts;
+               rt_ioctl_giwrts(net_dev, NULL, rts, NULL);
+                       break;
+               }
+        case SIOCSIWRTS:  //set RTS/CTS threshold (bytes)
+        {
+               struct iw_param *rts=&wrq->u.rts;
+               rt_ioctl_siwrts(net_dev, NULL, rts, NULL);
+                       break;
+               }
+        case SIOCGIWFRAG:  //get fragmentation thr (bytes)
+        {
+               struct iw_param *frag=&wrq->u.frag;
+               rt_ioctl_giwfrag(net_dev, NULL, frag, NULL);
+                       break;
+               }
+        case SIOCSIWFRAG:  //set fragmentation thr (bytes)
+        {
+               struct iw_param *frag=&wrq->u.frag;
+               rt_ioctl_siwfrag(net_dev, NULL, frag, NULL);
+                       break;
+               }
+        case SIOCGIWENCODE:  //get encoding token & mode
+        {
+               struct iw_point *erq=&wrq->u.encoding;
+               if(erq->pointer)
+                       rt_ioctl_giwencode(net_dev, NULL, erq, erq->pointer);
+                       break;
+               }
+        case SIOCSIWENCODE:  //set encoding token & mode
+        {
+               struct iw_point *erq=&wrq->u.encoding;
+               if(erq->pointer)
+                       rt_ioctl_siwencode(net_dev, NULL, erq, erq->pointer);
+                       break;
+               }
+               case SIOCGIWAP:     //get access point MAC addresses
+        {
+               struct sockaddr *ap_addr=&wrq->u.ap_addr;
+               rt_ioctl_giwap(net_dev, NULL, ap_addr, ap_addr->sa_data);
+                       break;
+               }
+           case SIOCSIWAP:  //set access point MAC addresses
+        {
+               struct sockaddr *ap_addr=&wrq->u.ap_addr;
+               rt_ioctl_siwap(net_dev, NULL, ap_addr, ap_addr->sa_data);
+                       break;
+               }
+               case SIOCGIWMODE:   //get operation mode
+        {
+               __u32 *mode=&wrq->u.mode;
+               rt_ioctl_giwmode(net_dev, NULL, mode, NULL);
+                       break;
+               }
+               case SIOCSIWMODE:   //set operation mode
+        {
+               __u32 *mode=&wrq->u.mode;
+               rt_ioctl_siwmode(net_dev, NULL, mode, NULL);
+                       break;
+               }
+               case SIOCGIWSENS:   //get sensitivity (dBm)
+               case SIOCSIWSENS:       //set sensitivity (dBm)
+               case SIOCGIWPOWER:  //get Power Management settings
+               case SIOCSIWPOWER:  //set Power Management settings
+               case SIOCGIWTXPOW:  //get transmit power (dBm)
+               case SIOCSIWTXPOW:  //set transmit power (dBm)
+               case SIOCGIWRANGE:      //Get range of parameters
+               case SIOCGIWRETRY:      //get retry limits and lifetime
+               case SIOCSIWRETRY:      //set retry limits and lifetime
+                       Status = -EOPNOTSUPP;
+                       break;
+               case RT_PRIV_IOCTL:
+                       subcmd = wrq->u.data.flags;
+                       if( subcmd & OID_GET_SET_TOGGLE)
+                               Status = RTMPSetInformation(pAd, rq, subcmd);
+                       else
+                               Status = RTMPQueryInformation(pAd, rq, subcmd);
+                       break;
+               case SIOCGIWPRIV:
+                       if (wrq->u.data.pointer)
+                       {
+                               if ( access_ok(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab)) != TRUE)
+                                       break;
+                               wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
+                               if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
+                                       Status = -EFAULT;
+                       }
+                       break;
+               case RTPRIV_IOCTL_SET:
+                       if(access_ok(VERIFY_READ, wrq->u.data.pointer, wrq->u.data.length) != TRUE)
+                               break;
+                       rt_ioctl_setparam(net_dev, NULL, NULL, wrq->u.data.pointer);
+                       break;
+               case RTPRIV_IOCTL_GSITESURVEY:
+                       RTMPIoctlGetSiteSurvey(pAd, wrq);
+                   break;
+#ifdef DBG
+               case RTPRIV_IOCTL_MAC:
+                       RTMPIoctlMAC(pAd, wrq);
+                       break;
+               case RTPRIV_IOCTL_E2P:
+                       RTMPIoctlE2PROM(pAd, wrq);
+                       break;
+#endif // DBG //
+        case SIOCETHTOOL:
+                break;
+               default:
+                       DBGPRINT(RT_DEBUG_ERROR, ("IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd));
+                       Status = -EOPNOTSUPP;
+                       break;
+       }
+
+    if(StateMachineTouched) // Upper layer sent a MLME-related operations
+       RT28XX_MLME_HANDLER(pAd);
+
+       return Status;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set SSID
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_SSID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    NDIS_802_11_SSID                    Ssid, *pSsid=NULL;
+    BOOLEAN                             StateMachineTouched = FALSE;
+    int                                 success = TRUE;
+
+    if( strlen(arg) <= MAX_LEN_OF_SSID)
+    {
+        NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID));
+        if (strlen(arg) != 0)
+        {
+            NdisMoveMemory(Ssid.Ssid, arg, strlen(arg));
+            Ssid.SsidLength = strlen(arg);
+        }
+        else   //ANY ssid
+        {
+            Ssid.SsidLength = 0;
+                   memcpy(Ssid.Ssid, "", 0);
+                       pAdapter->StaCfg.BssType = BSS_INFRA;
+                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+               pAdapter->StaCfg.WepStatus  = Ndis802_11EncryptionDisabled;
+               }
+        pSsid = &Ssid;
+
+        if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+        {
+            RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+            DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+        }
+
+        pAdapter->MlmeAux.CurrReqIsFromNdis = TRUE;
+        pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE;
+               pAdapter->bConfigChanged = TRUE;
+
+        MlmeEnqueue(pAdapter,
+                    MLME_CNTL_STATE_MACHINE,
+                    OID_802_11_SSID,
+                    sizeof(NDIS_802_11_SSID),
+                    (VOID *)pSsid);
+
+        StateMachineTouched = TRUE;
+        DBGPRINT(RT_DEBUG_TRACE, ("Set_SSID_Proc::(Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid));
+    }
+    else
+        success = FALSE;
+
+    if (StateMachineTouched) // Upper layer sent a MLME-related operations
+       RT28XX_MLME_HANDLER(pAdapter);
+
+    return success;
+}
+
+#ifdef WMM_SUPPORT
+/*
+    ==========================================================================
+    Description:
+        Set WmmCapable Enable or Disable
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_WmmCapable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       BOOLEAN bWmmCapable;
+
+       bWmmCapable = simple_strtol(arg, 0, 10);
+
+       if ((bWmmCapable == 1)
+#ifdef RT2870
+               && (pAd->NumberOfPipes >= 5)
+#endif // RT2870 //
+               )
+               pAd->CommonCfg.bWmmCapable = TRUE;
+       else if (bWmmCapable == 0)
+               pAd->CommonCfg.bWmmCapable = FALSE;
+       else
+               return FALSE;  //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_WmmCapable_Proc::(bWmmCapable=%d)\n",
+               pAd->CommonCfg.bWmmCapable));
+
+       return TRUE;
+}
+#endif // WMM_SUPPORT //
+
+/*
+    ==========================================================================
+    Description:
+        Set Network Type(Infrastructure/Adhoc mode)
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_NetworkType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    UINT32     Value = 0;
+
+    if (strcmp(arg, "Adhoc") == 0)
+       {
+               if (pAdapter->StaCfg.BssType != BSS_ADHOC)
+               {
+                       // Config has changed
+                       pAdapter->bConfigChanged = TRUE;
+            if (MONITOR_ON(pAdapter))
+            {
+                RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL);
+                RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value);
+                               Value &= (~0x80);
+                               RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value);
+                OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED);
+                pAdapter->StaCfg.bAutoReconnect = TRUE;
+                LinkDown(pAdapter, FALSE);
+            }
+                       if (INFRA_ON(pAdapter))
+                       {
+                               //BOOLEAN Cancelled;
+                               // Set the AutoReconnectSsid to prevent it reconnect to old SSID
+                               // Since calling this indicate user don't want to connect to that SSID anymore.
+                               pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+                               NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen);
+
+                               LinkDown(pAdapter, FALSE);
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event BB!\n"));
+                       }
+               }
+               pAdapter->StaCfg.BssType = BSS_ADHOC;
+        pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType;
+               DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(AD-HOC)\n"));
+       }
+    else if (strcmp(arg, "Infra") == 0)
+       {
+               if (pAdapter->StaCfg.BssType != BSS_INFRA)
+               {
+                       // Config has changed
+                       pAdapter->bConfigChanged = TRUE;
+            if (MONITOR_ON(pAdapter))
+            {
+                RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL);
+                RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value);
+                               Value &= (~0x80);
+                               RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value);
+                OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED);
+                pAdapter->StaCfg.bAutoReconnect = TRUE;
+                LinkDown(pAdapter, FALSE);
+            }
+                       if (ADHOC_ON(pAdapter))
+                       {
+                               // Set the AutoReconnectSsid to prevent it reconnect to old SSID
+                               // Since calling this indicate user don't want to connect to that SSID anymore.
+                               pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+                               NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen);
+
+                               LinkDown(pAdapter, FALSE);
+                       }
+               }
+               pAdapter->StaCfg.BssType = BSS_INFRA;
+        pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType;
+               DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(INFRA)\n"));
+
+        pAdapter->StaCfg.BssType = BSS_INFRA;
+       }
+    else if (strcmp(arg, "Monitor") == 0)
+    {
+               UCHAR   bbpValue = 0;
+               BCN_TIME_CFG_STRUC csr;
+               OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_INFRA_ON);
+        OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_ADHOC_ON);
+               OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED);
+               // disable all periodic state machine
+               pAdapter->StaCfg.bAutoReconnect = FALSE;
+               // reset all mlme state machine
+               RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+               DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_MEDIA_STATE_CONNECTED \n"));
+        if (pAdapter->CommonCfg.CentralChannel == 0)
+        {
+#ifdef DOT11_N_SUPPORT
+            if (pAdapter->CommonCfg.PhyMode == PHY_11AN_MIXED)
+                pAdapter->CommonCfg.CentralChannel = 36;
+            else
+#endif // DOT11_N_SUPPORT //
+                pAdapter->CommonCfg.CentralChannel = 6;
+        }
+#ifdef DOT11_N_SUPPORT
+        else
+            N_ChannelCheck(pAdapter);
+#endif // DOT11_N_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+       if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED &&
+            pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 &&
+            pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE)
+               {
+                       // 40MHz ,control channel at lower
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue);
+                       bbpValue &= (~0x18);
+                       bbpValue |= 0x10;
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue);
+                       pAdapter->CommonCfg.BBPCurrentBW = BW_40;
+                       //  RX : control channel at lower
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue);
+                       bbpValue &= (~0x20);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue);
+
+                       RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value);
+                       Value &= 0xfffffffe;
+                       RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value);
+                       pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel + 2;
+            AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE);
+                   AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel);
+            DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n",
+                                       pAdapter->CommonCfg.Channel,
+                                       pAdapter->CommonCfg.CentralChannel));
+               }
+               else if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED &&
+                 pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 &&
+                 pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)
+               {
+                       // 40MHz ,control channel at upper
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue);
+                       bbpValue &= (~0x18);
+                       bbpValue |= 0x10;
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue);
+                       pAdapter->CommonCfg.BBPCurrentBW = BW_40;
+                       RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value);
+                       Value |= 0x1;
+                       RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value);
+
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue);
+                       bbpValue |= (0x20);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue);
+                       pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel - 2;
+            AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE);
+                   AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel);
+            DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n",
+                                       pAdapter->CommonCfg.Channel,
+                                       pAdapter->CommonCfg.CentralChannel));
+               }
+               else
+#endif // DOT11_N_SUPPORT //
+               {
+                       // 20MHz
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue);
+                       bbpValue &= (~0x18);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue);
+                       pAdapter->CommonCfg.BBPCurrentBW = BW_20;
+                       AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.Channel, FALSE);
+                       AsicLockChannel(pAdapter, pAdapter->CommonCfg.Channel);
+                       DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAdapter->CommonCfg.Channel));
+               }
+               // Enable Rx with promiscuous reception
+               RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, 0x3);
+               // ASIC supporsts sniffer function with replacing RSSI with timestamp.
+               //RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value);
+               //Value |= (0x80);
+               //RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value);
+               // disable sync
+               RTMP_IO_READ32(pAdapter, BCN_TIME_CFG, &csr.word);
+               csr.field.bBeaconGen = 0;
+               csr.field.bTBTTEnable = 0;
+               csr.field.TsfSyncMode = 0;
+               RTMP_IO_WRITE32(pAdapter, BCN_TIME_CFG, csr.word);
+
+               pAdapter->StaCfg.BssType = BSS_MONITOR;
+        pAdapter->net_dev->type = ARPHRD_IEEE80211_PRISM; //ARPHRD_IEEE80211; // IEEE80211
+               DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(MONITOR)\n"));
+    }
+
+    // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key
+    pAdapter->StaCfg.WpaState = SS_NOTUSE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_NetworkType_Proc::(NetworkType=%d)\n", pAdapter->StaCfg.BssType));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Authentication mode
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_AuthMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch;
+    else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+    else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared;
+    else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK;
+    else if ((strcmp(arg, "WPANONE") == 0) || (strcmp(arg, "wpanone") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone;
+    else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK;
+#ifdef WPA_SUPPLICANT_SUPPORT
+    else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA;
+    else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2;
+#endif // WPA_SUPPLICANT_SUPPORT //
+    else
+        return FALSE;
+
+    pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_AuthMode_Proc::(AuthMode=%d)\n", pAdapter->StaCfg.AuthMode));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Encryption Type
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_EncrypType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11WEPDisabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11WEPDisabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11WEPDisabled;
+    }
+    else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11WEPEnabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11WEPEnabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11WEPEnabled;
+    }
+    else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11Encryption2Enabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11Encryption2Enabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11Encryption2Enabled;
+    }
+    else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11Encryption3Enabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11Encryption3Enabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11Encryption3Enabled;
+    }
+    else
+        return FALSE;
+
+    pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_EncrypType_Proc::(EncrypType=%d)\n", pAdapter->StaCfg.WepStatus));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Default Key ID
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_DefaultKeyID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    ULONG                               KeyIdx;
+
+    KeyIdx = simple_strtol(arg, 0, 10);
+    if((KeyIdx >= 1 ) && (KeyIdx <= 4))
+        pAdapter->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1 );
+    else
+        return FALSE;  //Invalid argument
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_DefaultKeyID_Proc::(DefaultKeyID=%d)\n", pAdapter->StaCfg.DefaultKeyId));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set WEP KEY1
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key1_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex"));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex"));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+
+    pAdapter->SharedKey[BSS0][0].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              0,
+                              pAdapter->SharedKey[BSS0][0].CipherAlg,
+                              pAdapter->SharedKey[BSS0][0].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+/*
+    ==========================================================================
+
+    Description:
+        Set WEP KEY2
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key2_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex"));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex"));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+    pAdapter->SharedKey[BSS0][1].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              1,
+                              pAdapter->SharedKey[BSS0][1].CipherAlg,
+                              pAdapter->SharedKey[BSS0][1].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+/*
+    ==========================================================================
+    Description:
+        Set WEP KEY3
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key3_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+    pAdapter->SharedKey[BSS0][2].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              2,
+                              pAdapter->SharedKey[BSS0][2].CipherAlg,
+                              pAdapter->SharedKey[BSS0][2].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+/*
+    ==========================================================================
+    Description:
+        Set WEP KEY4
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key4_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex"));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex"));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+    pAdapter->SharedKey[BSS0][3].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              3,
+                              pAdapter->SharedKey[BSS0][3].CipherAlg,
+                              pAdapter->SharedKey[BSS0][3].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set WPA PSK key
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_WPAPSK_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    UCHAR                   keyMaterial[40];
+
+    if ((pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) &&
+        (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) &&
+           (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone)
+               )
+        return TRUE;    // do nothing
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc::(WPAPSK=%s)\n", arg));
+
+    NdisZeroMemory(keyMaterial, 40);
+
+    if ((strlen(arg) < 8) || (strlen(arg) > 64))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("Set failed!!(WPAPSK=%s), WPAPSK key-string required 8 ~ 64 characters \n", arg));
+        return FALSE;
+    }
+
+    if (strlen(arg) == 64)
+    {
+        AtoH(arg, keyMaterial, 32);
+        NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32);
+
+    }
+    else
+    {
+        PasswordHash((char *)arg, pAdapter->MlmeAux.Ssid, pAdapter->MlmeAux.SsidLen, keyMaterial);
+        NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32);
+    }
+
+
+
+    if(pAdapter->StaCfg.BssType == BSS_ADHOC &&
+       pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+    {
+         pAdapter->StaCfg.WpaState = SS_NOTUSE;
+    }
+    else
+    {
+        // Start STA supplicant state machine
+        pAdapter->StaCfg.WpaState = SS_START;
+    }
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Power Saving mode
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_PSMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if (pAdapter->StaCfg.BssType == BSS_INFRA)
+    {
+        if ((strcmp(arg, "Max_PSP") == 0) ||
+                       (strcmp(arg, "max_psp") == 0) ||
+                       (strcmp(arg, "MAX_PSP") == 0))
+        {
+            // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+            // to exclude certain situations.
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP;
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            pAdapter->StaCfg.DefaultListenCount = 5;
+
+        }
+        else if ((strcmp(arg, "Fast_PSP") == 0) ||
+                                (strcmp(arg, "fast_psp") == 0) ||
+                 (strcmp(arg, "FAST_PSP") == 0))
+        {
+            // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+            // to exclude certain situations.
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP;
+            pAdapter->StaCfg.DefaultListenCount = 3;
+        }
+        else if ((strcmp(arg, "Legacy_PSP") == 0) ||
+                 (strcmp(arg, "legacy_psp") == 0) ||
+                 (strcmp(arg, "LEGACY_PSP") == 0))
+        {
+            // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+            // to exclude certain situations.
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP;
+            pAdapter->StaCfg.DefaultListenCount = 3;
+        }
+        else
+        {
+            //Default Ndis802_11PowerModeCAM
+            // clear PSM bit immediately
+            MlmeSetPsmBit(pAdapter, PWR_ACTIVE);
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM;
+        }
+
+        DBGPRINT(RT_DEBUG_TRACE, ("Set_PSMode_Proc::(PSMode=%ld)\n", pAdapter->StaCfg.WindowsPowerMode));
+    }
+    else
+        return FALSE;
+
+
+    return TRUE;
+}
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+/*
+    ==========================================================================
+    Description:
+        Set WpaSupport flag.
+    Value:
+        0: Driver ignore wpa_supplicant.
+        1: wpa_supplicant initiates scanning and AP selection.
+        2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters.
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Wpa_Support(
+    IN PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+
+    if ( simple_strtol(arg, 0, 10) == 0)
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE;
+    else if ( simple_strtol(arg, 0, 10) == 1)
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE;
+    else if ( simple_strtol(arg, 0, 10) == 2)
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE_WITH_WEB_UI;
+    else
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_Wpa_Support::(WpaSupplicantUP=%d)\n", pAd->StaCfg.WpaSupplicantUP));
+
+    return TRUE;
+}
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef DBG
+/*
+    ==========================================================================
+    Description:
+        Read / Write MAC
+    Arguments:
+        pAdapter                    Pointer to our adapter
+        wrq                         Pointer to the ioctl argument
+
+    Return Value:
+        None
+
+    Note:
+        Usage:
+               1.) iwpriv ra0 mac 0        ==> read MAC where Addr=0x0
+               2.) iwpriv ra0 mac 0=12     ==> write MAC where Addr=0x0, value=12
+    ==========================================================================
+*/
+VOID RTMPIoctlMAC(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq)
+{
+       CHAR                            *this_char;
+       CHAR                            *value;
+       INT                                     j = 0, k = 0;
+       CHAR                            msg[1024];
+       CHAR                            arg[255];
+       ULONG                           macAddr = 0;
+       UCHAR                           temp[16], temp2[16];
+       UINT32                          macValue = 0;
+       INT                                     Status;
+
+
+       memset(msg, 0x00, 1024);
+       if (wrq->u.data.length > 1) //No parameters.
+       {
+           Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length);
+               sprintf(msg, "\n");
+
+               //Parsing Read or Write
+           this_char = arg;
+               if (!*this_char)
+                       goto next;
+
+               if ((value = rtstrchr(this_char, '=')) != NULL)
+                       *value++ = 0;
+
+               if (!value || !*value)
+               { //Read
+                       // Sanity check
+                       if(strlen(this_char) > 4)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+
+                       // Mac Addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       if(strlen(this_char) == 4)
+                       {
+                               AtoH(this_char, temp, 2);
+                               macAddr = *temp*256 + temp[1];
+                               if (macAddr < 0xFFFF)
+                               {
+                                       RTMP_IO_READ32(pAdapter, macAddr, &macValue);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%lx, MacValue=%x\n", macAddr, macValue));
+                                       sprintf(msg+strlen(msg), "[0x%08lX]:%08X  ", macAddr , macValue);
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       goto next;
+                               }
+                       }
+               }
+               else
+               { //Write
+                       memcpy(&temp2, value, strlen(value));
+                       temp2[strlen(value)] = '\0';
+
+                       // Sanity check
+                       if((strlen(this_char) > 4) || strlen(temp2) > 8)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+
+                       j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               if(temp2[j] > 'f' || temp2[j] < '0')
+                                       return;
+                       }
+
+                       //MAC Addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       //MAC value
+                       k = j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               temp2[8-k+j] = temp2[j];
+                       }
+
+                       while(k < 8)
+                               temp2[7-k++]='0';
+                       temp2[8]='\0';
+
+                       {
+                               AtoH(this_char, temp, 2);
+                               macAddr = *temp*256 + temp[1];
+
+                               AtoH(temp2, temp, 4);
+                               macValue = *temp*256*256*256 + temp[1]*256*256 + temp[2]*256 + temp[3];
+
+                               // debug mode
+                               if (macAddr == (HW_DEBUG_SETTING_BASE + 4))
+                               {
+                                       // 0x2bf4: byte0 non-zero: enable R17 tuning, 0: disable R17 tuning
+                    if (macValue & 0x000000ff)
+                    {
+                        pAdapter->BbpTuning.bEnable = TRUE;
+                        DBGPRINT(RT_DEBUG_TRACE,("turn on R17 tuning\n"));
+                    }
+                    else
+                    {
+                        UCHAR R66;
+                        pAdapter->BbpTuning.bEnable = FALSE;
+                        R66 = 0x26 + GET_LNA_GAIN(pAdapter);
+#ifdef RALINK_ATE
+                                               if (ATE_ON(pAdapter))
+                                               {
+                                                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter)));
+                                               }
+                                               else
+#endif // RALINK_ATE //
+                                               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter)));
+                        DBGPRINT(RT_DEBUG_TRACE,("turn off R17 tuning, restore to 0x%02x\n", R66));
+                    }
+                                       return;
+                               }
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%02lx, MacValue=0x%x\n", macAddr, macValue));
+
+                               RTMP_IO_WRITE32(pAdapter, macAddr, macValue);
+                               sprintf(msg+strlen(msg), "[0x%08lX]:%08X  ", macAddr, macValue);
+                       }
+               }
+       }
+next:
+       if(strlen(msg) == 1)
+               sprintf(msg+strlen(msg), "===>Error command format!");
+
+       // Copy the information into the user buffer
+       wrq->u.data.length = strlen(msg);
+       Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlMAC\n\n"));
+}
+
+/*
+    ==========================================================================
+    Description:
+        Read / Write E2PROM
+    Arguments:
+        pAdapter                    Pointer to our adapter
+        wrq                         Pointer to the ioctl argument
+
+    Return Value:
+        None
+
+    Note:
+        Usage:
+               1.) iwpriv ra0 e2p 0            ==> read E2PROM where Addr=0x0
+               2.) iwpriv ra0 e2p 0=1234    ==> write E2PROM where Addr=0x0, value=1234
+    ==========================================================================
+*/
+VOID RTMPIoctlE2PROM(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq)
+{
+       CHAR                            *this_char;
+       CHAR                            *value;
+       INT                                     j = 0, k = 0;
+       CHAR                            msg[1024];
+       CHAR                            arg[255];
+       USHORT                          eepAddr = 0;
+       UCHAR                           temp[16], temp2[16];
+       USHORT                          eepValue;
+       int                                     Status;
+
+
+       memset(msg, 0x00, 1024);
+       if (wrq->u.data.length > 1) //No parameters.
+       {
+           Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length);
+               sprintf(msg, "\n");
+
+           //Parsing Read or Write
+               this_char = arg;
+
+
+               if (!*this_char)
+                       goto next;
+
+               if ((value = rtstrchr(this_char, '=')) != NULL)
+                       *value++ = 0;
+
+               if (!value || !*value)
+               { //Read
+
+                       // Sanity check
+                       if(strlen(this_char) > 4)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+
+                       // E2PROM addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       if(strlen(this_char) == 4)
+                       {
+                               AtoH(this_char, temp, 2);
+                               eepAddr = *temp*256 + temp[1];
+                               if (eepAddr < 0xFFFF)
+                               {
+                                       RT28xx_EEPROM_READ16(pAdapter, eepAddr, eepValue);
+                                       sprintf(msg+strlen(msg), "[0x%04X]:0x%04X  ", eepAddr , eepValue);
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       goto next;
+                               }
+                       }
+               }
+               else
+               { //Write
+                       memcpy(&temp2, value, strlen(value));
+                       temp2[strlen(value)] = '\0';
+
+                       // Sanity check
+                       if((strlen(this_char) > 4) || strlen(temp2) > 8)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+                       j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               if(temp2[j] > 'f' || temp2[j] < '0')
+                                       return;
+                       }
+
+                       //MAC Addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       //MAC value
+                       k = j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               temp2[4-k+j] = temp2[j];
+                       }
+
+                       while(k < 4)
+                               temp2[3-k++]='0';
+                       temp2[4]='\0';
+
+                       AtoH(this_char, temp, 2);
+                       eepAddr = *temp*256 + temp[1];
+
+                       AtoH(temp2, temp, 2);
+                       eepValue = *temp*256 + temp[1];
+
+                       RT28xx_EEPROM_WRITE16(pAdapter, eepAddr, eepValue);
+                       sprintf(msg+strlen(msg), "[0x%02X]:%02X  ", eepAddr, eepValue);
+               }
+       }
+next:
+       if(strlen(msg) == 1)
+               sprintf(msg+strlen(msg), "===>Error command format!");
+
+
+       // Copy the information into the user buffer
+       wrq->u.data.length = strlen(msg);
+       Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlE2PROM\n"));
+}
+#endif // DBG //
+
+
+
+
+INT Set_TGnWifiTest_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg)
+{
+    if (simple_strtol(arg, 0, 10) == 0)
+        pAd->StaCfg.bTGnWifiTest = FALSE;
+    else
+        pAd->StaCfg.bTGnWifiTest = TRUE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("IF Set_TGnWifiTest_Proc::(bTGnWifiTest=%d)\n", pAd->StaCfg.bTGnWifiTest));
+       return TRUE;
+}
+
+INT Set_LongRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg)
+{
+       TX_RTY_CFG_STRUC        tx_rty_cfg;
+       UCHAR                           LongRetryLimit = (UCHAR)simple_strtol(arg, 0, 10);
+
+       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+       tx_rty_cfg.field.LongRtyLimit = LongRetryLimit;
+       RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+       DBGPRINT(RT_DEBUG_TRACE, ("IF Set_LongRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word));
+       return TRUE;
+}
+
+INT Set_ShortRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg)
+{
+       TX_RTY_CFG_STRUC        tx_rty_cfg;
+       UCHAR                           ShortRetryLimit = (UCHAR)simple_strtol(arg, 0, 10);
+
+       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+       tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit;
+       RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+       DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ShortRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word));
+       return TRUE;
+}
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+INT Set_Ieee80211dClientMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if (simple_strtol(arg, 0, 10) == 0)
+        pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_None;
+    else if (simple_strtol(arg, 0, 10) == 1)
+        pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Flexible;
+    else if (simple_strtol(arg, 0, 10) == 2)
+        pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Strict;
+    else
+        return FALSE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_Ieee802dMode_Proc::(IEEEE0211dMode=%d)\n", pAdapter->StaCfg.IEEE80211dClientMode));
+    return TRUE;
+}
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+#ifdef CARRIER_DETECTION_SUPPORT
+INT Set_CarrierDetect_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg)
+{
+    if (simple_strtol(arg, 0, 10) == 0)
+        pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+    else
+        pAd->CommonCfg.CarrierDetect.Enable = TRUE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("IF Set_CarrierDetect_Proc::(CarrierDetect.Enable=%d)\n", pAd->CommonCfg.CarrierDetect.Enable));
+       return TRUE;
+}
+#endif // CARRIER_DETECTION_SUPPORT //
+
+
+INT    Show_Adhoc_MacTable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PCHAR                   extra)
+{
+       INT i;
+
+       sprintf(extra, "\n");
+
+#ifdef DOT11_N_SUPPORT
+       sprintf(extra, "%sHT Operating Mode : %d\n", extra, pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode);
+#endif // DOT11_N_SUPPORT //
+
+       sprintf(extra, "%s\n%-19s%-4s%-4s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s\n", extra,
+                       "MAC", "AID", "BSS", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC");
+
+       for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+
+               if (strlen(extra) > (IW_PRIV_SIZE_MASK - 30))
+                   break;
+               if ((pEntry->ValidAsCLI || pEntry->ValidAsApCli) && (pEntry->Sst == SST_ASSOC))
+               {
+                       sprintf(extra, "%s%02X:%02X:%02X:%02X:%02X:%02X  ", extra,
+                               pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+                               pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]);
+                       sprintf(extra, "%s%-4d", extra, (int)pEntry->Aid);
+                       sprintf(extra, "%s%-4d", extra, (int)pEntry->apidx);
+                       sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi0);
+                       sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi1);
+                       sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi2);
+                       sprintf(extra, "%s%-10s", extra, GetPhyMode(pEntry->HTPhyMode.field.MODE));
+                       sprintf(extra, "%s%-6s", extra, GetBW(pEntry->HTPhyMode.field.BW));
+                       sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.MCS);
+                       sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.ShortGI);
+                       sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.STBC);
+                       sprintf(extra, "%s%-10d, %d, %d%%\n", extra, pEntry->DebugFIFOCount, pEntry->DebugTxCount,
+                                               (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0);
+                       sprintf(extra, "%s\n", extra);
+               }
+       }
+
+       return TRUE;
+}
+
+
diff --git a/drivers/staging/rt2870/tmp61 b/drivers/staging/rt2870/tmp61
new file mode 100644 (file)
index 0000000..992096a
--- /dev/null
@@ -0,0 +1,7037 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+    Module Name:
+    sta_ioctl.c
+
+    Abstract:
+    IOCTL related subroutines
+
+    Revision History:
+    Who         When          What
+    --------    ----------    ----------------------------------------------
+    Rory Chen   01-03-2003    created
+       Rory Chen   02-14-2005    modify to support RT61
+*/
+
+#include       "rt_config.h"
+
+#ifdef DBG
+extern ULONG    RTDebugLevel;
+#endif
+
+#define NR_WEP_KEYS                            4
+#define WEP_SMALL_KEY_LEN                      (40/8)
+#define WEP_LARGE_KEY_LEN                      (104/8)
+
+#define GROUP_KEY_NO                4
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E)               iwe_stream_add_event(_A, _B, _C, _D, _E)
+#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E)               iwe_stream_add_point(_A, _B, _C, _D, _E)
+#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F)   iwe_stream_add_value(_A, _B, _C, _D, _E, _F)
+#else
+#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E)               iwe_stream_add_event(_B, _C, _D, _E)
+#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E)               iwe_stream_add_point(_B, _C, _D, _E)
+#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F)   iwe_stream_add_value(_B, _C, _D, _E, _F)
+#endif
+
+extern UCHAR    CipherWpa2Template[];
+extern UCHAR    CipherWpaPskTkip[];
+extern UCHAR    CipherWpaPskTkipLen;
+
+typedef struct PACKED _RT_VERSION_INFO{
+    UCHAR       DriverVersionW;
+    UCHAR       DriverVersionX;
+    UCHAR       DriverVersionY;
+    UCHAR       DriverVersionZ;
+    UINT        DriverBuildYear;
+    UINT        DriverBuildMonth;
+    UINT        DriverBuildDay;
+} RT_VERSION_INFO, *PRT_VERSION_INFO;
+
+struct iw_priv_args privtab[] = {
+{ RTPRIV_IOCTL_SET,
+  IW_PRIV_TYPE_CHAR | 1024, 0,
+  "set"},
+
+{ RTPRIV_IOCTL_SHOW, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  ""},
+{ RTPRIV_IOCTL_SHOW, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  ""},
+/* --- sub-ioctls definitions --- */
+    { SHOW_CONN_STATUS,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "connStatus" },
+       { SHOW_DRVIER_VERION,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "driverVer" },
+    { SHOW_BA_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "bainfo" },
+       { SHOW_DESC_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "descinfo" },
+    { RAIO_OFF,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_off" },
+       { RAIO_ON,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_on" },
+#ifdef QOS_DLS_SUPPORT
+       { SHOW_DLS_ENTRY_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "dlsentryinfo" },
+#endif // QOS_DLS_SUPPORT //
+       { SHOW_CFG_VALUE,
+         IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "show" },
+       { SHOW_ADHOC_ENTRY_INFO,
+         0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "adhocEntry" },
+
+/* --- sub-ioctls relations --- */
+
+#ifdef DBG
+{ RTPRIV_IOCTL_BBP,
+  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  "bbp"},
+{ RTPRIV_IOCTL_MAC,
+  IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024,
+  "mac"},
+{ RTPRIV_IOCTL_E2P,
+  IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024,
+  "e2p"},
+#endif  /* DBG */
+
+{ RTPRIV_IOCTL_STATISTICS,
+  0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK,
+  "stat"},
+{ RTPRIV_IOCTL_GSITESURVEY,
+  0, IW_PRIV_TYPE_CHAR | 1024,
+  "get_site_survey"},
+};
+
+INT Set_SSID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+#ifdef WMM_SUPPORT
+INT    Set_WmmCapable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif
+
+INT Set_NetworkType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_AuthMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_EncrypType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_DefaultKeyID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key1_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key2_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key3_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_Key4_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+INT Set_WPAPSK_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+
+INT Set_PSMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+INT Set_Wpa_Support(
+    IN PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg);
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef DBG
+VOID RTMPIoctlBBP(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq);
+
+VOID RTMPIoctlMAC(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq);
+
+VOID RTMPIoctlE2PROM(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  struct iwreq    *wrq);
+#endif // DBG //
+
+
+NDIS_STATUS RTMPWPANoneAddKeyProc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN PVOID                   pBuf);
+
+INT Set_FragTest_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+
+#ifdef DOT11_N_SUPPORT
+INT Set_TGnWifiTest_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg);
+#endif // DOT11_N_SUPPORT //
+
+INT Set_LongRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg);
+
+INT Set_ShortRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg);
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+INT Set_Ieee80211dClientMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg);
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+#ifdef CARRIER_DETECTION_SUPPORT
+INT Set_CarrierDetect_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg);
+#endif // CARRIER_DETECTION_SUPPORT //
+
+INT    Show_Adhoc_MacTable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PCHAR                   extra);
+
+static struct {
+       CHAR *name;
+       INT (*set_proc)(PRTMP_ADAPTER pAdapter, PUCHAR arg);
+} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = {
+       {"DriverVersion",                               Set_DriverVersion_Proc},
+       {"CountryRegion",                               Set_CountryRegion_Proc},
+       {"CountryRegionABand",                  Set_CountryRegionABand_Proc},
+       {"SSID",                                                Set_SSID_Proc},
+       {"WirelessMode",                                Set_WirelessMode_Proc},
+       {"TxBurst",                                     Set_TxBurst_Proc},
+       {"TxPreamble",                          Set_TxPreamble_Proc},
+       {"TxPower",                                     Set_TxPower_Proc},
+       {"Channel",                                     Set_Channel_Proc},
+       {"BGProtection",                                Set_BGProtection_Proc},
+       {"RTSThreshold",                                Set_RTSThreshold_Proc},
+       {"FragThreshold",                               Set_FragThreshold_Proc},
+#ifdef DOT11_N_SUPPORT
+       {"HtBw",                                Set_HtBw_Proc},
+       {"HtMcs",                               Set_HtMcs_Proc},
+       {"HtGi",                                Set_HtGi_Proc},
+       {"HtOpMode",                        Set_HtOpMode_Proc},
+       {"HtExtcha",                        Set_HtExtcha_Proc},
+       {"HtMpduDensity",                       Set_HtMpduDensity_Proc},
+       {"HtBaWinSize",                         Set_HtBaWinSize_Proc},
+       {"HtRdg",                                       Set_HtRdg_Proc},
+       {"HtAmsdu",                                     Set_HtAmsdu_Proc},
+       {"HtAutoBa",                            Set_HtAutoBa_Proc},
+       {"HtBaDecline",                                 Set_BADecline_Proc},
+       {"HtProtect",                           Set_HtProtect_Proc},
+       {"HtMimoPs",                            Set_HtMimoPs_Proc},
+#endif // DOT11_N_SUPPORT //
+
+#ifdef AGGREGATION_SUPPORT
+       {"PktAggregate",                                Set_PktAggregate_Proc},
+#endif
+
+#ifdef WMM_SUPPORT
+       {"WmmCapable",                                  Set_WmmCapable_Proc},
+#endif
+       {"IEEE80211H",                                  Set_IEEE80211H_Proc},
+    {"NetworkType",                 Set_NetworkType_Proc},
+       {"AuthMode",                                    Set_AuthMode_Proc},
+       {"EncrypType",                                  Set_EncrypType_Proc},
+       {"DefaultKeyID",                                Set_DefaultKeyID_Proc},
+       {"Key1",                                                Set_Key1_Proc},
+       {"Key2",                                                Set_Key2_Proc},
+       {"Key3",                                                Set_Key3_Proc},
+       {"Key4",                                                Set_Key4_Proc},
+       {"WPAPSK",                                              Set_WPAPSK_Proc},
+       {"ResetCounter",                                Set_ResetStatCounter_Proc},
+       {"PSMode",                      Set_PSMode_Proc},
+#ifdef DBG
+       {"Debug",                                               Set_Debug_Proc},
+#endif
+
+#ifdef RALINK_ATE
+       {"ATE",                                                 Set_ATE_Proc},
+       {"ATEDA",                                               Set_ATE_DA_Proc},
+       {"ATESA",                                               Set_ATE_SA_Proc},
+       {"ATEBSSID",                                    Set_ATE_BSSID_Proc},
+       {"ATECHANNEL",                                  Set_ATE_CHANNEL_Proc},
+       {"ATETXPOW0",                                   Set_ATE_TX_POWER0_Proc},
+       {"ATETXPOW1",                                   Set_ATE_TX_POWER1_Proc},
+       {"ATETXANT",                                    Set_ATE_TX_Antenna_Proc},
+       {"ATERXANT",                                    Set_ATE_RX_Antenna_Proc},
+       {"ATETXFREQOFFSET",                             Set_ATE_TX_FREQOFFSET_Proc},
+       {"ATETXBW",                                             Set_ATE_TX_BW_Proc},
+       {"ATETXLEN",                                    Set_ATE_TX_LENGTH_Proc},
+       {"ATETXCNT",                                    Set_ATE_TX_COUNT_Proc},
+       {"ATETXMCS",                                    Set_ATE_TX_MCS_Proc},
+       {"ATETXMODE",                                   Set_ATE_TX_MODE_Proc},
+       {"ATETXGI",                                             Set_ATE_TX_GI_Proc},
+       {"ATERXFER",                                    Set_ATE_RX_FER_Proc},
+       {"ATERRF",                                              Set_ATE_Read_RF_Proc},
+       {"ATEWRF1",                                             Set_ATE_Write_RF1_Proc},
+       {"ATEWRF2",                                             Set_ATE_Write_RF2_Proc},
+       {"ATEWRF3",                                             Set_ATE_Write_RF3_Proc},
+       {"ATEWRF4",                                             Set_ATE_Write_RF4_Proc},
+       {"ATELDE2P",                                Set_ATE_Load_E2P_Proc},
+       {"ATERE2P",                                             Set_ATE_Read_E2P_Proc},
+       {"ATESHOW",                                             Set_ATE_Show_Proc},
+       {"ATEHELP",                                             Set_ATE_Help_Proc},
+
+#ifdef RALINK_28xx_QA
+       {"TxStop",                                              Set_TxStop_Proc},
+       {"RxStop",                                              Set_RxStop_Proc},
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+    {"WpaSupport",                  Set_Wpa_Support},
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+
+
+       {"FixedTxMode",                 Set_FixedTxMode_Proc},
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+       {"OpMode",                                              Set_OpMode_Proc},
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+#ifdef DOT11_N_SUPPORT
+    {"TGnWifiTest",                 Set_TGnWifiTest_Proc},
+    {"ForceGF",                                        Set_ForceGF_Proc},
+#endif // DOT11_N_SUPPORT //
+#ifdef QOS_DLS_SUPPORT
+       {"DlsAddEntry",                                 Set_DlsAddEntry_Proc},
+       {"DlsTearDownEntry",                    Set_DlsTearDownEntry_Proc},
+#endif // QOS_DLS_SUPPORT //
+       {"LongRetry",                           Set_LongRetryLimit_Proc},
+       {"ShortRetry",                          Set_ShortRetryLimit_Proc},
+#ifdef EXT_BUILD_CHANNEL_LIST
+       {"11dClientMode",                               Set_Ieee80211dClientMode_Proc},
+#endif // EXT_BUILD_CHANNEL_LIST //
+#ifdef CARRIER_DETECTION_SUPPORT
+       {"CarrierDetect",                               Set_CarrierDetect_Proc},
+#endif // CARRIER_DETECTION_SUPPORT //
+
+       {NULL,}
+};
+
+
+VOID RTMPAddKey(
+       IN      PRTMP_ADAPTER       pAd,
+       IN      PNDIS_802_11_KEY    pKey)
+{
+       ULONG                           KeyIdx;
+       MAC_TABLE_ENTRY         *pEntry;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey ------>\n"));
+
+       if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+       {
+               if (pKey->KeyIndex & 0x80000000)
+               {
+                   if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+            {
+                NdisZeroMemory(pAd->StaCfg.PMK, 32);
+                NdisMoveMemory(pAd->StaCfg.PMK, pKey->KeyMaterial, pKey->KeyLength);
+                goto end;
+            }
+                   // Update PTK
+                   NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
+            pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
+            NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pKey->KeyMaterial, LEN_TKIP_EK);
+#ifdef WPA_SUPPLICANT_SUPPORT
+            if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+            {
+                NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+            else
+#endif // WPA_SUPPLICANT_SUPPORT //
+            {
+               NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+
+            // Decide its ChiperAlg
+               if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+                       pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
+               else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
+                       pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
+               else
+                       pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE;
+
+            // Update these related information to MAC_TABLE_ENTRY
+               pEntry = &pAd->MacTab.Content[BSSID_WCID];
+            NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[BSS0][0].Key, LEN_TKIP_EK);
+               NdisMoveMemory(pEntry->PairwiseKey.RxMic, pAd->SharedKey[BSS0][0].RxMic, LEN_TKIP_RXMICK);
+               NdisMoveMemory(pEntry->PairwiseKey.TxMic, pAd->SharedKey[BSS0][0].TxMic, LEN_TKIP_TXMICK);
+               pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
+
+               // Update pairwise key information to ASIC Shared Key Table
+               AsicAddSharedKeyEntry(pAd,
+                                                         BSS0,
+                                                         0,
+                                                         pAd->SharedKey[BSS0][0].CipherAlg,
+                                                         pAd->SharedKey[BSS0][0].Key,
+                                                         pAd->SharedKey[BSS0][0].TxMic,
+                                                         pAd->SharedKey[BSS0][0].RxMic);
+
+               // Update ASIC WCID attribute table and IVEIV table
+               RTMPAddWcidAttributeEntry(pAd,
+                                                                 BSS0,
+                                                                 0,
+                                                                 pAd->SharedKey[BSS0][0].CipherAlg,
+                                                                 pEntry);
+
+            if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2)
+            {
+                // set 802.1x port control
+                   //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               STA_PORT_SECURED(pAd);
+
+                // Indicate Connected for GUI
+                pAd->IndicateMediaState = NdisMediaStateConnected;
+            }
+               }
+        else
+        {
+            // Update GTK
+            pAd->StaCfg.DefaultKeyId = (pKey->KeyIndex & 0xFF);
+            NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY));
+            pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK;
+            NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKey->KeyMaterial, LEN_TKIP_EK);
+#ifdef WPA_SUPPLICANT_SUPPORT
+            if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
+            {
+                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+            else
+#endif // WPA_SUPPLICANT_SUPPORT //
+            {
+               NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+            }
+
+            // Update Shared Key CipherAlg
+               pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE;
+               if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP;
+               else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
+                       pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES;
+
+            // Update group key information to ASIC Shared Key Table
+               AsicAddSharedKeyEntry(pAd,
+                                                         BSS0,
+                                                         pAd->StaCfg.DefaultKeyId,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic,
+                                                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic);
+
+               // Update ASIC WCID attribute table and IVEIV table
+               RTMPAddWcidAttributeEntry(pAd,
+                                                                 BSS0,
+                                                                 pAd->StaCfg.DefaultKeyId,
+                                                                 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+                                                                 NULL);
+
+            // set 802.1x port control
+               //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAd);
+
+            // Indicate Connected for GUI
+            pAd->IndicateMediaState = NdisMediaStateConnected;
+        }
+       }
+       else    // dynamic WEP from wpa_supplicant
+       {
+               UCHAR   CipherAlg;
+       PUCHAR  Key;
+
+               if(pKey->KeyLength == 32)
+                       goto end;
+
+               KeyIdx = pKey->KeyIndex & 0x0fffffff;
+
+               if (KeyIdx < 4)
+               {
+                       // it is a default shared key, for Pairwise key setting
+                       if (pKey->KeyIndex & 0x80000000)
+                       {
+                               pEntry = MacTableLookup(pAd, pKey->BSSID);
+
+                               if (pEntry)
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey: Set Pair-wise Key\n"));
+
+                                       // set key material and key length
+                                       pEntry->PairwiseKey.KeyLen = (UCHAR)pKey->KeyLength;
+                                       NdisMoveMemory(pEntry->PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength);
+
+                                       // set Cipher type
+                                       if (pKey->KeyLength == 5)
+                                               pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64;
+                                       else
+                                               pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128;
+
+                                       // Add Pair-wise key to Asic
+                                       AsicAddPairwiseKeyEntry(
+                                               pAd,
+                                               pEntry->Addr,
+                                               (UCHAR)pEntry->Aid,
+                               &pEntry->PairwiseKey);
+
+                                       // update WCID attribute table and IVEIV table for this entry
+                                       RTMPAddWcidAttributeEntry(
+                                               pAd,
+                                               BSS0,
+                                               KeyIdx, // The value may be not zero
+                                               pEntry->PairwiseKey.CipherAlg,
+                                               pEntry);
+
+                               }
+                       }
+                       else
+            {
+                               // Default key for tx (shared key)
+                               pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx;
+
+                               // set key material and key length
+                               pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pKey->KeyLength;
+                               NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength);
+
+                               // Set Ciper type
+                               if (pKey->KeyLength == 5)
+                                       pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP64;
+                               else
+                                       pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP128;
+
+                       CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
+                       Key = pAd->SharedKey[BSS0][KeyIdx].Key;
+
+                               // Set Group key material to Asic
+                       AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL);
+
+                               // Update WCID attribute table and IVEIV table for this group key table
+                               RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, CipherAlg, NULL);
+
+                       }
+               }
+       }
+end:
+       return;
+}
+
+char * rtstrchr(const char * s, int c)
+{
+    for(; *s != (char) c; ++s)
+        if (*s == '\0')
+            return NULL;
+    return (char *) s;
+}
+
+/*
+This is required for LinEX2004/kernel2.6.7 to provide iwlist scanning function
+*/
+
+int
+rt_ioctl_giwname(struct net_device *dev,
+                  struct iw_request_info *info,
+                  char *name, char *extra)
+{
+//     PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+#ifdef RT2870
+       strncpy(name, "RT2870 Wireless", IFNAMSIZ);
+#endif // RT2870 //
+       return 0;
+}
+
+int rt_ioctl_siwfreq(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_freq *freq, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       int     chan = -1;
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+        return -ENETDOWN;
+    }
+
+
+       if (freq->e > 1)
+               return -EINVAL;
+
+       if((freq->e == 0) && (freq->m <= 1000))
+               chan = freq->m; // Setting by channel number
+       else
+               MAP_KHZ_TO_CHANNEL_ID( (freq->m /100) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G,
+
+    if (ChannelSanity(pAdapter, chan) == TRUE)
+    {
+       pAdapter->CommonCfg.Channel = chan;
+       DBGPRINT(RT_DEBUG_ERROR, ("==>rt_ioctl_siwfreq::SIOCSIWFREQ[cmd=0x%x] (Channel=%d)\n", SIOCSIWFREQ, pAdapter->CommonCfg.Channel));
+    }
+    else
+        return -EINVAL;
+
+       return 0;
+}
+int rt_ioctl_giwfreq(struct net_device *dev,
+                  struct iw_request_info *info,
+                  struct iw_freq *freq, char *extra)
+{
+    VIRTUAL_ADAPTER *pVirtualAd = NULL;
+       PRTMP_ADAPTER pAdapter = NULL;
+       UCHAR ch;
+       ULONG   m;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+               ch = pAdapter->CommonCfg.Channel;
+
+       DBGPRINT(RT_DEBUG_TRACE,("==>rt_ioctl_giwfreq  %d\n", ch));
+
+    MAP_CHANNEL_ID_TO_KHZ(ch, m);
+       freq->m = m * 100;
+       freq->e = 1;
+       return 0;
+}
+
+int rt_ioctl_siwmode(struct net_device *dev,
+                  struct iw_request_info *info,
+                  __u32 *mode, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+       DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+    }
+
+       switch (*mode)
+       {
+               case IW_MODE_ADHOC:
+                       Set_NetworkType_Proc(pAdapter, "Adhoc");
+                       break;
+               case IW_MODE_INFRA:
+                       Set_NetworkType_Proc(pAdapter, "Infra");
+                       break;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
+        case IW_MODE_MONITOR:
+                       Set_NetworkType_Proc(pAdapter, "Monitor");
+                       break;
+#endif
+               default:
+                       DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_siwmode::SIOCSIWMODE (unknown %d)\n", *mode));
+                       return -EINVAL;
+       }
+
+       // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key
+       pAdapter->StaCfg.WpaState = SS_NOTUSE;
+
+       return 0;
+}
+
+int rt_ioctl_giwmode(struct net_device *dev,
+                  struct iw_request_info *info,
+                  __u32 *mode, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       if (ADHOC_ON(pAdapter))
+               *mode = IW_MODE_ADHOC;
+    else if (INFRA_ON(pAdapter))
+               *mode = IW_MODE_INFRA;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
+    else if (MONITOR_ON(pAdapter))
+    {
+        *mode = IW_MODE_MONITOR;
+    }
+#endif
+    else
+        *mode = IW_MODE_AUTO;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("==>rt_ioctl_giwmode(mode=%d)\n", *mode));
+       return 0;
+}
+
+int rt_ioctl_siwsens(struct net_device *dev,
+                  struct iw_request_info *info,
+                  char *name, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       return 0;
+}
+
+int rt_ioctl_giwsens(struct net_device *dev,
+                  struct iw_request_info *info,
+                  char *name, char *extra)
+{
+       return 0;
+}
+
+int rt_ioctl_giwrange(struct net_device *dev,
+                  struct iw_request_info *info,
+                  struct iw_point *data, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+       struct iw_range *range = (struct iw_range *) extra;
+       u16 val;
+       int i;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE ,("===>rt_ioctl_giwrange\n"));
+       data->length = sizeof(struct iw_range);
+       memset(range, 0, sizeof(struct iw_range));
+
+       range->txpower_capa = IW_TXPOW_DBM;
+
+       if (INFRA_ON(pAdapter)||ADHOC_ON(pAdapter))
+       {
+               range->min_pmp = 1 * 1024;
+               range->max_pmp = 65535 * 1024;
+               range->min_pmt = 1 * 1024;
+               range->max_pmt = 1000 * 1024;
+               range->pmp_flags = IW_POWER_PERIOD;
+               range->pmt_flags = IW_POWER_TIMEOUT;
+               range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT |
+                       IW_POWER_UNICAST_R | IW_POWER_ALL_R;
+       }
+
+       range->we_version_compiled = WIRELESS_EXT;
+       range->we_version_source = 14;
+
+       range->retry_capa = IW_RETRY_LIMIT;
+       range->retry_flags = IW_RETRY_LIMIT;
+       range->min_retry = 0;
+       range->max_retry = 255;
+
+       range->num_channels =  pAdapter->ChannelListNum;
+
+       val = 0;
+       for (i = 1; i <= range->num_channels; i++)
+       {
+               u32 m;
+               range->freq[val].i = pAdapter->ChannelList[i-1].Channel;
+               MAP_CHANNEL_ID_TO_KHZ(pAdapter->ChannelList[i-1].Channel, m);
+               range->freq[val].m = m * 100; /* HZ */
+
+               range->freq[val].e = 1;
+               val++;
+               if (val == IW_MAX_FREQUENCIES)
+                       break;
+       }
+       range->num_frequency = val;
+
+       range->max_qual.qual = 100; /* what is correct max? This was not
+                                       * documented exactly. At least
+                                       * 69 has been observed. */
+       range->max_qual.level = 0; /* dB */
+       range->max_qual.noise = 0; /* dB */
+
+       /* What would be suitable values for "average/typical" qual? */
+       range->avg_qual.qual = 20;
+       range->avg_qual.level = -60;
+       range->avg_qual.noise = -95;
+       range->sensitivity = 3;
+
+       range->max_encoding_tokens = NR_WEP_KEYS;
+       range->num_encoding_sizes = 2;
+       range->encoding_size[0] = 5;
+       range->encoding_size[1] = 13;
+
+       range->min_rts = 0;
+       range->max_rts = 2347;
+       range->min_frag = 256;
+       range->max_frag = 2346;
+
+#if WIRELESS_EXT > 17
+       /* IW_ENC_CAPA_* bit field */
+       range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+                                       IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+#endif
+
+       return 0;
+}
+
+int rt_ioctl_siwap(struct net_device *dev,
+                     struct iw_request_info *info,
+                     struct sockaddr *ap_addr, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+    NDIS_802_11_MAC_ADDRESS Bssid;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+    }
+
+       if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+    {
+        RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+        DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+    }
+
+    // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+    // this request, because this request is initiated by NDIS.
+    pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+       // Prevent to connect AP again in STAMlmePeriodicExec
+       pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+
+    memset(Bssid, 0, MAC_ADDR_LEN);
+    memcpy(Bssid, ap_addr->sa_data, MAC_ADDR_LEN);
+    MlmeEnqueue(pAdapter,
+                MLME_CNTL_STATE_MACHINE,
+                OID_802_11_BSSID,
+                sizeof(NDIS_802_11_MAC_ADDRESS),
+                (VOID *)&Bssid);
+
+    DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCSIWAP %02x:%02x:%02x:%02x:%02x:%02x\n",
+        Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
+
+       return 0;
+}
+
+int rt_ioctl_giwap(struct net_device *dev,
+                     struct iw_request_info *info,
+                     struct sockaddr *ap_addr, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
+       {
+               ap_addr->sa_family = ARPHRD_ETHER;
+               memcpy(ap_addr->sa_data, &pAdapter->CommonCfg.Bssid, ETH_ALEN);
+       }
+#ifdef WPA_SUPPLICANT_SUPPORT
+    // Add for RT2870
+    else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+    {
+        ap_addr->sa_family = ARPHRD_ETHER;
+        memcpy(ap_addr->sa_data, &pAdapter->MlmeAux.Bssid, ETH_ALEN);
+    }
+#endif // WPA_SUPPLICANT_SUPPORT //
+       else
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=EMPTY)\n"));
+               return -ENOTCONN;
+       }
+
+       return 0;
+}
+
+/*
+ * Units are in db above the noise floor. That means the
+ * rssi values reported in the tx/rx descriptors in the
+ * driver are the SNR expressed in db.
+ *
+ * If you assume that the noise floor is -95, which is an
+ * excellent assumption 99.5 % of the time, then you can
+ * derive the absolute signal level (i.e. -95 + rssi).
+ * There are some other slight factors to take into account
+ * depending on whether the rssi measurement is from 11b,
+ * 11g, or 11a.   These differences are at most 2db and
+ * can be documented.
+ *
+ * NB: various calculations are based on the orinoco/wavelan
+ *     drivers for compatibility
+ */
+static void set_quality(PRTMP_ADAPTER pAdapter,
+                        struct iw_quality *iq,
+                        signed char rssi)
+{
+       __u8 ChannelQuality;
+
+       // Normalize Rssi
+       if (rssi >= -50)
+               ChannelQuality = 100;
+       else if (rssi >= -80) // between -50 ~ -80dbm
+               ChannelQuality = (__u8)(24 + ((rssi + 80) * 26)/10);
+       else if (rssi >= -90)   // between -80 ~ -90dbm
+        ChannelQuality = (__u8)((rssi + 90) * 26)/10;
+       else
+               ChannelQuality = 0;
+
+    iq->qual = (__u8)ChannelQuality;
+
+    iq->level = (__u8)(rssi);
+    iq->noise = (pAdapter->BbpWriteLatch[66] > pAdapter->BbpTuning.FalseCcaUpperThreshold) ? ((__u8)pAdapter->BbpTuning.FalseCcaUpperThreshold) : ((__u8) pAdapter->BbpWriteLatch[66]);        // noise level (dBm)
+    iq->noise += 256 - 143;
+    iq->updated = pAdapter->iw_stats.qual.updated;
+}
+
+int rt_ioctl_iwaplist(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_point *data, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       struct sockaddr addr[IW_MAX_AP];
+       struct iw_quality qual[IW_MAX_AP];
+       int i;
+
+       //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               data->length = 0;
+               return 0;
+        //return -ENETDOWN;
+       }
+
+       for (i = 0; i <IW_MAX_AP ; i++)
+       {
+               if (i >=  pAdapter->ScanTab.BssNr)
+                       break;
+               addr[i].sa_family = ARPHRD_ETHER;
+                       memcpy(addr[i].sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN);
+               set_quality(pAdapter, &qual[i], pAdapter->ScanTab.BssEntry[i].Rssi);
+       }
+       data->length = i;
+       memcpy(extra, &addr, i*sizeof(addr[0]));
+       data->flags = 1;                /* signal quality present (sort of) */
+       memcpy(extra + i*sizeof(addr[0]), &qual, i*sizeof(qual[i]));
+
+       return 0;
+}
+
+#ifdef SIOCGIWSCAN
+int rt_ioctl_siwscan(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_point *data, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       ULONG                                                           Now;
+       int Status = NDIS_STATUS_SUCCESS;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       if (MONITOR_ON(pAdapter))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n"));
+        return -EINVAL;
+    }
+
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+       if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE)
+       {
+               pAdapter->StaCfg.WpaSupplicantScanCount++;
+       }
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+    pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE;
+       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+               return 0;
+       do{
+               Now = jiffies;
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+               if ((pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) &&
+                       (pAdapter->StaCfg.WpaSupplicantScanCount > 3))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!! WpaSupplicantScanCount > 3\n"));
+                       Status = NDIS_STATUS_SUCCESS;
+                       break;
+               }
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+               if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) &&
+                       ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+                       (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) &&
+                       (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+               {
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n"));
+                       Status = NDIS_STATUS_SUCCESS;
+                       break;
+               }
+
+               if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+               {
+                       RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                       DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+               }
+
+               // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+               // this request, because this request is initiated by NDIS.
+               pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+               // Reset allowed scan retries
+               pAdapter->StaCfg.ScanCnt = 0;
+               pAdapter->StaCfg.LastScanTime = Now;
+
+               MlmeEnqueue(pAdapter,
+                       MLME_CNTL_STATE_MACHINE,
+                       OID_802_11_BSSID_LIST_SCAN,
+                       0,
+                       NULL);
+
+               Status = NDIS_STATUS_SUCCESS;
+               RT28XX_MLME_HANDLER(pAdapter);
+       }while(0);
+       return 0;
+}
+
+int rt_ioctl_giwscan(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_point *data, char *extra)
+{
+
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       int i=0;
+       char *current_ev = extra, *previous_ev = extra;
+       char *end_buf;
+       char *current_val, custom[MAX_CUSTOM_LEN] = {0};
+#ifndef IWEVGENIE
+       char idx;
+#endif // IWEVGENIE //
+       struct iw_event iwe;
+
+       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+    {
+               /*
+                * Still scanning, indicate the caller should try again.
+                */
+               return -EAGAIN;
+       }
+
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+       if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE)
+       {
+               pAdapter->StaCfg.WpaSupplicantScanCount = 0;
+       }
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+       if (pAdapter->ScanTab.BssNr == 0)
+       {
+               data->length = 0;
+               return 0;
+       }
+
+#if WIRELESS_EXT >= 17
+    if (data->length > 0)
+        end_buf = extra + data->length;
+    else
+        end_buf = extra + IW_SCAN_MAX_DATA;
+#else
+    end_buf = extra + IW_SCAN_MAX_DATA;
+#endif
+
+       for (i = 0; i < pAdapter->ScanTab.BssNr; i++)
+       {
+               if (current_ev >= end_buf)
+        {
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+        }
+
+               //MAC address
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWAP;
+               iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+                               memcpy(iwe.u.ap_addr.sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, ETH_ALEN);
+
+        previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //ESSID
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWESSID;
+               iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].SsidLen;
+               iwe.u.data.flags = 1;
+
+        previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_POINT(info, current_ev,end_buf, &iwe, pAdapter->ScanTab.BssEntry[i].Ssid);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Network Type
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWMODE;
+               if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11IBSS)
+               {
+                       iwe.u.mode = IW_MODE_ADHOC;
+               }
+               else if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11Infrastructure)
+               {
+                       iwe.u.mode = IW_MODE_INFRA;
+               }
+               else
+               {
+                       iwe.u.mode = IW_MODE_AUTO;
+               }
+               iwe.len = IW_EV_UINT_LEN;
+
+        previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe,  IW_EV_UINT_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Channel and Frequency
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWFREQ;
+               if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
+                       iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
+               else
+                       iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
+               iwe.u.freq.e = 0;
+               iwe.u.freq.i = 0;
+
+               previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+        //Add quality statistics
+        //================================
+        memset(&iwe, 0, sizeof(iwe));
+       iwe.cmd = IWEVQUAL;
+       iwe.u.qual.level = 0;
+       iwe.u.qual.noise = 0;
+        set_quality(pAdapter, &iwe.u.qual, pAdapter->ScanTab.BssEntry[i].Rssi);
+       current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Encyption key
+               //================================
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWENCODE;
+               if (CAP_IS_PRIVACY_ON (pAdapter->ScanTab.BssEntry[i].CapabilityInfo ))
+                       iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+               else
+                       iwe.u.data.flags = IW_ENCODE_DISABLED;
+
+        previous_ev = current_ev;
+        current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,&iwe, (char *)pAdapter->SharedKey[BSS0][(iwe.u.data.flags & IW_ENCODE_INDEX)-1].Key);
+        if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+            return -E2BIG;
+#else
+                       break;
+#endif
+
+               //Bit Rate
+               //================================
+               if (pAdapter->ScanTab.BssEntry[i].SupRateLen)
+        {
+            UCHAR tmpRate = pAdapter->ScanTab.BssEntry[i].SupRate[pAdapter->ScanTab.BssEntry[i].SupRateLen-1];
+                       memset(&iwe, 0, sizeof(iwe));
+                       iwe.cmd = SIOCGIWRATE;
+               current_val = current_ev + IW_EV_LCP_LEN;
+            if (tmpRate == 0x82)
+                iwe.u.bitrate.value =  1 * 1000000;
+            else if (tmpRate == 0x84)
+                iwe.u.bitrate.value =  2 * 1000000;
+            else if (tmpRate == 0x8B)
+                iwe.u.bitrate.value =  5.5 * 1000000;
+            else if (tmpRate == 0x96)
+                iwe.u.bitrate.value =  11 * 1000000;
+            else
+                   iwe.u.bitrate.value =  (tmpRate/2) * 1000000;
+
+                       iwe.u.bitrate.disabled = 0;
+                       current_val = IWE_STREAM_ADD_VALUE(info, current_ev,
+                               current_val, end_buf, &iwe,
+                       IW_EV_PARAM_LEN);
+
+               if((current_val-current_ev)>IW_EV_LCP_LEN)
+               current_ev = current_val;
+               else
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+
+#ifdef IWEVGENIE
+               //WPA IE
+               if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0)
+               {
+                       memset(&iwe, 0, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+                       memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].WpaIE.IE[0]),
+                                                  pAdapter->ScanTab.BssEntry[i].WpaIE.IELen);
+                       iwe.cmd = IWEVGENIE;
+                       iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].WpaIE.IELen;
+                       current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom);
+                       if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+               }
+
+               //WPA2 IE
+        if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0)
+        {
+               memset(&iwe, 0, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+                       memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].RsnIE.IE[0]),
+                                                  pAdapter->ScanTab.BssEntry[i].RsnIE.IELen);
+                       iwe.cmd = IWEVGENIE;
+                       iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].RsnIE.IELen;
+                       current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom);
+                       if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+#else
+        //WPA IE
+               //================================
+        if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0)
+        {
+               NdisZeroMemory(&iwe, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+               iwe.cmd = IWEVCUSTOM;
+            iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen * 2) + 7;
+            NdisMoveMemory(custom, "wpa_ie=", 7);
+            for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].WpaIE.IELen; idx++)
+                sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].WpaIE.IE[idx]);
+            previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe,  custom);
+            if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+
+        //WPA2 IE
+        if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0)
+        {
+               NdisZeroMemory(&iwe, sizeof(iwe));
+                       memset(&custom[0], 0, MAX_CUSTOM_LEN);
+               iwe.cmd = IWEVCUSTOM;
+            iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen * 2) + 7;
+            NdisMoveMemory(custom, "rsn_ie=", 7);
+                       for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].RsnIE.IELen; idx++)
+                sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].RsnIE.IE[idx]);
+            previous_ev = current_ev;
+               current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe,  custom);
+            if (current_ev == previous_ev)
+#if WIRELESS_EXT >= 17
+                return -E2BIG;
+#else
+                           break;
+#endif
+        }
+#endif // IWEVGENIE //
+       }
+
+       data->length = current_ev - extra;
+    pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE;
+       DBGPRINT(RT_DEBUG_ERROR ,("===>rt_ioctl_giwscan. %d(%d) BSS returned, data->length = %d\n",i , pAdapter->ScanTab.BssNr, data->length));
+       return 0;
+}
+#endif
+
+int rt_ioctl_siwessid(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *essid)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+    }
+
+       if (data->flags)
+       {
+               PCHAR   pSsidString = NULL;
+
+               // Includes null character.
+               if (data->length > (IW_ESSID_MAX_SIZE + 1))
+                       return -E2BIG;
+
+               pSsidString = (CHAR *) kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG);
+               if (pSsidString)
+               {
+                       NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1);
+                       NdisMoveMemory(pSsidString, essid, data->length);
+                       if (Set_SSID_Proc(pAdapter, pSsidString) == FALSE)
+                               return -EINVAL;
+               }
+               else
+                       return -ENOMEM;
+       }
+       else
+       {
+               // ANY ssid
+               if (Set_SSID_Proc(pAdapter, "") == FALSE)
+                       return -EINVAL;
+    }
+       return 0;
+}
+
+int rt_ioctl_giwessid(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *essid)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       data->flags = 1;
+    if (MONITOR_ON(pAdapter))
+    {
+        data->length  = 0;
+        return 0;
+    }
+
+       if (OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED))
+       {
+               DBGPRINT(RT_DEBUG_TRACE ,("MediaState is connected\n"));
+               data->length = pAdapter->CommonCfg.SsidLen;
+               memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen);
+       }
+#ifdef RT2870
+#ifdef WPA_SUPPLICANT_SUPPORT
+    // Add for RT2870
+    else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+    {
+        data->length = pAdapter->CommonCfg.SsidLen;
+               memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen);
+       }
+#endif // WPA_SUPPLICANT_SUPPORT //
+#endif // RT2870 //
+       else
+       {//the ANY ssid was specified
+               data->length  = 0;
+               DBGPRINT(RT_DEBUG_TRACE ,("MediaState is not connected, ess\n"));
+       }
+
+       return 0;
+
+}
+
+int rt_ioctl_siwnickn(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *nickname)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+        DBGPRINT(RT_DEBUG_TRACE ,("INFO::Network is down!\n"));
+        return -ENETDOWN;
+    }
+
+       if (data->length > IW_ESSID_MAX_SIZE)
+               return -EINVAL;
+
+       memset(pAdapter->nickname, 0, IW_ESSID_MAX_SIZE + 1);
+       memcpy(pAdapter->nickname, nickname, data->length);
+
+
+       return 0;
+}
+
+int rt_ioctl_giwnickn(struct net_device *dev,
+                        struct iw_request_info *info,
+                        struct iw_point *data, char *nickname)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       if (data->length > strlen(pAdapter->nickname) + 1)
+               data->length = strlen(pAdapter->nickname) + 1;
+       if (data->length > 0) {
+               memcpy(nickname, pAdapter->nickname, data->length-1);
+               nickname[data->length-1] = '\0';
+       }
+       return 0;
+}
+
+int rt_ioctl_siwrts(struct net_device *dev,
+                      struct iw_request_info *info,
+                      struct iw_param *rts, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       u16 val;
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+        return -ENETDOWN;
+    }
+
+       if (rts->disabled)
+               val = MAX_RTS_THRESHOLD;
+       else if (rts->value < 0 || rts->value > MAX_RTS_THRESHOLD)
+               return -EINVAL;
+       else if (rts->value == 0)
+           val = MAX_RTS_THRESHOLD;
+       else
+               val = rts->value;
+
+       if (val != pAdapter->CommonCfg.RtsThreshold)
+               pAdapter->CommonCfg.RtsThreshold = val;
+
+       return 0;
+}
+
+int rt_ioctl_giwrts(struct net_device *dev,
+                      struct iw_request_info *info,
+                      struct iw_param *rts, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+       rts->value = pAdapter->CommonCfg.RtsThreshold;
+       rts->disabled = (rts->value == MAX_RTS_THRESHOLD);
+       rts->fixed = 1;
+
+       return 0;
+}
+
+int rt_ioctl_siwfrag(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_param *frag, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+       u16 val;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       if (frag->disabled)
+               val = MAX_FRAG_THRESHOLD;
+       else if (frag->value >= MIN_FRAG_THRESHOLD || frag->value <= MAX_FRAG_THRESHOLD)
+        val = __cpu_to_le16(frag->value & ~0x1); /* even numbers only */
+       else if (frag->value == 0)
+           val = MAX_FRAG_THRESHOLD;
+       else
+               return -EINVAL;
+
+       pAdapter->CommonCfg.FragmentThreshold = val;
+       return 0;
+}
+
+int rt_ioctl_giwfrag(struct net_device *dev,
+                       struct iw_request_info *info,
+                       struct iw_param *frag, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+       frag->value = pAdapter->CommonCfg.FragmentThreshold;
+       frag->disabled = (frag->value == MAX_FRAG_THRESHOLD);
+       frag->fixed = 1;
+
+       return 0;
+}
+
+#define MAX_WEP_KEY_SIZE 13
+#define MIN_WEP_KEY_SIZE 5
+int rt_ioctl_siwencode(struct net_device *dev,
+                         struct iw_request_info *info,
+                         struct iw_point *erq, char *extra)
+{
+       PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+               return -ENETDOWN;
+       }
+
+       if ((erq->length == 0) &&
+        (erq->flags & IW_ENCODE_DISABLED))
+       {
+               pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled;
+               pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled;
+               pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled;
+        pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+        goto done;
+       }
+       else if ((erq->length == 0) &&
+             (erq->flags & IW_ENCODE_RESTRICTED || erq->flags & IW_ENCODE_OPEN))
+       {
+           //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+               STA_PORT_SECURED(pAdapter);
+               pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled;
+               pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled;
+               pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled;
+        pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+               if (erq->flags & IW_ENCODE_RESTRICTED)
+                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared;
+       else
+                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+        goto done;
+       }
+
+    if (erq->length > 0)
+       {
+               int keyIdx = (erq->flags & IW_ENCODE_INDEX) - 1;
+               /* Check the size of the key */
+               if (erq->length > MAX_WEP_KEY_SIZE) {
+                       return -EINVAL;
+               }
+               /* Check key index */
+               if ((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS))
+        {
+            DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::Wrong keyIdx=%d! Using default key instead (%d)\n",
+                                        keyIdx, pAdapter->StaCfg.DefaultKeyId));
+
+            //Using default key
+                       keyIdx = pAdapter->StaCfg.DefaultKeyId;
+        }
+
+        NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key,  16);
+
+               if (erq->length == MAX_WEP_KEY_SIZE)
+        {
+                       pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE;
+            pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128;
+               }
+               else if (erq->length == MIN_WEP_KEY_SIZE)
+        {
+            pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE;
+            pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64;
+               }
+               else
+                       /* Disable the key */
+                       pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0;
+
+               /* Check if the key is not marked as invalid */
+               if(!(erq->flags & IW_ENCODE_NOKEY)) {
+                       /* Copy the key in the driver */
+                       NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, extra, erq->length);
+        }
+       }
+    else
+                       {
+               /* Do we want to just set the transmit key index ? */
+               int index = (erq->flags & IW_ENCODE_INDEX) - 1;
+               if ((index >= 0) && (index < 4))
+        {
+                       pAdapter->StaCfg.DefaultKeyId = index;
+            }
+        else
+                       /* Don't complain if only change the mode */
+                       if(!erq->flags & IW_ENCODE_MODE) {
+                               return -EINVAL;
+               }
+       }
+
+done:
+    DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::erq->flags=%x\n",erq->flags));
+       DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::AuthMode=%x\n",pAdapter->StaCfg.AuthMode));
+       DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::DefaultKeyId=%x, KeyLen = %d\n",pAdapter->StaCfg.DefaultKeyId , pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen));
+       DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::WepStatus=%x\n",pAdapter->StaCfg.WepStatus));
+       return 0;
+}
+
+int
+rt_ioctl_giwencode(struct net_device *dev,
+                         struct iw_request_info *info,
+                         struct iw_point *erq, char *key)
+{
+       int kid;
+       PRTMP_ADAPTER   pAdapter = NULL;
+       VIRTUAL_ADAPTER *pVirtualAd = NULL;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               if (pVirtualAd && pVirtualAd->RtmpDev)
+                       pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+       kid = erq->flags & IW_ENCODE_INDEX;
+       DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_giwencode %d\n", erq->flags & IW_ENCODE_INDEX));
+
+       if (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled)
+       {
+               erq->length = 0;
+               erq->flags = IW_ENCODE_DISABLED;
+       }
+       else if ((kid > 0) && (kid <=4))
+       {
+               // copy wep key
+               erq->flags = kid ;                      /* NB: base 1 */
+               if (erq->length > pAdapter->SharedKey[BSS0][kid-1].KeyLen)
+                       erq->length = pAdapter->SharedKey[BSS0][kid-1].KeyLen;
+               memcpy(key, pAdapter->SharedKey[BSS0][kid-1].Key, erq->length);
+               //if ((kid == pAdapter->PortCfg.DefaultKeyId))
+               //erq->flags |= IW_ENCODE_ENABLED;      /* XXX */
+               if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared)
+                       erq->flags |= IW_ENCODE_RESTRICTED;             /* XXX */
+               else
+                       erq->flags |= IW_ENCODE_OPEN;           /* XXX */
+
+       }
+       else if (kid == 0)
+       {
+               if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared)
+                       erq->flags |= IW_ENCODE_RESTRICTED;             /* XXX */
+               else
+                       erq->flags |= IW_ENCODE_OPEN;           /* XXX */
+               erq->length = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen;
+               memcpy(key, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, erq->length);
+               // copy default key ID
+               if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared)
+                       erq->flags |= IW_ENCODE_RESTRICTED;             /* XXX */
+               else
+                       erq->flags |= IW_ENCODE_OPEN;           /* XXX */
+               erq->flags = pAdapter->StaCfg.DefaultKeyId + 1;                 /* NB: base 1 */
+               erq->flags |= IW_ENCODE_ENABLED;        /* XXX */
+       }
+
+       return 0;
+
+}
+
+static int
+rt_ioctl_setparam(struct net_device *dev, struct iw_request_info *info,
+                        void *w, char *extra)
+{
+    VIRTUAL_ADAPTER    *pVirtualAd = NULL;
+       PRTMP_ADAPTER pAdapter;
+       POS_COOKIE pObj;
+       char *this_char = extra;
+       char *value;
+       int  Status=0;
+
+       if (dev->priv_flags == INT_MAIN)
+       {
+               pAdapter = dev->priv;
+       }
+       else
+       {
+               pVirtualAd = dev->priv;
+               pAdapter = pVirtualAd->RtmpDev->priv;
+       }
+       pObj = (POS_COOKIE) pAdapter->OS_Cookie;
+
+       if (pAdapter == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+       {
+               pObj->ioctl_if_type = INT_MAIN;
+        pObj->ioctl_if = MAIN_MBSSID;
+       }
+
+       //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+                       return -ENETDOWN;
+       }
+
+       if (!*this_char)
+               return -EINVAL;
+
+       if ((value = rtstrchr(this_char, '=')) != NULL)
+           *value++ = 0;
+
+       if (!value)
+           return -EINVAL;
+
+       // reject setting nothing besides ANY ssid(ssidLen=0)
+    if (!*value && (strcmp(this_char, "SSID") != 0))
+        return -EINVAL;
+
+       for (PRTMP_PRIVATE_SET_PROC = RTMP_PRIVATE_SUPPORT_PROC; PRTMP_PRIVATE_SET_PROC->name; PRTMP_PRIVATE_SET_PROC++)
+       {
+           if (strcmp(this_char, PRTMP_PRIVATE_SET_PROC->name) == 0)
+           {
+               if(!PRTMP_PRIVATE_SET_PROC->set_proc(pAdapter, value))
+               {       //FALSE:Set private failed then return Invalid argument
+                           Status = -EINVAL;
+               }
+                   break;      //Exit for loop.
+           }
+       }
+
+       if(PRTMP_PRIVATE_SET_PROC->name == NULL)
+       {  //Not found argument
+           Status = -EINVAL;
+           DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_setparam:: (iwpriv) Not Support Set Command [%s=%s]\n", this_char, value));
+       }
+
+    return Status;
+}
+
+
+static int
+rt_private_get_statistics(struct net_device *dev, struct iw_request_info *info,
+               struct iw_point *wrq, char *extra)
+{
+       INT                             Status = 0;
+    PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+
+    if (extra == NULL)
+    {
+        wrq->length = 0;
+        return -EIO;
+    }
+
+    memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+    sprintf(extra, "\n\n");
+
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+       {
+           sprintf(extra+strlen(extra), "Tx success                      = %ld\n", (ULONG)pAd->ate.TxDoneCount);
+           //sprintf(extra+strlen(extra), "Tx success without retry        = %ld\n", (ULONG)pAd->ate.TxDoneCount);
+       }
+       else
+#endif // RALINK_ATE //
+       {
+    sprintf(extra+strlen(extra), "Tx success                      = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart);
+    sprintf(extra+strlen(extra), "Tx success without retry        = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart - (ULONG)pAd->WlanCounters.RetryCount.QuadPart);
+       }
+    sprintf(extra+strlen(extra), "Tx success after retry          = %ld\n", (ULONG)pAd->WlanCounters.RetryCount.QuadPart);
+    sprintf(extra+strlen(extra), "Tx fail to Rcv ACK after retry  = %ld\n", (ULONG)pAd->WlanCounters.FailedCount.QuadPart);
+    sprintf(extra+strlen(extra), "RTS Success Rcv CTS             = %ld\n", (ULONG)pAd->WlanCounters.RTSSuccessCount.QuadPart);
+    sprintf(extra+strlen(extra), "RTS Fail Rcv CTS                = %ld\n", (ULONG)pAd->WlanCounters.RTSFailureCount.QuadPart);
+
+    sprintf(extra+strlen(extra), "Rx success                      = %ld\n", (ULONG)pAd->WlanCounters.ReceivedFragmentCount.QuadPart);
+    sprintf(extra+strlen(extra), "Rx with CRC                     = %ld\n", (ULONG)pAd->WlanCounters.FCSErrorCount.QuadPart);
+    sprintf(extra+strlen(extra), "Rx drop due to out of resource  = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer);
+    sprintf(extra+strlen(extra), "Rx duplicate frame              = %ld\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.QuadPart);
+
+    sprintf(extra+strlen(extra), "False CCA (one second)          = %ld\n", (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt);
+#ifdef RALINK_ATE
+       if (ATE_ON(pAd))
+       {
+               if (pAd->ate.RxAntennaSel == 0)
+               {
+               sprintf(extra+strlen(extra), "RSSI-A                          = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta));
+                       sprintf(extra+strlen(extra), "RSSI-B (if available)           = %ld\n", (LONG)(pAd->ate.LastRssi1 - pAd->BbpRssiToDbmDelta));
+                       sprintf(extra+strlen(extra), "RSSI-C (if available)           = %ld\n\n", (LONG)(pAd->ate.LastRssi2 - pAd->BbpRssiToDbmDelta));
+               }
+               else
+               {
+               sprintf(extra+strlen(extra), "RSSI                            = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta));
+               }
+       }
+       else
+#endif // RALINK_ATE //
+       {
+       sprintf(extra+strlen(extra), "RSSI-A                          = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta));
+        sprintf(extra+strlen(extra), "RSSI-B (if available)           = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi1 - pAd->BbpRssiToDbmDelta));
+        sprintf(extra+strlen(extra), "RSSI-C (if available)           = %ld\n\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi2 - pAd->BbpRssiToDbmDelta));
+       }
+#ifdef WPA_SUPPLICANT_SUPPORT
+    sprintf(extra+strlen(extra), "WpaSupplicantUP                 = %d\n\n", pAd->StaCfg.WpaSupplicantUP);
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+
+    wrq->length = strlen(extra) + 1; // 1: size of '\0'
+    DBGPRINT(RT_DEBUG_TRACE, ("<== rt_private_get_statistics, wrq->length = %d\n", wrq->length));
+
+    return Status;
+}
+
+#ifdef DOT11_N_SUPPORT
+void   getBaInfo(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  pOutBuf)
+{
+       INT i, j;
+       BA_ORI_ENTRY *pOriBAEntry;
+       BA_REC_ENTRY *pRecBAEntry;
+
+       for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+               if (((pEntry->ValidAsCLI || pEntry->ValidAsApCli) && (pEntry->Sst == SST_ASSOC))
+                       || (pEntry->ValidAsWDS) || (pEntry->ValidAsMesh))
+               {
+                       sprintf(pOutBuf, "%s\n%02X:%02X:%02X:%02X:%02X:%02X (Aid = %d) (AP) -\n",
+                pOutBuf,
+                               pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+                               pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5], pEntry->Aid);
+
+                       sprintf(pOutBuf, "%s[Recipient]\n", pOutBuf);
+                       for (j=0; j < NUM_OF_TID; j++)
+                       {
+                               if (pEntry->BARecWcidArray[j] != 0)
+                               {
+                                       pRecBAEntry =&pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]];
+                                       sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, LastIndSeq=%d, ReorderingPkts=%d\n", pOutBuf, j, pRecBAEntry->BAWinSize, pRecBAEntry->LastIndSeq, pRecBAEntry->list.qlen);
+                               }
+                       }
+                       sprintf(pOutBuf, "%s\n", pOutBuf);
+
+                       sprintf(pOutBuf, "%s[Originator]\n", pOutBuf);
+                       for (j=0; j < NUM_OF_TID; j++)
+                       {
+                               if (pEntry->BAOriWcidArray[j] != 0)
+                               {
+                                       pOriBAEntry =&pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]];
+                                       sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, StartSeq=%d, CurTxSeq=%d\n", pOutBuf, j, pOriBAEntry->BAWinSize, pOriBAEntry->Sequence, pEntry->TxSeq[j]);
+                               }
+                       }
+                       sprintf(pOutBuf, "%s\n\n", pOutBuf);
+               }
+        if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30))
+                break;
+       }
+
+       return;
+}
+#endif // DOT11_N_SUPPORT //
+
+static int
+rt_private_show(struct net_device *dev, struct iw_request_info *info,
+               struct iw_point *wrq, char *extra)
+{
+    INT                                Status = 0;
+    VIRTUAL_ADAPTER    *pVirtualAd = NULL;
+    PRTMP_ADAPTER   pAd;
+       POS_COOKIE              pObj;
+    u32             subcmd = wrq->flags;
+
+       if (dev->priv_flags == INT_MAIN)
+               pAd = dev->priv;
+       else
+       {
+               pVirtualAd = dev->priv;
+               pAd = pVirtualAd->RtmpDev->priv;
+       }
+       pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+       if (pAd == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+    if (extra == NULL)
+    {
+        wrq->length = 0;
+        return -EIO;
+    }
+    memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+
+       {
+               pObj->ioctl_if_type = INT_MAIN;
+        pObj->ioctl_if = MAIN_MBSSID;
+       }
+
+    switch(subcmd)
+    {
+
+        case SHOW_CONN_STATUS:
+            if (MONITOR_ON(pAd))
+            {
+#ifdef DOT11_N_SUPPORT
+                if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED &&
+                    pAd->CommonCfg.RegTransmitSetting.field.BW)
+                    sprintf(extra, "Monitor Mode(CentralChannel %d)\n", pAd->CommonCfg.CentralChannel);
+                else
+#endif // DOT11_N_SUPPORT //
+                    sprintf(extra, "Monitor Mode(Channel %d)\n", pAd->CommonCfg.Channel);
+            }
+            else
+            {
+                if (pAd->IndicateMediaState == NdisMediaStateConnected)
+               {
+                   if (INFRA_ON(pAd))
+                    {
+                    sprintf(extra, "Connected(AP: %s[%02X:%02X:%02X:%02X:%02X:%02X])\n",
+                                    pAd->CommonCfg.Ssid,
+                                    pAd->CommonCfg.Bssid[0],
+                                    pAd->CommonCfg.Bssid[1],
+                                    pAd->CommonCfg.Bssid[2],
+                                    pAd->CommonCfg.Bssid[3],
+                                    pAd->CommonCfg.Bssid[4],
+                                    pAd->CommonCfg.Bssid[5]);
+                       DBGPRINT(RT_DEBUG_TRACE ,("Ssid=%s ,Ssidlen = %d\n",pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen));
+               }
+                    else if (ADHOC_ON(pAd))
+                        sprintf(extra, "Connected\n");
+               }
+               else
+               {
+                   sprintf(extra, "Disconnected\n");
+                       DBGPRINT(RT_DEBUG_TRACE ,("ConnStatus is not connected\n"));
+               }
+            }
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+        case SHOW_DRVIER_VERION:
+            sprintf(extra, "Driver version-%s, %s %s\n", STA_DRIVER_VERSION, __DATE__, __TIME__ );
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+#ifdef DOT11_N_SUPPORT
+        case SHOW_BA_INFO:
+            getBaInfo(pAd, extra);
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+#endif // DOT11_N_SUPPORT //
+               case SHOW_DESC_INFO:
+                       {
+                               Show_DescInfo_Proc(pAd, NULL);
+                               wrq->length = 0; // 1: size of '\0'
+                       }
+                       break;
+        case RAIO_OFF:
+            if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+            {
+                sprintf(extra, "Scanning\n");
+                wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                break;
+            }
+            pAd->StaCfg.bSwRadio = FALSE;
+            if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
+            {
+                pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
+                if (pAd->StaCfg.bRadio == FALSE)
+                {
+                    MlmeRadioOff(pAd);
+                    // Update extra information
+                                       pAd->ExtraInfo = SW_RADIO_OFF;
+                }
+            }
+            sprintf(extra, "Radio Off\n");
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+        case RAIO_ON:
+            if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+            {
+                sprintf(extra, "Scanning\n");
+                wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                break;
+            }
+            pAd->StaCfg.bSwRadio = TRUE;
+            //if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
+            {
+                pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
+                if (pAd->StaCfg.bRadio == TRUE)
+                {
+                    MlmeRadioOn(pAd);
+                    // Update extra information
+                                       pAd->ExtraInfo = EXTRA_INFO_CLEAR;
+                }
+            }
+            sprintf(extra, "Radio On\n");
+            wrq->length = strlen(extra) + 1; // 1: size of '\0'
+            break;
+
+
+#ifdef QOS_DLS_SUPPORT
+               case SHOW_DLS_ENTRY_INFO:
+                       {
+                               Set_DlsEntryInfo_Display_Proc(pAd, NULL);
+                               wrq->length = 0; // 1: size of '\0'
+                       }
+                       break;
+#endif // QOS_DLS_SUPPORT //
+
+               case SHOW_CFG_VALUE:
+                       {
+                               Status = RTMPShowCfgValue(pAd, wrq->pointer, extra);
+                               if (Status == 0)
+                                       wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                       }
+                       break;
+               case SHOW_ADHOC_ENTRY_INFO:
+                       Show_Adhoc_MacTable_Proc(pAd, extra);
+                       wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                       break;
+        default:
+            DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow subcmd = %d\n", __FUNCTION__, subcmd));
+            break;
+    }
+
+    return Status;
+}
+
+#ifdef SIOCSIWMLME
+int rt_ioctl_siwmlme(struct net_device *dev,
+                          struct iw_request_info *info,
+                          union iwreq_data *wrqu,
+                          char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+       struct iw_mlme *pMlme = (struct iw_mlme *)wrqu->data.pointer;
+       MLME_QUEUE_ELEM                         MsgElem;
+       MLME_DISASSOC_REQ_STRUCT        DisAssocReq;
+       MLME_DEAUTH_REQ_STRUCT      DeAuthReq;
+
+       DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__));
+
+       if (pMlme == NULL)
+               return -EINVAL;
+
+       switch(pMlme->cmd)
+       {
+#ifdef IW_MLME_DEAUTH
+               case IW_MLME_DEAUTH:
+                       DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DEAUTH\n", __FUNCTION__));
+                       COPY_MAC_ADDR(DeAuthReq.Addr, pAd->CommonCfg.Bssid);
+                       DeAuthReq.Reason = pMlme->reason_code;
+                       MsgElem.MsgLen = sizeof(MLME_DEAUTH_REQ_STRUCT);
+                       NdisMoveMemory(MsgElem.Msg, &DeAuthReq, sizeof(MLME_DEAUTH_REQ_STRUCT));
+                       MlmeDeauthReqAction(pAd, &MsgElem);
+                       if (INFRA_ON(pAd))
+                       {
+                           LinkDown(pAd, FALSE);
+                           pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+                       }
+                       break;
+#endif // IW_MLME_DEAUTH //
+#ifdef IW_MLME_DISASSOC
+               case IW_MLME_DISASSOC:
+                       DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DISASSOC\n", __FUNCTION__));
+                       COPY_MAC_ADDR(DisAssocReq.Addr, pAd->CommonCfg.Bssid);
+                       DisAssocReq.Reason =  pMlme->reason_code;
+
+                       MsgElem.Machine = ASSOC_STATE_MACHINE;
+                       MsgElem.MsgType = MT2_MLME_DISASSOC_REQ;
+                       MsgElem.MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT);
+                       NdisMoveMemory(MsgElem.Msg, &DisAssocReq, sizeof(MLME_DISASSOC_REQ_STRUCT));
+
+                       pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC;
+                       MlmeDisassocReqAction(pAd, &MsgElem);
+                       break;
+#endif // IW_MLME_DISASSOC //
+               default:
+                       DBGPRINT(RT_DEBUG_TRACE, ("====> %s - Unknow Command\n", __FUNCTION__));
+                       break;
+       }
+
+       return 0;
+}
+#endif // SIOCSIWMLME //
+
+#if WIRELESS_EXT > 17
+int rt_ioctl_siwauth(struct net_device *dev,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = (PRTMP_ADAPTER) dev->priv;
+       struct iw_param *param = &wrqu->param;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_WPA_VERSION:
+            if (param->value == IW_AUTH_WPA_VERSION_WPA)
+            {
+                pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK;
+                               if (pAdapter->StaCfg.BssType == BSS_ADHOC)
+                                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone;
+            }
+            else if (param->value == IW_AUTH_WPA_VERSION_WPA2)
+                pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK;
+
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_CIPHER_PAIRWISE:
+            if (param->value == IW_AUTH_CIPHER_NONE)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_WEP40 ||
+                     param->value == IW_AUTH_CIPHER_WEP104)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled;
+#ifdef WPA_SUPPLICANT_SUPPORT
+                pAdapter->StaCfg.IEEE8021X = FALSE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+            }
+            else if (param->value == IW_AUTH_CIPHER_TKIP)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11Encryption2Enabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_CCMP)
+            {
+                pAdapter->StaCfg.WepStatus = Ndis802_11Encryption3Enabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11Encryption3Enabled;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_PAIRWISE - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_CIPHER_GROUP:
+            if (param->value == IW_AUTH_CIPHER_NONE)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_WEP40 ||
+                     param->value == IW_AUTH_CIPHER_WEP104)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_TKIP)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled;
+            }
+            else if (param->value == IW_AUTH_CIPHER_CCMP)
+            {
+                pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_GROUP - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_KEY_MGMT:
+            if (param->value == IW_AUTH_KEY_MGMT_802_1X)
+            {
+                if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
+                {
+                    pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA;
+#ifdef WPA_SUPPLICANT_SUPPORT
+                    pAdapter->StaCfg.IEEE8021X = FALSE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+                }
+                else if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+                {
+                    pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2;
+#ifdef WPA_SUPPLICANT_SUPPORT
+                    pAdapter->StaCfg.IEEE8021X = FALSE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+                }
+#ifdef WPA_SUPPLICANT_SUPPORT
+                else
+                    // WEP 1x
+                    pAdapter->StaCfg.IEEE8021X = TRUE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+            }
+            else if (param->value == 0)
+            {
+                //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               STA_PORT_SECURED(pAdapter);
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_KEY_MGMT - param->value = %d!\n", __FUNCTION__, param->value));
+            break;
+       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+            break;
+       case IW_AUTH_PRIVACY_INVOKED:
+            /*if (param->value == 0)
+                       {
+                pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+                pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled;
+                pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+                pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled;
+                   pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled;
+            }*/
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_PRIVACY_INVOKED - param->value = %d!\n", __FUNCTION__, param->value));
+               break;
+       case IW_AUTH_DROP_UNENCRYPTED:
+            if (param->value != 0)
+                pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                       else
+                       {
+                //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               STA_PORT_SECURED(pAdapter);
+                       }
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value));
+               break;
+       case IW_AUTH_80211_AUTH_ALG:
+                       if (param->value & IW_AUTH_ALG_SHARED_KEY)
+            {
+                               pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared;
+                       }
+            else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
+            {
+                               pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+                       }
+            else
+                               return -EINVAL;
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_80211_AUTH_ALG - param->value = %d!\n", __FUNCTION__, param->value));
+                       break;
+       case IW_AUTH_WPA_ENABLED:
+               DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_ENABLED - Driver supports WPA!(param->value = %d)\n", __FUNCTION__, param->value));
+               break;
+       default:
+               return -EOPNOTSUPP;
+}
+
+       return 0;
+}
+
+int rt_ioctl_giwauth(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAdapter = (PRTMP_ADAPTER) dev->priv;
+       struct iw_param *param = &wrqu->param;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+    }
+
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_DROP_UNENCRYPTED:
+        param->value = (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) ? 0 : 1;
+               break;
+
+       case IW_AUTH_80211_AUTH_ALG:
+        param->value = (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) ? IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM;
+               break;
+
+       case IW_AUTH_WPA_ENABLED:
+               param->value = (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) ? 1 : 0;
+               break;
+
+       default:
+               return -EOPNOTSUPP;
+       }
+    DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_giwauth::param->value = %d!\n", param->value));
+       return 0;
+}
+
+void fnSetCipherKey(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  INT             keyIdx,
+    IN  UCHAR           CipherAlg,
+    IN  BOOLEAN         bGTK,
+    IN  struct iw_encode_ext *ext)
+{
+    NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY));
+    pAdapter->SharedKey[BSS0][keyIdx].KeyLen = LEN_TKIP_EK;
+    NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, LEN_TKIP_EK);
+    NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].TxMic, ext->key + LEN_TKIP_EK, LEN_TKIP_TXMICK);
+    NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].RxMic, ext->key + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK);
+    pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CipherAlg;
+
+    // Update group key information to ASIC Shared Key Table
+       AsicAddSharedKeyEntry(pAdapter,
+                                                 BSS0,
+                                                 keyIdx,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].CipherAlg,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].Key,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].TxMic,
+                                                 pAdapter->SharedKey[BSS0][keyIdx].RxMic);
+
+    if (bGTK)
+        // Update ASIC WCID attribute table and IVEIV table
+       RTMPAddWcidAttributeEntry(pAdapter,
+                                                         BSS0,
+                                                         keyIdx,
+                                                         pAdapter->SharedKey[BSS0][keyIdx].CipherAlg,
+                                                         NULL);
+    else
+        // Update ASIC WCID attribute table and IVEIV table
+       RTMPAddWcidAttributeEntry(pAdapter,
+                                                         BSS0,
+                                                         keyIdx,
+                                                         pAdapter->SharedKey[BSS0][keyIdx].CipherAlg,
+                                                         &pAdapter->MacTab.Content[BSSID_WCID]);
+}
+
+int rt_ioctl_siwencodeext(struct net_device *dev,
+                          struct iw_request_info *info,
+                          union iwreq_data *wrqu,
+                          char *extra)
+                       {
+    PRTMP_ADAPTER   pAdapter = (PRTMP_ADAPTER) dev->priv;
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+    int keyIdx, alg = ext->alg;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+    if (encoding->flags & IW_ENCODE_DISABLED)
+       {
+        keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1;
+        // set BSSID wcid entry of the Pair-wise Key table as no-security mode
+           AsicRemovePairwiseKeyEntry(pAdapter, BSS0, BSSID_WCID);
+        pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0;
+               pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_NONE;
+               AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)keyIdx);
+        NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY));
+        DBGPRINT(RT_DEBUG_TRACE, ("%s::Remove all keys!(encoding->flags = %x)\n", __FUNCTION__, encoding->flags));
+    }
+                                       else
+    {
+        // Get Key Index and convet to our own defined key index
+       keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1;
+       if((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS))
+               return -EINVAL;
+
+        if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+        {
+            pAdapter->StaCfg.DefaultKeyId = keyIdx;
+            DBGPRINT(RT_DEBUG_TRACE, ("%s::DefaultKeyId = %d\n", __FUNCTION__, pAdapter->StaCfg.DefaultKeyId));
+        }
+
+        switch (alg) {
+               case IW_ENCODE_ALG_NONE:
+                DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_NONE\n", __FUNCTION__));
+                       break;
+               case IW_ENCODE_ALG_WEP:
+                DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_WEP - ext->key_len = %d, keyIdx = %d\n", __FUNCTION__, ext->key_len, keyIdx));
+                       if (ext->key_len == MAX_WEP_KEY_SIZE)
+                {
+                               pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE;
+                    pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128;
+                               }
+                       else if (ext->key_len == MIN_WEP_KEY_SIZE)
+                {
+                    pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE;
+                    pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64;
+                       }
+                       else
+                    return -EINVAL;
+
+                NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key,  16);
+                           NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, ext->key_len);
+                       break;
+            case IW_ENCODE_ALG_TKIP:
+                DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_TKIP - keyIdx = %d, ext->key_len = %d\n", __FUNCTION__, keyIdx, ext->key_len));
+                if (ext->key_len == 32)
+                {
+                    if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+                    {
+                        fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, FALSE, ext);
+                        if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2)
+                        {
+                            //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                            STA_PORT_SECURED(pAdapter);
+                        }
+               }
+                    else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+                    {
+                        fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, TRUE, ext);
+
+                        // set 802.1x port control
+                       //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAdapter);
+                    }
+                }
+                else
+                    return -EINVAL;
+                break;
+            case IW_ENCODE_ALG_CCMP:
+                if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+               {
+                    fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, FALSE, ext);
+                    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2)
+                       //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAdapter);
+                }
+                else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+                {
+                    fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, TRUE, ext);
+
+                    // set 802.1x port control
+                       //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                       STA_PORT_SECURED(pAdapter);
+                }
+                break;
+               default:
+                       return -EINVAL;
+               }
+    }
+
+    return 0;
+}
+
+int
+rt_ioctl_giwencodeext(struct net_device *dev,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) dev->priv;
+       PCHAR pKey = NULL;
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+       int idx, max_key_len;
+
+       DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_giwencodeext\n"));
+
+       max_key_len = encoding->length - sizeof(*ext);
+       if (max_key_len < 0)
+               return -EINVAL;
+
+       idx = encoding->flags & IW_ENCODE_INDEX;
+       if (idx)
+       {
+               if (idx < 1 || idx > 4)
+                       return -EINVAL;
+               idx--;
+
+               if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
+                       (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled))
+               {
+                       if (idx != pAd->StaCfg.DefaultKeyId)
+                       {
+                               ext->key_len = 0;
+                               return 0;
+                       }
+               }
+       }
+       else
+               idx = pAd->StaCfg.DefaultKeyId;
+
+       encoding->flags = idx + 1;
+       memset(ext, 0, sizeof(*ext));
+
+       ext->key_len = 0;
+       switch(pAd->StaCfg.WepStatus) {
+               case Ndis802_11WEPDisabled:
+                       ext->alg = IW_ENCODE_ALG_NONE;
+                       encoding->flags |= IW_ENCODE_DISABLED;
+                       break;
+               case Ndis802_11WEPEnabled:
+                       ext->alg = IW_ENCODE_ALG_WEP;
+                       if (pAd->SharedKey[BSS0][idx].KeyLen > max_key_len)
+                               return -E2BIG;
+                       else
+                       {
+                               ext->key_len = pAd->SharedKey[BSS0][idx].KeyLen;
+                               pKey = &(pAd->SharedKey[BSS0][idx].Key[0]);
+                       }
+                       break;
+               case Ndis802_11Encryption2Enabled:
+               case Ndis802_11Encryption3Enabled:
+                       if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)
+                               ext->alg = IW_ENCODE_ALG_TKIP;
+                       else
+                               ext->alg = IW_ENCODE_ALG_CCMP;
+
+                       if (max_key_len < 32)
+                               return -E2BIG;
+                       else
+                       {
+                               ext->key_len = 32;
+                               pKey = &pAd->StaCfg.PMK[0];
+                       }
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       if (ext->key_len && pKey)
+       {
+               encoding->flags |= IW_ENCODE_ENABLED;
+               memcpy(ext->key, pKey, ext->key_len);
+       }
+
+       return 0;
+}
+
+#ifdef SIOCSIWGENIE
+int rt_ioctl_siwgenie(struct net_device *dev,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+
+       if (wrqu->data.length > MAX_LEN_OF_RSNIE ||
+           (wrqu->data.length && extra == NULL))
+               return -EINVAL;
+
+       if (wrqu->data.length)
+       {
+               pAd->StaCfg.RSNIE_Len = wrqu->data.length;
+               NdisMoveMemory(&pAd->StaCfg.RSN_IE[0], extra, pAd->StaCfg.RSNIE_Len);
+       }
+       else
+       {
+               pAd->StaCfg.RSNIE_Len = 0;
+               NdisZeroMemory(&pAd->StaCfg.RSN_IE[0], MAX_LEN_OF_RSNIE);
+       }
+
+       return 0;
+}
+#endif // SIOCSIWGENIE //
+
+int rt_ioctl_giwgenie(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+
+       if ((pAd->StaCfg.RSNIE_Len == 0) ||
+               (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA))
+       {
+               wrqu->data.length = 0;
+               return 0;
+       }
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+#ifdef SIOCSIWGENIE
+       if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE)
+       {
+       if (wrqu->data.length < pAd->StaCfg.RSNIE_Len)
+               return -E2BIG;
+
+       wrqu->data.length = pAd->StaCfg.RSNIE_Len;
+       memcpy(extra, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len);
+       }
+       else
+#endif // SIOCSIWGENIE //
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+       {
+               UCHAR RSNIe = IE_WPA;
+
+               if (wrqu->data.length < (pAd->StaCfg.RSNIE_Len + 2)) // ID, Len
+                       return -E2BIG;
+               wrqu->data.length = pAd->StaCfg.RSNIE_Len + 2;
+
+               if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
+            (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2))
+                       RSNIe = IE_RSN;
+
+               extra[0] = (char)RSNIe;
+               extra[1] = pAd->StaCfg.RSNIE_Len;
+               memcpy(extra+2, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len);
+       }
+
+       return 0;
+}
+
+int rt_ioctl_siwpmksa(struct net_device *dev,
+                          struct iw_request_info *info,
+                          union iwreq_data *wrqu,
+                          char *extra)
+{
+       PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+       struct iw_pmksa *pPmksa = (struct iw_pmksa *)wrqu->data.pointer;
+       INT     CachedIdx = 0, idx = 0;
+
+       if (pPmksa == NULL)
+               return -EINVAL;
+
+       DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_siwpmksa\n"));
+       switch(pPmksa->cmd)
+       {
+               case IW_PMKSA_FLUSH:
+                       NdisZeroMemory(pAd->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO);
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_FLUSH\n"));
+                       break;
+               case IW_PMKSA_REMOVE:
+                       for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++)
+                       {
+                       // compare the BSSID
+                       if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN))
+                       {
+                               NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN);
+                                       NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].PMKID, 16);
+                                       for (idx = CachedIdx; idx < (pAd->StaCfg.SavedPMKNum - 1); idx++)
+                                       {
+                                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].BSSID[0], &pAd->StaCfg.SavedPMK[idx+1].BSSID[0], MAC_ADDR_LEN);
+                                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].PMKID[0], &pAd->StaCfg.SavedPMK[idx+1].PMKID[0], 16);
+                                       }
+                                       pAd->StaCfg.SavedPMKNum--;
+                               break;
+                       }
+               }
+
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_REMOVE\n"));
+                       break;
+               case IW_PMKSA_ADD:
+                       for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++)
+                       {
+                       // compare the BSSID
+                       if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN))
+                               break;
+               }
+
+               // Found, replace it
+               if (CachedIdx < PMKID_NO)
+               {
+                       DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx));
+                       NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN);
+                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16);
+                       pAd->StaCfg.SavedPMKNum++;
+               }
+               // Not found, replace the last one
+               else
+               {
+                       // Randomly replace one
+                       CachedIdx = (pPmksa->bssid.sa_data[5] % PMKID_NO);
+                       DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx));
+                       NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN);
+                               NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16);
+               }
+
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_ADD\n"));
+                       break;
+               default:
+                       DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - Unknow Command!!\n"));
+                       break;
+       }
+
+       return 0;
+}
+#endif // #if WIRELESS_EXT > 17
+
+#ifdef DBG
+static int
+rt_private_ioctl_bbp(struct net_device *dev, struct iw_request_info *info,
+               struct iw_point *wrq, char *extra)
+                       {
+       CHAR                            *this_char;
+       CHAR                            *value = NULL;
+       UCHAR                           regBBP = 0;
+//     CHAR                            arg[255]={0};
+       UINT32                          bbpId;
+       UINT32                          bbpValue;
+       BOOLEAN                         bIsPrintAllBBP = FALSE;
+       INT                                     Status = 0;
+    PRTMP_ADAPTER       pAdapter = (PRTMP_ADAPTER) dev->priv;
+
+
+       memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+
+       if (wrq->length > 1) //No parameters.
+                               {
+               sprintf(extra, "\n");
+
+               //Parsing Read or Write
+               this_char = wrq->pointer;
+               DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s\n", this_char));
+               if (!*this_char)
+                       goto next;
+
+               if ((value = rtstrchr(this_char, '=')) != NULL)
+                       *value++ = 0;
+
+               if (!value || !*value)
+               { //Read
+                       DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s, value=%s\n", this_char, value));
+                       if (sscanf(this_char, "%d", &(bbpId)) == 1)
+                       {
+                               if (bbpId <= 136)
+                               {
+#ifdef RALINK_ATE
+                                       if (ATE_ON(pAdapter))
+                                       {
+                                               ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                                       }
+                                       else
+#endif // RALINK_ATE //
+                                       {
+                                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                                       }
+                                       sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId*2, regBBP);
+                    wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                                       DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra));
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       bIsPrintAllBBP = TRUE;
+                                       goto next;
+                               }
+                       }
+                       else
+                       { //Invalid parametes, so default printk all bbp
+                               bIsPrintAllBBP = TRUE;
+                               goto next;
+                       }
+               }
+               else
+               { //Write
+                       if ((sscanf(this_char, "%d", &(bbpId)) == 1) && (sscanf(value, "%x", &(bbpValue)) == 1))
+                       {
+                               if (bbpId <= 136)
+                               {
+#ifdef RALINK_ATE
+                                       if (ATE_ON(pAdapter))
+                                       {
+                                               ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue);
+                                               //Read it back for showing
+                                               ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                                       }
+                                       else
+#endif // RALINK_ATE //
+                                       {
+                                           RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue);
+                                       //Read it back for showing
+                                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                       }
+                                       sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId*2, regBBP);
+                    wrq->length = strlen(extra) + 1; // 1: size of '\0'
+                                       DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra));
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       bIsPrintAllBBP = TRUE;
+                                       goto next;
+                               }
+                       }
+                       else
+                       { //Invalid parametes, so default printk all bbp
+                               bIsPrintAllBBP = TRUE;
+                               goto next;
+                       }
+               }
+               }
+       else
+               bIsPrintAllBBP = TRUE;
+
+next:
+       if (bIsPrintAllBBP)
+       {
+               memset(extra, 0x00, IW_PRIV_SIZE_MASK);
+               sprintf(extra, "\n");
+               for (bbpId = 0; bbpId <= 136; bbpId++)
+               {
+                   if (strlen(extra) >= (IW_PRIV_SIZE_MASK - 10))
+                break;
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                       }
+                       else
+#endif // RALINK_ATE //
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, &regBBP);
+                       sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X    ", bbpId, bbpId*2, regBBP);
+                       if (bbpId%5 == 4)
+                               sprintf(extra+strlen(extra), "\n");
+               }
+
+        wrq->length = strlen(extra) + 1; // 1: size of '\0'
+        DBGPRINT(RT_DEBUG_TRACE, ("wrq->length = %d\n", wrq->length));
+       }
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<==rt_private_ioctl_bbp\n\n"));
+
+    return Status;
+}
+#endif // DBG //
+
+int rt_ioctl_siwrate(struct net_device *dev,
+                       struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
+{
+    PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+    UINT32          rate = wrqu->bitrate.value, fixed = wrqu->bitrate.fixed;
+
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+    DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(rate = %d, fixed = %d)\n", rate, fixed));
+    /* rate = -1 => auto rate
+       rate = X, fixed = 1 => (fixed rate X)
+    */
+    if (rate == -1)
+    {
+               //Auto Rate
+               pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+               pAd->StaCfg.bAutoTxRateSwitch = TRUE;
+               if ((pAd->CommonCfg.PhyMode <= PHY_11G) ||
+                   (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))
+                       RTMPSetDesiredRates(pAd, -1);
+
+#ifdef DOT11_N_SUPPORT
+               SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+    }
+    else
+    {
+        if (fixed)
+        {
+               pAd->StaCfg.bAutoTxRateSwitch = FALSE;
+            if ((pAd->CommonCfg.PhyMode <= PHY_11G) ||
+                (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))
+                RTMPSetDesiredRates(pAd, rate);
+            else
+            {
+                pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+#ifdef DOT11_N_SUPPORT
+                SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(HtMcs=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.MCS));
+        }
+        else
+        {
+            // TODO: rate = X, fixed = 0 => (rates <= X)
+            return -EOPNOTSUPP;
+        }
+    }
+
+    return 0;
+}
+
+int rt_ioctl_giwrate(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+    PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER) dev->priv;
+    int rate_index = 0, rate_count = 0;
+    HTTRANSMIT_SETTING ht_setting;
+    __s32 ralinkrate[] =
+       {2,  4,   11,  22, // CCK
+       12, 18,   24,  36, 48, 72, 96, 108, // OFDM
+       13, 26,   39,  52,  78, 104, 117, 130, 26,  52,  78, 104, 156, 208, 234, 260, // 20MHz, 800ns GI, MCS: 0 ~ 15
+       39, 78,  117, 156, 234, 312, 351, 390,                                                                            // 20MHz, 800ns GI, MCS: 16 ~ 23
+       27, 54,   81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, // 40MHz, 800ns GI, MCS: 0 ~ 15
+       81, 162, 243, 324, 486, 648, 729, 810,                                                                            // 40MHz, 800ns GI, MCS: 16 ~ 23
+       14, 29,   43,  57,  87, 115, 130, 144, 29, 59,   87, 115, 173, 230, 260, 288, // 20MHz, 400ns GI, MCS: 0 ~ 15
+       43, 87,  130, 173, 260, 317, 390, 433,                                                                            // 20MHz, 400ns GI, MCS: 16 ~ 23
+       30, 60,   90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, // 40MHz, 400ns GI, MCS: 0 ~ 15
+       90, 180, 270, 360, 540, 720, 810, 900};                                                                           // 40MHz, 400ns GI, MCS: 16 ~ 23
+
+    rate_count = sizeof(ralinkrate)/sizeof(__s32);
+    //check if the interface is down
+       if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+       {
+               DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+       return -ENETDOWN;
+       }
+
+    if ((pAd->StaCfg.bAutoTxRateSwitch == FALSE) &&
+        (INFRA_ON(pAd)) &&
+        ((pAd->CommonCfg.PhyMode <= PHY_11G) || (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)))
+        ht_setting.word = pAd->StaCfg.HTPhyMode.word;
+    else
+        ht_setting.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word;
+
+#ifdef DOT11_N_SUPPORT
+    if (ht_setting.field.MODE >= MODE_HTMIX)
+    {
+//     rate_index = 12 + ((UCHAR)ht_setting.field.BW *16) + ((UCHAR)ht_setting.field.ShortGI *32) + ((UCHAR)ht_setting.field.MCS);
+       rate_index = 12 + ((UCHAR)ht_setting.field.BW *24) + ((UCHAR)ht_setting.field.ShortGI *48) + ((UCHAR)ht_setting.field.MCS);
+    }
+    else
+#endif // DOT11_N_SUPPORT //
+    if (ht_setting.field.MODE == MODE_OFDM)
+       rate_index = (UCHAR)(ht_setting.field.MCS) + 4;
+    else if (ht_setting.field.MODE == MODE_CCK)
+       rate_index = (UCHAR)(ht_setting.field.MCS);
+
+    if (rate_index < 0)
+        rate_index = 0;
+
+    if (rate_index > rate_count)
+        rate_index = rate_count;
+
+    wrqu->bitrate.value = ralinkrate[rate_index] * 500000;
+    wrqu->bitrate.disabled = 0;
+
+    return 0;
+}
+
+static const iw_handler rt_handler[] =
+{
+       (iw_handler) NULL,                                  /* SIOCSIWCOMMIT */
+       (iw_handler) rt_ioctl_giwname,                  /* SIOCGIWNAME   */
+       (iw_handler) NULL,                                  /* SIOCSIWNWID   */
+       (iw_handler) NULL,                                  /* SIOCGIWNWID   */
+       (iw_handler) rt_ioctl_siwfreq,              /* SIOCSIWFREQ   */
+       (iw_handler) rt_ioctl_giwfreq,              /* SIOCGIWFREQ   */
+       (iw_handler) rt_ioctl_siwmode,              /* SIOCSIWMODE   */
+       (iw_handler) rt_ioctl_giwmode,              /* SIOCGIWMODE   */
+       (iw_handler) NULL,                              /* SIOCSIWSENS   */
+       (iw_handler) NULL,                              /* SIOCGIWSENS   */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWRANGE  */
+       (iw_handler) rt_ioctl_giwrange,             /* SIOCGIWRANGE  */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWPRIV   */
+       (iw_handler) NULL /* kernel code */,    /* SIOCGIWPRIV   */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWSTATS  */
+       (iw_handler) rt28xx_get_wireless_stats /* kernel code */,    /* SIOCGIWSTATS  */
+       (iw_handler) NULL,                              /* SIOCSIWSPY    */
+       (iw_handler) NULL,                              /* SIOCGIWSPY    */
+       (iw_handler) NULL,                                      /* SIOCSIWTHRSPY */
+       (iw_handler) NULL,                                      /* SIOCGIWTHRSPY */
+       (iw_handler) rt_ioctl_siwap,            /* SIOCSIWAP     */
+       (iw_handler) rt_ioctl_giwap,                /* SIOCGIWAP     */
+#ifdef SIOCSIWMLME
+       (iw_handler) rt_ioctl_siwmlme,          /* SIOCSIWMLME   */
+#else
+       (iw_handler) NULL,                                      /* SIOCSIWMLME */
+#endif // SIOCSIWMLME //
+       (iw_handler) rt_ioctl_iwaplist,             /* SIOCGIWAPLIST */
+#ifdef SIOCGIWSCAN
+       (iw_handler) rt_ioctl_siwscan,              /* SIOCSIWSCAN   */
+       (iw_handler) rt_ioctl_giwscan,              /* SIOCGIWSCAN   */
+#else
+       (iw_handler) NULL,                                      /* SIOCSIWSCAN   */
+       (iw_handler) NULL,                                      /* SIOCGIWSCAN   */
+#endif /* SIOCGIWSCAN */
+       (iw_handler) rt_ioctl_siwessid,             /* SIOCSIWESSID  */
+       (iw_handler) rt_ioctl_giwessid,             /* SIOCGIWESSID  */
+       (iw_handler) rt_ioctl_siwnickn,             /* SIOCSIWNICKN  */
+       (iw_handler) rt_ioctl_giwnickn,             /* SIOCGIWNICKN  */
+       (iw_handler) NULL,                                      /* -- hole --    */
+       (iw_handler) NULL,                                      /* -- hole --    */
+       (iw_handler) rt_ioctl_siwrate,          /* SIOCSIWRATE   */
+       (iw_handler) rt_ioctl_giwrate,          /* SIOCGIWRATE   */
+       (iw_handler) rt_ioctl_siwrts,               /* SIOCSIWRTS    */
+       (iw_handler) rt_ioctl_giwrts,               /* SIOCGIWRTS    */
+       (iw_handler) rt_ioctl_siwfrag,              /* SIOCSIWFRAG   */
+       (iw_handler) rt_ioctl_giwfrag,              /* SIOCGIWFRAG   */
+       (iw_handler) NULL,                              /* SIOCSIWTXPOW  */
+       (iw_handler) NULL,                              /* SIOCGIWTXPOW  */
+       (iw_handler) NULL,                              /* SIOCSIWRETRY  */
+       (iw_handler) NULL,                              /* SIOCGIWRETRY  */
+       (iw_handler) rt_ioctl_siwencode,                /* SIOCSIWENCODE */
+       (iw_handler) rt_ioctl_giwencode,                /* SIOCGIWENCODE */
+       (iw_handler) NULL,                              /* SIOCSIWPOWER  */
+       (iw_handler) NULL,                              /* SIOCGIWPOWER  */
+       (iw_handler) NULL,                                              /* -- hole -- */
+       (iw_handler) NULL,                                              /* -- hole -- */
+#if WIRELESS_EXT > 17
+    (iw_handler) rt_ioctl_siwgenie,         /* SIOCSIWGENIE  */
+       (iw_handler) rt_ioctl_giwgenie,         /* SIOCGIWGENIE  */
+       (iw_handler) rt_ioctl_siwauth,              /* SIOCSIWAUTH   */
+       (iw_handler) rt_ioctl_giwauth,              /* SIOCGIWAUTH   */
+       (iw_handler) rt_ioctl_siwencodeext,         /* SIOCSIWENCODEEXT */
+       (iw_handler) rt_ioctl_giwencodeext,             /* SIOCGIWENCODEEXT */
+       (iw_handler) rt_ioctl_siwpmksa,         /* SIOCSIWPMKSA  */
+#endif
+};
+
+static const iw_handler rt_priv_handlers[] = {
+       (iw_handler) NULL, /* + 0x00 */
+       (iw_handler) NULL, /* + 0x01 */
+#ifndef CONFIG_AP_SUPPORT
+       (iw_handler) rt_ioctl_setparam, /* + 0x02 */
+#else
+       (iw_handler) NULL, /* + 0x02 */
+#endif // CONFIG_AP_SUPPORT //
+#ifdef DBG
+       (iw_handler) rt_private_ioctl_bbp, /* + 0x03 */
+#else
+       (iw_handler) NULL, /* + 0x03 */
+#endif
+       (iw_handler) NULL, /* + 0x04 */
+       (iw_handler) NULL, /* + 0x05 */
+       (iw_handler) NULL, /* + 0x06 */
+       (iw_handler) NULL, /* + 0x07 */
+       (iw_handler) NULL, /* + 0x08 */
+       (iw_handler) rt_private_get_statistics, /* + 0x09 */
+       (iw_handler) NULL, /* + 0x0A */
+       (iw_handler) NULL, /* + 0x0B */
+       (iw_handler) NULL, /* + 0x0C */
+       (iw_handler) NULL, /* + 0x0D */
+       (iw_handler) NULL, /* + 0x0E */
+       (iw_handler) NULL, /* + 0x0F */
+       (iw_handler) NULL, /* + 0x10 */
+       (iw_handler) rt_private_show, /* + 0x11 */
+    (iw_handler) NULL, /* + 0x12 */
+       (iw_handler) NULL, /* + 0x13 */
+       (iw_handler) NULL, /* + 0x15 */
+       (iw_handler) NULL, /* + 0x17 */
+       (iw_handler) NULL, /* + 0x18 */
+};
+
+const struct iw_handler_def rt28xx_iw_handler_def =
+{
+#define        N(a)    (sizeof (a) / sizeof (a[0]))
+       .standard       = (iw_handler *) rt_handler,
+       .num_standard   = sizeof(rt_handler) / sizeof(iw_handler),
+       .private        = (iw_handler *) rt_priv_handlers,
+       .num_private            = N(rt_priv_handlers),
+       .private_args   = (struct iw_priv_args *) privtab,
+       .num_private_args       = N(privtab),
+#if IW_HANDLER_VERSION >= 7
+    .get_wireless_stats = rt28xx_get_wireless_stats,
+#endif
+};
+
+INT RTMPSetInformation(
+    IN  PRTMP_ADAPTER pAdapter,
+    IN  OUT struct ifreq    *rq,
+    IN  INT                 cmd)
+{
+    struct iwreq                        *wrq = (struct iwreq *) rq;
+    NDIS_802_11_SSID                    Ssid;
+    NDIS_802_11_MAC_ADDRESS             Bssid;
+    RT_802_11_PHY_MODE                  PhyMode;
+    RT_802_11_STA_CONFIG                StaConfig;
+    NDIS_802_11_RATES                   aryRates;
+    RT_802_11_PREAMBLE                  Preamble;
+    NDIS_802_11_WEP_STATUS              WepStatus;
+    NDIS_802_11_AUTHENTICATION_MODE     AuthMode = Ndis802_11AuthModeMax;
+    NDIS_802_11_NETWORK_INFRASTRUCTURE  BssType;
+    NDIS_802_11_RTS_THRESHOLD           RtsThresh;
+    NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh;
+    NDIS_802_11_POWER_MODE              PowerMode;
+    PNDIS_802_11_KEY                    pKey = NULL;
+    PNDIS_802_11_WEP                           pWepKey =NULL;
+    PNDIS_802_11_REMOVE_KEY             pRemoveKey = NULL;
+    NDIS_802_11_CONFIGURATION           Config, *pConfig = NULL;
+    NDIS_802_11_NETWORK_TYPE            NetType;
+    ULONG                               Now;
+    UINT                                KeyIdx = 0;
+    INT                                 Status = NDIS_STATUS_SUCCESS, MaxPhyMode = PHY_11G;
+    ULONG                               PowerTemp;
+    BOOLEAN                             RadioState;
+    BOOLEAN                             StateMachineTouched = FALSE;
+#ifdef DOT11_N_SUPPORT
+       OID_SET_HT_PHYMODE                                      HT_PhyMode;     //11n ,kathy
+#endif // DOT11_N_SUPPORT //
+#ifdef WPA_SUPPLICANT_SUPPORT
+    PNDIS_802_11_PMKID                  pPmkId = NULL;
+    BOOLEAN                                            IEEE8021xState = FALSE;
+    BOOLEAN                                            IEEE8021x_required_keys = FALSE;
+    UCHAR                               wpa_supplicant_enable = 0;
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef SNMP_SUPPORT
+       TX_RTY_CFG_STRUC                        tx_rty_cfg;
+       ULONG                                           ShortRetryLimit, LongRetryLimit;
+       UCHAR                                           ctmp;
+#endif // SNMP_SUPPORT //
+
+
+
+#ifdef DOT11_N_SUPPORT
+       MaxPhyMode = PHY_11N_5G;
+#endif // DOT11_N_SUPPORT //
+
+
+       DBGPRINT(RT_DEBUG_TRACE, ("-->RTMPSetInformation(),     0x%08x\n", cmd&0x7FFF));
+    switch(cmd & 0x7FFF) {
+        case RT_OID_802_11_COUNTRY_REGION:
+            if (wrq->u.data.length < sizeof(UCHAR))
+                Status = -EINVAL;
+                       // Only avaliable when EEPROM not programming
+            else if (!(pAdapter->CommonCfg.CountryRegion & 0x80) && !(pAdapter->CommonCfg.CountryRegionForABand & 0x80))
+            {
+                ULONG   Country;
+                UCHAR  TmpPhy;
+
+                               Status = copy_from_user(&Country, wrq->u.data.pointer, wrq->u.data.length);
+                               pAdapter->CommonCfg.CountryRegion = (UCHAR)(Country & 0x000000FF);
+                               pAdapter->CommonCfg.CountryRegionForABand = (UCHAR)((Country >> 8) & 0x000000FF);
+                TmpPhy = pAdapter->CommonCfg.PhyMode;
+                               pAdapter->CommonCfg.PhyMode = 0xff;
+                               // Build all corresponding channel information
+                               RTMPSetPhyMode(pAdapter, TmpPhy);
+#ifdef DOT11_N_SUPPORT
+                               SetCommonHT(pAdapter);
+#endif // DOT11_N_SUPPORT //
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_COUNTRY_REGION (A:%d  B/G:%d)\n", pAdapter->CommonCfg.CountryRegionForABand,
+                                   pAdapter->CommonCfg.CountryRegion));
+            }
+            break;
+        case OID_802_11_BSSID_LIST_SCAN:
+ #ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               break;
+                       }
+#endif // RALINK_ATE //
+            Now = jiffies;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID_LIST_SCAN, TxCnt = %d \n", pAdapter->RalinkCounters.LastOneSecTotalTxCount));
+
+            if (MONITOR_ON(pAdapter))
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n"));
+                break;
+            }
+
+                       //Benson add 20080527, when radio off, sta don't need to scan
+                       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF))
+                               break;
+
+                       if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+                       {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is scanning now !!!\n"));
+                               pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE;
+                               Status = NDIS_STATUS_SUCCESS;
+                break;
+            }
+
+                       if (pAdapter->RalinkCounters.LastOneSecTotalTxCount > 100)
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, ignore this set::OID_802_11_BSSID_LIST_SCAN\n"));
+                               Status = NDIS_STATUS_SUCCESS;
+                               pAdapter->StaCfg.ScanCnt = 99;          // Prevent auto scan triggered by this OID
+                               break;
+            }
+
+            if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) &&
+                               ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+                               (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+                               (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
+                               (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) &&
+                (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n"));
+                               Status = NDIS_STATUS_SUCCESS;
+                               pAdapter->StaCfg.ScanCnt = 99;          // Prevent auto scan triggered by this OID
+                               break;
+            }
+
+
+            if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+            {
+                RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+            }
+
+            // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+            // this request, because this request is initiated by NDIS.
+            pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+            // Reset allowed scan retries
+            pAdapter->StaCfg.ScanCnt = 0;
+            pAdapter->StaCfg.LastScanTime = Now;
+
+                       pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE;
+            RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+            MlmeEnqueue(pAdapter,
+                        MLME_CNTL_STATE_MACHINE,
+                        OID_802_11_BSSID_LIST_SCAN,
+                        0,
+                        NULL);
+
+            Status = NDIS_STATUS_SUCCESS;
+            StateMachineTouched = TRUE;
+            break;
+        case OID_802_11_SSID:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_SSID))
+                Status = -EINVAL;
+            else
+            {
+               PCHAR pSsidString = NULL;
+                Status = copy_from_user(&Ssid, wrq->u.data.pointer, wrq->u.data.length);
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SSID (Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid));
+                if (Ssid.SsidLength > MAX_LEN_OF_SSID)
+                    Status = -EINVAL;
+                else
+                {
+                       if (Ssid.SsidLength == 0)
+                       {
+                               Set_SSID_Proc(pAdapter, "");
+                       }
+                                       else
+                       {
+                               pSsidString = (CHAR *) kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG);
+                                               if (pSsidString)
+                                               {
+                                                       NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1);
+                                                       NdisMoveMemory(pSsidString, Ssid.Ssid, Ssid.SsidLength);
+                                       Set_SSID_Proc(pAdapter, pSsidString);
+                                                       kfree(pSsidString);
+                                               }
+                                               else
+                                                       Status = -ENOMEM;
+                       }
+                }
+            }
+            break;
+        case OID_802_11_BSSID:
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               break;
+                       }
+#endif // RALINK_ATE //
+            if (wrq->u.data.length != sizeof(NDIS_802_11_MAC_ADDRESS))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&Bssid, wrq->u.data.pointer, wrq->u.data.length);
+
+                // tell CNTL state machine to call NdisMSetInformationComplete() after completing
+                // this request, because this request is initiated by NDIS.
+                pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE;
+
+                               // Prevent to connect AP again in STAMlmePeriodicExec
+                               pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+
+                // Reset allowed scan retries
+                               pAdapter->StaCfg.ScanCnt = 0;
+
+                if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+                {
+                    RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                    DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+                }
+                MlmeEnqueue(pAdapter,
+                            MLME_CNTL_STATE_MACHINE,
+                            OID_802_11_BSSID,
+                            sizeof(NDIS_802_11_MAC_ADDRESS),
+                            (VOID *)&Bssid);
+                Status = NDIS_STATUS_SUCCESS;
+                StateMachineTouched = TRUE;
+
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                        Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
+            }
+            break;
+        case RT_OID_802_11_RADIO:
+            if (wrq->u.data.length != sizeof(BOOLEAN))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&RadioState, wrq->u.data.pointer, wrq->u.data.length);
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RADIO (=%d)\n", RadioState));
+                if (pAdapter->StaCfg.bSwRadio != RadioState)
+                {
+                    pAdapter->StaCfg.bSwRadio = RadioState;
+                    if (pAdapter->StaCfg.bRadio != (pAdapter->StaCfg.bHwRadio && pAdapter->StaCfg.bSwRadio))
+                    {
+                        pAdapter->StaCfg.bRadio = (pAdapter->StaCfg.bHwRadio && pAdapter->StaCfg.bSwRadio);
+                        if (pAdapter->StaCfg.bRadio == TRUE)
+                        {
+                            MlmeRadioOn(pAdapter);
+                            // Update extra information
+                                                       pAdapter->ExtraInfo = EXTRA_INFO_CLEAR;
+                        }
+                        else
+                        {
+                            MlmeRadioOff(pAdapter);
+                            // Update extra information
+                                                       pAdapter->ExtraInfo = SW_RADIO_OFF;
+                        }
+                    }
+                }
+            }
+            break;
+        case RT_OID_802_11_PHY_MODE:
+            if (wrq->u.data.length != sizeof(RT_802_11_PHY_MODE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&PhyMode, wrq->u.data.pointer, wrq->u.data.length);
+                               if (PhyMode <= MaxPhyMode)
+                               {
+                       RTMPSetPhyMode(pAdapter, PhyMode);
+#ifdef DOT11_N_SUPPORT
+                                       SetCommonHT(pAdapter);
+#endif // DOT11_N_SUPPORT //
+                               }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PHY_MODE (=%d)\n", PhyMode));
+            }
+            break;
+        case RT_OID_802_11_STA_CONFIG:
+            if (wrq->u.data.length != sizeof(RT_802_11_STA_CONFIG))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&StaConfig, wrq->u.data.pointer, wrq->u.data.length);
+                pAdapter->CommonCfg.bEnableTxBurst = StaConfig.EnableTxBurst;
+                pAdapter->CommonCfg.UseBGProtection = StaConfig.UseBGProtection;
+                pAdapter->CommonCfg.bUseShortSlotTime = 1; // 2003-10-30 always SHORT SLOT capable
+                if ((pAdapter->CommonCfg.PhyMode != StaConfig.AdhocMode) &&
+                                       (StaConfig.AdhocMode <= MaxPhyMode))
+                {
+                    // allow dynamic change of "USE OFDM rate or not" in ADHOC mode
+                    // if setting changed, need to reset current TX rate as well as BEACON frame format
+                    if (pAdapter->StaCfg.BssType == BSS_ADHOC)
+                    {
+                                               pAdapter->CommonCfg.PhyMode = StaConfig.AdhocMode;
+                       RTMPSetPhyMode(pAdapter, PhyMode);
+                        MlmeUpdateTxRates(pAdapter, FALSE, 0);
+                        MakeIbssBeacon(pAdapter);           // re-build BEACON frame
+                        AsicEnableIbssSync(pAdapter);   // copy to on-chip memory
+                    }
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_STA_CONFIG (Burst=%d, Protection=%ld,ShortSlot=%d\n",
+                                        pAdapter->CommonCfg.bEnableTxBurst,
+                                        pAdapter->CommonCfg.UseBGProtection,
+                                        pAdapter->CommonCfg.bUseShortSlotTime));
+            }
+            break;
+        case OID_802_11_DESIRED_RATES:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_RATES))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&aryRates, wrq->u.data.pointer, wrq->u.data.length);
+                NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES);
+                NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES));
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DESIRED_RATES (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n",
+                    pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1],
+                    pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3],
+                    pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5],
+                    pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] ));
+                // Changing DesiredRate may affect the MAX TX rate we used to TX frames out
+                MlmeUpdateTxRates(pAdapter, FALSE, 0);
+            }
+            break;
+        case RT_OID_802_11_PREAMBLE:
+            if (wrq->u.data.length != sizeof(RT_802_11_PREAMBLE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&Preamble, wrq->u.data.pointer, wrq->u.data.length);
+                if (Preamble == Rt802_11PreambleShort)
+                {
+                    pAdapter->CommonCfg.TxPreamble = Preamble;
+                    MlmeSetTxPreamble(pAdapter, Rt802_11PreambleShort);
+                }
+                else if ((Preamble == Rt802_11PreambleLong) || (Preamble == Rt802_11PreambleAuto))
+                {
+                    // if user wants AUTO, initialize to LONG here, then change according to AP's
+                    // capability upon association.
+                    pAdapter->CommonCfg.TxPreamble = Preamble;
+                    MlmeSetTxPreamble(pAdapter, Rt802_11PreambleLong);
+                }
+                else
+                {
+                    Status = -EINVAL;
+                    break;
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PREAMBLE (=%d)\n", Preamble));
+            }
+            break;
+        case OID_802_11_WEP_STATUS:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_WEP_STATUS))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&WepStatus, wrq->u.data.pointer, wrq->u.data.length);
+                // Since TKIP, AES, WEP are all supported. It should not have any invalid setting
+                if (WepStatus <= Ndis802_11Encryption3KeyAbsent)
+                {
+                    if (pAdapter->StaCfg.WepStatus != WepStatus)
+                    {
+                        // Config has changed
+                        pAdapter->bConfigChanged = TRUE;
+                    }
+                    pAdapter->StaCfg.WepStatus     = WepStatus;
+                    pAdapter->StaCfg.OrigWepStatus = WepStatus;
+                    pAdapter->StaCfg.PairCipher    = WepStatus;
+                       pAdapter->StaCfg.GroupCipher   = WepStatus;
+                }
+                else
+                {
+                    Status  = -EINVAL;
+                    break;
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEP_STATUS (=%d)\n",WepStatus));
+            }
+            break;
+        case OID_802_11_AUTHENTICATION_MODE:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_AUTHENTICATION_MODE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&AuthMode, wrq->u.data.pointer, wrq->u.data.length);
+                if (AuthMode > Ndis802_11AuthModeMax)
+                {
+                    Status  = -EINVAL;
+                    break;
+                }
+                else
+                {
+                    if (pAdapter->StaCfg.AuthMode != AuthMode)
+                    {
+                        // Config has changed
+                        pAdapter->bConfigChanged = TRUE;
+                    }
+                    pAdapter->StaCfg.AuthMode = AuthMode;
+                }
+                pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n",pAdapter->StaCfg.AuthMode));
+            }
+            break;
+        case OID_802_11_INFRASTRUCTURE_MODE:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&BssType, wrq->u.data.pointer, wrq->u.data.length);
+
+                               if (BssType == Ndis802_11IBSS)
+                                       Set_NetworkType_Proc(pAdapter, "Adhoc");
+                               else if (BssType == Ndis802_11Infrastructure)
+                                       Set_NetworkType_Proc(pAdapter, "Infra");
+                               else if (BssType == Ndis802_11Monitor)
+                                       Set_NetworkType_Proc(pAdapter, "Monitor");
+                               else
+                               {
+                                       Status  = -EINVAL;
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_INFRASTRUCTURE_MODE (unknown)\n"));
+                               }
+                       }
+                       break;
+        case OID_802_11_REMOVE_WEP:
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_WEP\n"));
+            if (wrq->u.data.length != sizeof(NDIS_802_11_KEY_INDEX))
+            {
+                               Status = -EINVAL;
+            }
+            else
+            {
+                               KeyIdx = *(NDIS_802_11_KEY_INDEX *) wrq->u.data.pointer;
+
+                               if (KeyIdx & 0x80000000)
+                               {
+                                       // Should never set default bit when remove key
+                                       Status = -EINVAL;
+                               }
+                               else
+                               {
+                                       KeyIdx = KeyIdx & 0x0fffffff;
+                                       if (KeyIdx >= 4){
+                                               Status = -EINVAL;
+                                       }
+                                       else
+                                       {
+                                               pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = 0;
+                                               pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE;
+                                               AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)KeyIdx);
+                                       }
+                               }
+            }
+            break;
+        case RT_OID_802_11_RESET_COUNTERS:
+            NdisZeroMemory(&pAdapter->WlanCounters, sizeof(COUNTER_802_11));
+            NdisZeroMemory(&pAdapter->Counters8023, sizeof(COUNTER_802_3));
+            NdisZeroMemory(&pAdapter->RalinkCounters, sizeof(COUNTER_RALINK));
+            pAdapter->Counters8023.RxNoBuffer   = 0;
+                       pAdapter->Counters8023.GoodReceives = 0;
+                       pAdapter->Counters8023.RxNoBuffer   = 0;
+#ifdef RT2870
+                       pAdapter->BulkOutComplete       = 0;
+                       pAdapter->BulkOutCompleteOther= 0;
+                       pAdapter->BulkOutCompleteCancel = 0;
+                       pAdapter->BulkOutReq = 0;
+                       pAdapter->BulkInReq= 0;
+                       pAdapter->BulkInComplete = 0;
+                       pAdapter->BulkInCompleteFail = 0;
+#endif // RT2870 //
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RESET_COUNTERS \n"));
+            break;
+        case OID_802_11_RTS_THRESHOLD:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_RTS_THRESHOLD))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&RtsThresh, wrq->u.data.pointer, wrq->u.data.length);
+                if (RtsThresh > MAX_RTS_THRESHOLD)
+                    Status  = -EINVAL;
+                else
+                    pAdapter->CommonCfg.RtsThreshold = (USHORT)RtsThresh;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_RTS_THRESHOLD (=%ld)\n",RtsThresh));
+            break;
+        case OID_802_11_FRAGMENTATION_THRESHOLD:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_FRAGMENTATION_THRESHOLD))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&FragThresh, wrq->u.data.pointer, wrq->u.data.length);
+                pAdapter->CommonCfg.bUseZeroToDisableFragment = FALSE;
+                if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD)
+                {
+                    if (FragThresh == 0)
+                    {
+                        pAdapter->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;
+                        pAdapter->CommonCfg.bUseZeroToDisableFragment = TRUE;
+                    }
+                    else
+                        Status  = -EINVAL;
+                }
+                else
+                    pAdapter->CommonCfg.FragmentThreshold = (USHORT)FragThresh;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_FRAGMENTATION_THRESHOLD (=%ld) \n",FragThresh));
+            break;
+        case OID_802_11_POWER_MODE:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_POWER_MODE))
+                Status = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&PowerMode, wrq->u.data.pointer, wrq->u.data.length);
+                if (PowerMode == Ndis802_11PowerModeCAM)
+                       Set_PSMode_Proc(pAdapter, "CAM");
+                else if (PowerMode == Ndis802_11PowerModeMAX_PSP)
+                       Set_PSMode_Proc(pAdapter, "Max_PSP");
+                else if (PowerMode == Ndis802_11PowerModeFast_PSP)
+                                       Set_PSMode_Proc(pAdapter, "Fast_PSP");
+                else if (PowerMode == Ndis802_11PowerModeLegacy_PSP)
+                                       Set_PSMode_Proc(pAdapter, "Legacy_PSP");
+                else
+                    Status = -EINVAL;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_POWER_MODE (=%d)\n",PowerMode));
+            break;
+         case RT_OID_802_11_TX_POWER_LEVEL_1:
+                       if (wrq->u.data.length  < sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&PowerTemp, wrq->u.data.pointer, wrq->u.data.length);
+                               if (PowerTemp > 100)
+                                       PowerTemp = 0xffffffff;  // AUTO
+                               pAdapter->CommonCfg.TxPowerDefault = PowerTemp; //keep current setting.
+                                       pAdapter->CommonCfg.TxPowerPercentage = pAdapter->CommonCfg.TxPowerDefault;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAdapter->CommonCfg.TxPowerPercentage));
+                       }
+               break;
+               case OID_802_11_NETWORK_TYPE_IN_USE:
+                       if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_TYPE))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&NetType, wrq->u.data.pointer, wrq->u.data.length);
+
+                               if (NetType == Ndis802_11DS)
+                                       RTMPSetPhyMode(pAdapter, PHY_11B);
+                               else if (NetType == Ndis802_11OFDM24)
+                                       RTMPSetPhyMode(pAdapter, PHY_11BG_MIXED);
+                               else if (NetType == Ndis802_11OFDM5)
+                                       RTMPSetPhyMode(pAdapter, PHY_11A);
+                               else
+                                       Status = -EINVAL;
+#ifdef DOT11_N_SUPPORT
+                               if (Status == NDIS_STATUS_SUCCESS)
+                                       SetCommonHT(pAdapter);
+#endif // DOT11_N_SUPPORT //
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_NETWORK_TYPE_IN_USE (=%d)\n",NetType));
+                   }
+                       break;
+        // For WPA PSK PMK key
+        case RT_OID_802_11_ADD_WPA:
+            pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+            if(pKey == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+
+            Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (pKey->Length != wrq->u.data.length)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!!\n"));
+            }
+            else
+            {
+                if ((pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) &&
+                                   (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) &&
+                                   (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) )
+                {
+                    Status = -EOPNOTSUPP;
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!! [AuthMode != WPAPSK/WPA2PSK/WPANONE]\n"));
+                }
+                else if ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+                                                (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
+                                                (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) )     // Only for WPA PSK mode
+                               {
+                    NdisMoveMemory(pAdapter->StaCfg.PMK, &pKey->KeyMaterial, pKey->KeyLength);
+                    // Use RaConfig as PSK agent.
+                    // Start STA supplicant state machine
+                    if (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone)
+                        pAdapter->StaCfg.WpaState = SS_START;
+
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength));
+                }
+                else
+                {
+                    pAdapter->StaCfg.WpaState = SS_NOTUSE;
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength));
+                }
+            }
+            kfree(pKey);
+            break;
+        case OID_802_11_REMOVE_KEY:
+            pRemoveKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+            if(pRemoveKey == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+
+            Status = copy_from_user(pRemoveKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (pRemoveKey->Length != wrq->u.data.length)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!\n"));
+            }
+            else
+            {
+                if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+                {
+                    RTMPWPARemoveKeyProc(pAdapter, pRemoveKey);
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Remove WPA Key!!\n"));
+                }
+                else
+                {
+                    KeyIdx = pRemoveKey->KeyIndex;
+
+                    if (KeyIdx & 0x80000000)
+                    {
+                        // Should never set default bit when remove key
+                        Status  = -EINVAL;
+                        DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(Should never set default bit when remove key)\n"));
+                    }
+                    else
+                    {
+                        KeyIdx = KeyIdx & 0x0fffffff;
+                        if (KeyIdx > 3)
+                        {
+                            Status  = -EINVAL;
+                            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(KeyId[%d] out of range)\n", KeyIdx));
+                        }
+                        else
+                        {
+                            pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = 0;
+                            pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE;
+                            AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)KeyIdx);
+                            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY (id=0x%x, Len=%d-byte)\n", pRemoveKey->KeyIndex, pRemoveKey->Length));
+                        }
+                    }
+                }
+            }
+            kfree(pRemoveKey);
+            break;
+        // New for WPA
+        case OID_802_11_ADD_KEY:
+            pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+            if(pKey == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+            Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (pKey->Length != wrq->u.data.length)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY, Failed!!\n"));
+            }
+            else
+            {
+                RTMPAddKey(pAdapter, pKey);
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength));
+            }
+            kfree(pKey);
+            break;
+        case OID_802_11_CONFIGURATION:
+            if (wrq->u.data.length != sizeof(NDIS_802_11_CONFIGURATION))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&Config, wrq->u.data.pointer, wrq->u.data.length);
+                pConfig = &Config;
+
+                if ((pConfig->BeaconPeriod >= 20) && (pConfig->BeaconPeriod <=400))
+                     pAdapter->CommonCfg.BeaconPeriod = (USHORT) pConfig->BeaconPeriod;
+
+                pAdapter->StaActive.AtimWin = (USHORT) pConfig->ATIMWindow;
+                MAP_KHZ_TO_CHANNEL_ID(pConfig->DSConfig, pAdapter->CommonCfg.Channel);
+                //
+                               // Save the channel on MlmeAux for CntlOidRTBssidProc used.
+                               //
+                               pAdapter->MlmeAux.Channel = pAdapter->CommonCfg.Channel;
+
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CONFIGURATION (BeacnPeriod=%ld,AtimW=%ld,Ch=%d)\n",
+                    pConfig->BeaconPeriod, pConfig->ATIMWindow, pAdapter->CommonCfg.Channel));
+                // Config has changed
+                pAdapter->bConfigChanged = TRUE;
+            }
+            break;
+#ifdef DOT11_N_SUPPORT
+               case RT_OID_802_11_SET_HT_PHYMODE:
+                       if (wrq->u.data.length  != sizeof(OID_SET_HT_PHYMODE))
+                               Status = -EINVAL;
+                       else
+                       {
+                           POID_SET_HT_PHYMODE pHTPhyMode = &HT_PhyMode;
+
+                               Status = copy_from_user(&HT_PhyMode, wrq->u.data.pointer, wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::pHTPhyMode      (PhyMode = %d,TransmitNo = %d, HtMode = %d,     ExtOffset =     %d , MCS = %d, BW =     %d,     STBC = %d, SHORTGI = %d) \n",
+                               pHTPhyMode->PhyMode, pHTPhyMode->TransmitNo,pHTPhyMode->HtMode,pHTPhyMode->ExtOffset,
+                               pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC,      pHTPhyMode->SHORTGI));
+                               if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+                                       RTMPSetHT(pAdapter,     pHTPhyMode);
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_HT_PHYMODE(MCS=%d,BW=%d,SGI=%d,STBC=%d)\n",
+                               pAdapter->StaCfg.HTPhyMode.field.MCS, pAdapter->StaCfg.HTPhyMode.field.BW, pAdapter->StaCfg.HTPhyMode.field.ShortGI,
+                               pAdapter->StaCfg.HTPhyMode.field.STBC));
+                       break;
+#endif // DOT11_N_SUPPORT //
+               case RT_OID_802_11_SET_APSD_SETTING:
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               ULONG apsd ;
+                               Status = copy_from_user(&apsd, wrq->u.data.pointer,     wrq->u.data.length);
+
+                               /*-------------------------------------------------------------------
+                               |B31~B7 |       B6~B5    |       B4      |       B3      |      B2       |      B1       |         B0           |
+                               ---------------------------------------------------------------------
+                               | Rsvd  | Max SP Len | AC_VO | AC_VI | AC_BK | AC_BE | APSD     Capable |
+                               ---------------------------------------------------------------------*/
+                               pAdapter->CommonCfg.bAPSDCapable = (apsd & 0x00000001) ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_BE = ((apsd & 0x00000002) >> 1)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_BK = ((apsd & 0x00000004) >> 2)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_VI = ((apsd & 0x00000008) >> 3)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.bAPSDAC_VO = ((apsd & 0x00000010) >> 4)     ? TRUE : FALSE;
+                               pAdapter->CommonCfg.MaxSPLength = (UCHAR)((apsd & 0x00000060) >> 5);
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_SETTING (apsd=0x%lx, APSDCap=%d, [BE,BK,VI,VO]=[%d/%d/%d/%d],    MaxSPLen=%d)\n", apsd, pAdapter->CommonCfg.bAPSDCapable,
+                                       pAdapter->CommonCfg.bAPSDAC_BE, pAdapter->CommonCfg.bAPSDAC_BK, pAdapter->CommonCfg.bAPSDAC_VI, pAdapter->CommonCfg.bAPSDAC_VO, pAdapter->CommonCfg.MaxSPLength));
+                       }
+                       break;
+
+               case RT_OID_802_11_SET_APSD_PSM:
+                       if (wrq->u.data.length  != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               // Driver needs to notify AP when PSM changes
+                               Status = copy_from_user(&pAdapter->CommonCfg.bAPSDForcePowerSave, wrq->u.data.pointer, wrq->u.data.length);
+                               if (pAdapter->CommonCfg.bAPSDForcePowerSave     != pAdapter->StaCfg.Psm)
+                               {
+                                       MlmeSetPsmBit(pAdapter, pAdapter->CommonCfg.bAPSDForcePowerSave);
+                                       RTMPSendNullFrame(pAdapter,     pAdapter->CommonCfg.TxRate,     TRUE);
+                               }
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_PSM (bAPSDForcePowerSave:%d)\n", pAdapter->CommonCfg.bAPSDForcePowerSave));
+                       }
+                       break;
+#ifdef QOS_DLS_SUPPORT
+               case RT_OID_802_11_SET_DLS:
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               BOOLEAN oldvalue = pAdapter->CommonCfg.bDLSCapable;
+                               Status = copy_from_user(&pAdapter->CommonCfg.bDLSCapable, wrq->u.data.pointer, wrq->u.data.length);
+                               if (oldvalue && !pAdapter->CommonCfg.bDLSCapable)
+                               {
+                                       int     i;
+                                       // tear down local dls table entry
+                                       for     (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+                                       {
+                                               if (pAdapter->StaCfg.DLSEntry[i].Valid && (pAdapter->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+                                               {
+                                                       pAdapter->StaCfg.DLSEntry[i].Status     = DLS_NONE;
+                                                       pAdapter->StaCfg.DLSEntry[i].Valid      = FALSE;
+                                                       RTMPSendDLSTearDownFrame(pAdapter, pAdapter->StaCfg.DLSEntry[i].MacAddr);
+                                               }
+                                       }
+
+                                       // tear down peer dls table     entry
+                                       for     (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+                                       {
+                                               if (pAdapter->StaCfg.DLSEntry[i].Valid && (pAdapter->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+                                               {
+                                                       pAdapter->StaCfg.DLSEntry[i].Status     = DLS_NONE;
+                                                       pAdapter->StaCfg.DLSEntry[i].Valid      = FALSE;
+                                                       RTMPSendDLSTearDownFrame(pAdapter, pAdapter->StaCfg.DLSEntry[i].MacAddr);
+                                               }
+                                       }
+                               }
+
+                               DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS (=%d)\n", pAdapter->CommonCfg.bDLSCapable));
+                       }
+                       break;
+
+               case RT_OID_802_11_SET_DLS_PARAM:
+                       if (wrq->u.data.length  != sizeof(RT_802_11_DLS_UI))
+                               Status = -EINVAL;
+                       else
+                       {
+                               RT_802_11_DLS   Dls;
+
+                               NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
+                               RTMPMoveMemory(&Dls, wrq->u.data.pointer, sizeof(RT_802_11_DLS_UI));
+                               MlmeEnqueue(pAdapter,
+                                                       MLME_CNTL_STATE_MACHINE,
+                                                       RT_OID_802_11_SET_DLS_PARAM,
+                                                       sizeof(RT_802_11_DLS),
+                                                       &Dls);
+                               DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS_PARAM \n"));
+                       }
+                       break;
+#endif // QOS_DLS_SUPPORT //
+               case RT_OID_802_11_SET_WMM:
+                       if (wrq->u.data.length  != sizeof(BOOLEAN))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&pAdapter->CommonCfg.bWmmCapable, wrq->u.data.pointer, wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_WMM (=%d)     \n", pAdapter->CommonCfg.bWmmCapable));
+                       }
+                       break;
+
+               case OID_802_11_DISASSOCIATE:
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               break;
+                       }
+#endif // RALINK_ATE //
+                       //
+                       // Set NdisRadioStateOff to     TRUE, instead of called MlmeRadioOff.
+                       // Later on, NDIS_802_11_BSSID_LIST_EX->NumberOfItems should be 0
+                       // when query OID_802_11_BSSID_LIST.
+                       //
+                       // TRUE:  NumberOfItems will set to     0.
+                       // FALSE: NumberOfItems no change.
+                       //
+                       pAdapter->CommonCfg.NdisRadioStateOff = TRUE;
+                       // Set to immediately send the media disconnect event
+                       pAdapter->MlmeAux.CurrReqIsFromNdis     = TRUE;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DISASSOCIATE \n"));
+
+                       if (INFRA_ON(pAdapter))
+                       {
+                               if (pAdapter->Mlme.CntlMachine.CurrState !=     CNTL_IDLE)
+                               {
+                                       RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME     busy, reset     MLME state machine !!!\n"));
+                               }
+
+                               MlmeEnqueue(pAdapter,
+                                       MLME_CNTL_STATE_MACHINE,
+                                       OID_802_11_DISASSOCIATE,
+                                       0,
+                                       NULL);
+
+                               StateMachineTouched     = TRUE;
+                       }
+                       break;
+
+#ifdef DOT11_N_SUPPORT
+               case RT_OID_802_11_SET_IMME_BA_CAP:
+                               if (wrq->u.data.length != sizeof(OID_BACAP_STRUC))
+                                       Status = -EINVAL;
+                               else
+                               {
+                                       OID_BACAP_STRUC Orde ;
+                                       Status = copy_from_user(&Orde, wrq->u.data.pointer, wrq->u.data.length);
+                                       if (Orde.Policy > BA_NOTUSE)
+                                       {
+                                               Status = NDIS_STATUS_INVALID_DATA;
+                                       }
+                                       else if (Orde.Policy == BA_NOTUSE)
+                                       {
+                                               pAdapter->CommonCfg.BACapability.field.Policy = BA_NOTUSE;
+                                               pAdapter->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MimoPs= Orde.MMPSmode;
+                                               pAdapter->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode;
+                                               // UPdata to HT IE
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode;
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize;
+                                               pAdapter->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity;
+                                       }
+                                       else
+                                       {
+                        pAdapter->CommonCfg.BACapability.field.AutoBA = Orde.AutoBA;
+                                               pAdapter->CommonCfg.BACapability.field.Policy = IMMED_BA; // we only support immediate BA.
+                                               pAdapter->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable;
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize;
+                                               pAdapter->CommonCfg.DesiredHtPhy.MimoPs = Orde.MMPSmode;
+                                               pAdapter->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode;
+
+                                               // UPdata to HT IE
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode;
+                                               pAdapter->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize;
+                                               pAdapter->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity;
+
+                                               if (pAdapter->CommonCfg.BACapability.field.RxBAWinLimit > MAX_RX_REORDERBUF)
+                                                       pAdapter->CommonCfg.BACapability.field.RxBAWinLimit = MAX_RX_REORDERBUF;
+
+                                       }
+
+                                       pAdapter->CommonCfg.REGBACapability.word = pAdapter->CommonCfg.BACapability.word;
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::(Orde.AutoBA = %d) (Policy=%d)(ReBAWinLimit=%d)(TxBAWinLimit=%d)(AutoMode=%d)\n",Orde.AutoBA, pAdapter->CommonCfg.BACapability.field.Policy,
+                                               pAdapter->CommonCfg.BACapability.field.RxBAWinLimit,pAdapter->CommonCfg.BACapability.field.TxBAWinLimit, pAdapter->CommonCfg.BACapability.field.AutoBA));
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::(MimoPs = %d)(AmsduEnable = %d) (AmsduSize=%d)(MpduDensity=%d)\n",pAdapter->CommonCfg.DesiredHtPhy.MimoPs, pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable,
+                                               pAdapter->CommonCfg.DesiredHtPhy.AmsduSize, pAdapter->CommonCfg.DesiredHtPhy.MpduDensity));
+                               }
+
+                               break;
+               case RT_OID_802_11_ADD_IMME_BA:
+                       DBGPRINT(RT_DEBUG_TRACE, (" Set :: RT_OID_802_11_ADD_IMME_BA \n"));
+                       if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY))
+                                       Status = -EINVAL;
+                       else
+                       {
+                               UCHAR                   index;
+                               OID_ADD_BA_ENTRY    BA;
+                               MAC_TABLE_ENTRY     *pEntry;
+
+                               Status = copy_from_user(&BA, wrq->u.data.pointer, wrq->u.data.length);
+                               if (BA.TID > 15)
+                               {
+                                       Status = NDIS_STATUS_INVALID_DATA;
+                                       break;
+                               }
+                               else
+                               {
+                                       //BATableInsertEntry
+                                       //As ad-hoc mode, BA pair is not limited to only BSSID. so add via OID.
+                                       index = BA.TID;
+                                       // in ad hoc mode, when adding BA pair, we should insert this entry into MACEntry too
+                                       pEntry = MacTableLookup(pAdapter, BA.MACAddr);
+                                       if (!pEntry)
+                                       {
+                                               DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_802_11_ADD_IMME_BA. break on no connection.----:%x:%x\n", BA.MACAddr[4], BA.MACAddr[5]));
+                                               break;
+                                       }
+                                       if (BA.IsRecipient == FALSE)
+                                       {
+                                           if (pEntry->bIAmBadAtheros == TRUE)
+                                                       pAdapter->CommonCfg.BACapability.field.RxBAWinLimit = 0x10;
+
+                                               BAOriSessionSetUp(pAdapter, pEntry, index, 0, 100, TRUE);
+                                       }
+                                       else
+                                       {
+                                               //BATableInsertEntry(pAdapter, pEntry->Aid, BA.MACAddr, 0, 0xffff, BA.TID, BA.nMSDU, BA.IsRecipient);
+                                       }
+
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_IMME_BA. Rec = %d. Mac = %x:%x:%x:%x:%x:%x . \n",
+                                               BA.IsRecipient, BA.MACAddr[0], BA.MACAddr[1], BA.MACAddr[2], BA.MACAddr[2]
+                                               , BA.MACAddr[4], BA.MACAddr[5]));
+                               }
+                       }
+                       break;
+
+               case RT_OID_802_11_TEAR_IMME_BA:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA \n"));
+                       if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY))
+                                       Status = -EINVAL;
+                       else
+                       {
+                               POID_ADD_BA_ENTRY       pBA;
+                               MAC_TABLE_ENTRY *pEntry;
+
+                               pBA = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+
+                               if (pBA == NULL)
+                               {
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA kmalloc() can't allocate enough memory\n"));
+                                       Status = NDIS_STATUS_FAILURE;
+                               }
+                               else
+                               {
+                                       Status = copy_from_user(pBA, wrq->u.data.pointer, wrq->u.data.length);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA(TID=%d, bAllTid=%d)\n", pBA->TID, pBA->bAllTid));
+
+                                       if (!pBA->bAllTid && (pBA->TID > NUM_OF_TID))
+                                       {
+                                               Status = NDIS_STATUS_INVALID_DATA;
+                                               break;
+                                       }
+
+                                       if (pBA->IsRecipient == FALSE)
+                                       {
+                                               pEntry = MacTableLookup(pAdapter, pBA->MACAddr);
+                                               DBGPRINT(RT_DEBUG_TRACE, (" pBA->IsRecipient == FALSE\n"));
+                                               if (pEntry)
+                                               {
+                                                       DBGPRINT(RT_DEBUG_TRACE, (" pBA->pEntry\n"));
+                                                       BAOriSessionTearDown(pAdapter, pEntry->Aid, pBA->TID, FALSE, TRUE);
+                                               }
+                                               else
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n"));
+                                       }
+                                       else
+                                       {
+                                               pEntry = MacTableLookup(pAdapter, pBA->MACAddr);
+                                               if (pEntry)
+                                               {
+                                                       BARecSessionTearDown( pAdapter, (UCHAR)pEntry->Aid, pBA->TID, TRUE);
+                                               }
+                                               else
+                                                       DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n"));
+                                       }
+                                       kfree(pBA);
+                               }
+            }
+            break;
+#endif // DOT11_N_SUPPORT //
+
+        // For WPA_SUPPLICANT to set static wep key
+       case OID_802_11_ADD_WEP:
+           pWepKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+
+           if(pWepKey == NULL)
+            {
+                Status = -ENOMEM;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed!!\n"));
+                break;
+            }
+            Status = copy_from_user(pWepKey, wrq->u.data.pointer, wrq->u.data.length);
+            if (Status)
+            {
+                Status  = -EINVAL;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (length mismatch)!!\n"));
+            }
+            else
+            {
+                       KeyIdx = pWepKey->KeyIndex & 0x0fffffff;
+                // KeyIdx must be 0 ~ 3
+                if (KeyIdx > 4)
+                       {
+                    Status  = -EINVAL;
+                    DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (KeyIdx must be smaller than 4)!!\n"));
+                }
+                else
+                {
+                    UCHAR CipherAlg = 0;
+                    PUCHAR Key;
+
+                    // set key material and key length
+                    NdisZeroMemory(pAdapter->SharedKey[BSS0][KeyIdx].Key, 16);
+                    pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength;
+                    NdisMoveMemory(pAdapter->SharedKey[BSS0][KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength);
+
+                    switch(pWepKey->KeyLength)
+                    {
+                        case 5:
+                            CipherAlg = CIPHER_WEP64;
+                            break;
+                        case 13:
+                            CipherAlg = CIPHER_WEP128;
+                            break;
+                        default:
+                            DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, only support CIPHER_WEP64(len:5) & CIPHER_WEP128(len:13)!!\n"));
+                            Status = -EINVAL;
+                            break;
+                    }
+                    pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CipherAlg;
+
+                    // Default key for tx (shared key)
+                    if (pWepKey->KeyIndex & 0x80000000)
+                    {
+#ifdef WPA_SUPPLICANT_SUPPORT
+                        // set key material and key length
+                        NdisZeroMemory(pAdapter->StaCfg.DesireSharedKey[KeyIdx].Key, 16);
+                        pAdapter->StaCfg.DesireSharedKey[KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength;
+                        NdisMoveMemory(pAdapter->StaCfg.DesireSharedKey[KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength);
+                        pAdapter->StaCfg.DesireSharedKeyId = KeyIdx;
+                        pAdapter->StaCfg.DesireSharedKey[KeyIdx].CipherAlg = CipherAlg;
+#endif // WPA_SUPPLICANT_SUPPORT //
+                        pAdapter->StaCfg.DefaultKeyId = (UCHAR) KeyIdx;
+                    }
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+                    if (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)
+#endif // WPA_SUPPLICANT_SUPPORT
+                    {
+                        Key = pAdapter->SharedKey[BSS0][KeyIdx].Key;
+
+                        // Set key material and cipherAlg to Asic
+                                       AsicAddSharedKeyEntry(pAdapter, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL);
+
+                        if (pWepKey->KeyIndex & 0x80000000)
+                        {
+                            PMAC_TABLE_ENTRY pEntry = &pAdapter->MacTab.Content[BSSID_WCID];
+                            // Assign group key info
+                                               RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, NULL);
+                                               // Assign pairwise key info
+                                               RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, pEntry);
+                        }
+                    }
+                                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP (id=0x%x, Len=%d-byte), %s\n", pWepKey->KeyIndex, pWepKey->KeyLength, (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) ? "Port Secured":"Port NOT Secured"));
+                               }
+            }
+            kfree(pWepKey);
+            break;
+#ifdef WPA_SUPPLICANT_SUPPORT
+           case OID_SET_COUNTERMEASURES:
+            if (wrq->u.data.length != sizeof(int))
+                Status  = -EINVAL;
+            else
+            {
+                int enabled = 0;
+                Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length);
+                if (enabled == 1)
+                    pAdapter->StaCfg.bBlockAssoc = TRUE;
+                else
+                    // WPA MIC error should block association attempt for 60 seconds
+                    pAdapter->StaCfg.bBlockAssoc = FALSE;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_SET_COUNTERMEASURES bBlockAssoc=%s\n", pAdapter->StaCfg.bBlockAssoc ? "TRUE":"FALSE"));
+            }
+               break;
+        case RT_OID_WPA_SUPPLICANT_SUPPORT:
+                       if (wrq->u.data.length != sizeof(UCHAR))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&wpa_supplicant_enable, wrq->u.data.pointer, wrq->u.data.length);
+                       pAdapter->StaCfg.WpaSupplicantUP = wpa_supplicant_enable;
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAdapter->StaCfg.WpaSupplicantUP));
+                       }
+            break;
+        case OID_802_11_DEAUTHENTICATION:
+            if (wrq->u.data.length != sizeof(MLME_DEAUTH_REQ_STRUCT))
+                Status  = -EINVAL;
+            else
+            {
+                MLME_DEAUTH_REQ_STRUCT      *pInfo;
+                               MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+
+                pInfo = (MLME_DEAUTH_REQ_STRUCT *) MsgElem->Msg;
+                Status = copy_from_user(pInfo, wrq->u.data.pointer, wrq->u.data.length);
+                MlmeDeauthReqAction(pAdapter, MsgElem);
+                               kfree(MsgElem);
+
+                if (INFRA_ON(pAdapter))
+                {
+                    LinkDown(pAdapter, FALSE);
+                    pAdapter->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+                }
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION (Reason=%d)\n", pInfo->Reason));
+            }
+            break;
+        case OID_802_11_DROP_UNENCRYPTED:
+            if (wrq->u.data.length != sizeof(int))
+                Status  = -EINVAL;
+            else
+            {
+                int enabled = 0;
+                Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length);
+                if (enabled == 1)
+                    pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+                else
+                    pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+                               NdisAcquireSpinLock(&pAdapter->MacTabLock);
+                               pAdapter->MacTab.Content[BSSID_WCID].PortSecured = pAdapter->StaCfg.PortSecured;
+                               NdisReleaseSpinLock(&pAdapter->MacTabLock);
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DROP_UNENCRYPTED (=%d)\n", enabled));
+            }
+            break;
+        case OID_802_11_SET_IEEE8021X:
+            if (wrq->u.data.length != sizeof(BOOLEAN))
+                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&IEEE8021xState, wrq->u.data.pointer, wrq->u.data.length);
+                       pAdapter->StaCfg.IEEE8021X = IEEE8021xState;
+                DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X (=%d)\n", IEEE8021xState));
+            }
+            break;
+        case OID_802_11_SET_IEEE8021X_REQUIRE_KEY:
+                       if (wrq->u.data.length != sizeof(BOOLEAN))
+                                Status  = -EINVAL;
+            else
+            {
+                Status = copy_from_user(&IEEE8021x_required_keys, wrq->u.data.pointer, wrq->u.data.length);
+                               pAdapter->StaCfg.IEEE8021x_required_keys = IEEE8021x_required_keys;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X_REQUIRE_KEY (%d)\n", IEEE8021x_required_keys));
+                       }
+                       break;
+        case OID_802_11_PMKID:
+               pPmkId = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG);
+
+               if(pPmkId == NULL) {
+                Status = -ENOMEM;
+                break;
+            }
+            Status = copy_from_user(pPmkId, wrq->u.data.pointer, wrq->u.data.length);
+
+               // check the PMKID information
+               if (pPmkId->BSSIDInfoCount == 0)
+                NdisZeroMemory(pAdapter->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO);
+               else
+               {
+                       PBSSID_INFO     pBssIdInfo;
+                       UINT            BssIdx;
+                       UINT            CachedIdx;
+
+                       for (BssIdx = 0; BssIdx < pPmkId->BSSIDInfoCount; BssIdx++)
+                       {
+                               // point to the indexed BSSID_INFO structure
+                               pBssIdInfo = (PBSSID_INFO) ((PUCHAR) pPmkId + 2 * sizeof(UINT) + BssIdx * sizeof(BSSID_INFO));
+                               // Find the entry in the saved data base.
+                               for (CachedIdx = 0; CachedIdx < pAdapter->StaCfg.SavedPMKNum; CachedIdx++)
+                               {
+                                       // compare the BSSID
+                                       if (NdisEqualMemory(pBssIdInfo->BSSID, pAdapter->StaCfg.SavedPMK[CachedIdx].BSSID, sizeof(NDIS_802_11_MAC_ADDRESS)))
+                                               break;
+                               }
+
+                               // Found, replace it
+                               if (CachedIdx < PMKID_NO)
+                               {
+                                       DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx));
+                                       NdisMoveMemory(&pAdapter->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO));
+                                       pAdapter->StaCfg.SavedPMKNum++;
+                               }
+                               // Not found, replace the last one
+                               else
+                               {
+                                       // Randomly replace one
+                                       CachedIdx = (pBssIdInfo->BSSID[5] % PMKID_NO);
+                                       DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx));
+                                       NdisMoveMemory(&pAdapter->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO));
+                               }
+                       }
+                       }
+                       if(pPmkId)
+                               kfree(pPmkId);
+               break;
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+
+
+#ifdef SNMP_SUPPORT
+               case OID_802_11_SHORTRETRYLIMIT:
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&ShortRetryLimit, wrq->u.data.pointer, wrq->u.data.length);
+                               RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                               tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit;
+                               RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SHORTRETRYLIMIT (tx_rty_cfg.field.ShortRetryLimit=%d, ShortRetryLimit=%ld)\n", tx_rty_cfg.field.ShortRtyLimit, ShortRetryLimit));
+                       }
+                       break;
+
+               case OID_802_11_LONGRETRYLIMIT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT \n"));
+                       if (wrq->u.data.length != sizeof(ULONG))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&LongRetryLimit, wrq->u.data.pointer, wrq->u.data.length);
+                               RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                               tx_rty_cfg.field.LongRtyLimit = LongRetryLimit;
+                               RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT (tx_rty_cfg.field.LongRetryLimit= %d,LongRetryLimit=%ld)\n", tx_rty_cfg.field.LongRtyLimit, LongRetryLimit));
+                       }
+                       break;
+
+               case OID_802_11_WEPDEFAULTKEYVALUE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE\n"));
+                       pKey = kmalloc(wrq->u.data.length, GFP_KERNEL);
+                       Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length);
+                       //pKey = &WepKey;
+
+                       if ( pKey->Length != wrq->u.data.length)
+                       {
+                               Status = -EINVAL;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE, Failed!!\n"));
+                       }
+                       KeyIdx = pKey->KeyIndex & 0x0fffffff;
+                       DBGPRINT(RT_DEBUG_TRACE,("pKey->KeyIndex =%d, pKey->KeyLength=%d\n", pKey->KeyIndex, pKey->KeyLength));
+
+                       // it is a shared key
+                       if (KeyIdx > 4)
+                               Status = -EINVAL;
+                       else
+                       {
+                               pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen = (UCHAR) pKey->KeyLength;
+                               NdisMoveMemory(&pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, &pKey->KeyMaterial, pKey->KeyLength);
+                               if (pKey->KeyIndex & 0x80000000)
+                               {
+                                       // Default key for tx (shared key)
+                                       pAdapter->StaCfg.DefaultKeyId = (UCHAR) KeyIdx;
+                               }
+                               //RestartAPIsRequired = TRUE;
+                       }
+                       break;
+
+
+               case OID_802_11_WEPDEFAULTKEYID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYID \n"));
+
+                       if (wrq->u.data.length != sizeof(UCHAR))
+                               Status = -EINVAL;
+                       else
+                               Status = copy_from_user(&pAdapter->StaCfg.DefaultKeyId, wrq->u.data.pointer, wrq->u.data.length);
+
+                       break;
+
+
+               case OID_802_11_CURRENTCHANNEL:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CURRENTCHANNEL \n"));
+                       if (wrq->u.data.length != sizeof(UCHAR))
+                               Status = -EINVAL;
+                       else
+                       {
+                               Status = copy_from_user(&ctmp, wrq->u.data.pointer, wrq->u.data.length);
+                               sprintf(&ctmp,"%d", ctmp);
+                               Set_Channel_Proc(pAdapter, &ctmp);
+                       }
+                       break;
+#endif
+
+
+
+        default:
+            DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd));
+            Status = -EOPNOTSUPP;
+            break;
+    }
+
+
+    return Status;
+}
+
+INT RTMPQueryInformation(
+    IN  PRTMP_ADAPTER pAdapter,
+    IN  OUT struct ifreq    *rq,
+    IN  INT                 cmd)
+{
+    struct iwreq                        *wrq = (struct iwreq *) rq;
+    NDIS_802_11_BSSID_LIST_EX           *pBssidList = NULL;
+    PNDIS_WLAN_BSSID_EX                 pBss;
+    NDIS_802_11_SSID                    Ssid;
+    NDIS_802_11_CONFIGURATION           *pConfiguration = NULL;
+    RT_802_11_LINK_STATUS               *pLinkStatus = NULL;
+    RT_802_11_STA_CONFIG                *pStaConfig = NULL;
+    NDIS_802_11_STATISTICS              *pStatistics = NULL;
+    NDIS_802_11_RTS_THRESHOLD           RtsThresh;
+    NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh;
+    NDIS_802_11_POWER_MODE              PowerMode;
+    NDIS_802_11_NETWORK_INFRASTRUCTURE  BssType;
+    RT_802_11_PREAMBLE                  PreamType;
+    NDIS_802_11_AUTHENTICATION_MODE     AuthMode;
+    NDIS_802_11_WEP_STATUS              WepStatus;
+    NDIS_MEDIA_STATE                    MediaState;
+    ULONG                               BssBufSize, ulInfo=0, NetworkTypeList[4], apsd = 0;
+    USHORT                              BssLen = 0;
+    PUCHAR                              pBuf = NULL, pPtr;
+    INT                                 Status = NDIS_STATUS_SUCCESS;
+    UINT                                we_version_compiled;
+    UCHAR                               i, Padding = 0;
+    BOOLEAN                             RadioState;
+       UCHAR   driverVersion[8];
+    OID_SET_HT_PHYMODE                         *pHTPhyMode = NULL;
+
+
+#ifdef SNMP_SUPPORT
+       //for snmp, kathy
+       DefaultKeyIdxValue                      *pKeyIdxValue;
+       INT                                                     valueLen;
+       TX_RTY_CFG_STRUC                        tx_rty_cfg;
+       ULONG                                           ShortRetryLimit, LongRetryLimit;
+       UCHAR                                           tmp[64];
+#endif //SNMP
+
+    switch(cmd)
+    {
+        case RT_OID_DEVICE_NAME:
+            wrq->u.data.length = sizeof(STA_NIC_DEVICE_NAME);
+            Status = copy_to_user(wrq->u.data.pointer, STA_NIC_DEVICE_NAME, wrq->u.data.length);
+            break;
+        case RT_OID_VERSION_INFO:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_VERSION_INFO \n"));
+                       wrq->u.data.length = 8*sizeof(UCHAR);
+                       sprintf(&driverVersion[0], "%s", STA_DRIVER_VERSION);
+                       driverVersion[7] = '\0';
+                       if (copy_to_user(wrq->u.data.pointer, &driverVersion, wrq->u.data.length))
+            {
+                               Status = -EFAULT;
+            }
+            break;
+#ifdef RALINK_ATE
+               case RT_QUERY_ATE_TXDONE_COUNT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_QUERY_ATE_TXDONE_COUNT \n"));
+                       wrq->u.data.length = sizeof(UINT32);
+                       if (copy_to_user(wrq->u.data.pointer, &pAdapter->ate.TxDoneCount, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+                       break;
+#endif // RALINK_ATE //
+        case OID_802_11_BSSID_LIST:
+            if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+            {
+               /*
+                * Still scanning, indicate the caller should try again.
+                */
+               DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (Still scanning)\n"));
+                               return -EAGAIN;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (%d BSS returned)\n",pAdapter->ScanTab.BssNr));
+                       pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE;
+            // Claculate total buffer size required
+            BssBufSize = sizeof(ULONG);
+
+            for (i = 0; i < pAdapter->ScanTab.BssNr; i++)
+            {
+                // Align pointer to 4 bytes boundary.
+                //Padding = 4 - (pAdapter->ScanTab.BssEntry[i].VarIELen & 0x0003);
+                //if (Padding == 4)
+                //    Padding = 0;
+                BssBufSize += (sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen + Padding);
+            }
+
+            // For safety issue, we add 256 bytes just in case
+            BssBufSize += 256;
+            // Allocate the same size as passed from higher layer
+            pBuf = kmalloc(BssBufSize, MEM_ALLOC_FLAG);
+            if(pBuf == NULL)
+            {
+                Status = -ENOMEM;
+                break;
+            }
+            // Init 802_11_BSSID_LIST_EX structure
+            NdisZeroMemory(pBuf, BssBufSize);
+            pBssidList = (PNDIS_802_11_BSSID_LIST_EX) pBuf;
+            pBssidList->NumberOfItems = pAdapter->ScanTab.BssNr;
+
+            // Calculate total buffer length
+            BssLen = 4; // Consist of NumberOfItems
+            // Point to start of NDIS_WLAN_BSSID_EX
+            // pPtr = pBuf + sizeof(ULONG);
+            pPtr = (PUCHAR) &pBssidList->Bssid[0];
+            for (i = 0; i < pAdapter->ScanTab.BssNr; i++)
+            {
+                pBss = (PNDIS_WLAN_BSSID_EX) pPtr;
+                NdisMoveMemory(&pBss->MacAddress, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN);
+                if ((pAdapter->ScanTab.BssEntry[i].Hidden == 1) && (pAdapter->StaCfg.bShowHiddenSSID == FALSE))
+                {
+                    //
+                                       // We must return this SSID during 4way handshaking, otherwise Aegis will failed to parse WPA infomation
+                                       // and then failed to send EAPOl farame.
+                                       //
+                                       if ((pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAdapter->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED))
+                                       {
+                                               pBss->Ssid.SsidLength = pAdapter->ScanTab.BssEntry[i].SsidLen;
+                                               NdisMoveMemory(pBss->Ssid.Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen);
+                                       }
+                                       else
+                       pBss->Ssid.SsidLength = 0;
+                }
+                else
+                {
+                    pBss->Ssid.SsidLength = pAdapter->ScanTab.BssEntry[i].SsidLen;
+                    NdisMoveMemory(pBss->Ssid.Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen);
+                }
+                pBss->Privacy = pAdapter->ScanTab.BssEntry[i].Privacy;
+                pBss->Rssi = pAdapter->ScanTab.BssEntry[i].Rssi - pAdapter->BbpRssiToDbmDelta;
+                pBss->NetworkTypeInUse = NetworkTypeInUseSanity(&pAdapter->ScanTab.BssEntry[i]);
+                pBss->Configuration.Length = sizeof(NDIS_802_11_CONFIGURATION);
+                pBss->Configuration.BeaconPeriod = pAdapter->ScanTab.BssEntry[i].BeaconPeriod;
+                pBss->Configuration.ATIMWindow = pAdapter->ScanTab.BssEntry[i].AtimWin;
+
+                MAP_CHANNEL_ID_TO_KHZ(pAdapter->ScanTab.BssEntry[i].Channel, pBss->Configuration.DSConfig);
+
+                if (pAdapter->ScanTab.BssEntry[i].BssType == BSS_INFRA)
+                    pBss->InfrastructureMode = Ndis802_11Infrastructure;
+                else
+                    pBss->InfrastructureMode = Ndis802_11IBSS;
+
+                NdisMoveMemory(pBss->SupportedRates, pAdapter->ScanTab.BssEntry[i].SupRate, pAdapter->ScanTab.BssEntry[i].SupRateLen);
+                NdisMoveMemory(pBss->SupportedRates + pAdapter->ScanTab.BssEntry[i].SupRateLen,
+                               pAdapter->ScanTab.BssEntry[i].ExtRate,
+                               pAdapter->ScanTab.BssEntry[i].ExtRateLen);
+
+                if (pAdapter->ScanTab.BssEntry[i].VarIELen == 0)
+                {
+                    pBss->IELength = sizeof(NDIS_802_11_FIXED_IEs);
+                    NdisMoveMemory(pBss->IEs, &pAdapter->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs));
+                    pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs);
+                }
+                else
+                {
+                    pBss->IELength = (ULONG)(sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen);
+                    pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs);
+                    NdisMoveMemory(pBss->IEs, &pAdapter->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs));
+                    NdisMoveMemory(pBss->IEs + sizeof(NDIS_802_11_FIXED_IEs), pAdapter->ScanTab.BssEntry[i].VarIEs, pAdapter->ScanTab.BssEntry[i].VarIELen);
+                    pPtr += pAdapter->ScanTab.BssEntry[i].VarIELen;
+                }
+                pBss->Length = (ULONG)(sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen + Padding);
+
+#if WIRELESS_EXT < 17
+                if ((BssLen + pBss->Length) < wrq->u.data.length)
+                BssLen += pBss->Length;
+                else
+                {
+                    pBssidList->NumberOfItems = i;
+                    break;
+                }
+#else
+                BssLen += pBss->Length;
+#endif
+            }
+
+#if WIRELESS_EXT < 17
+            wrq->u.data.length = BssLen;
+#else
+            if (BssLen > wrq->u.data.length)
+            {
+                kfree(pBssidList);
+                return -E2BIG;
+            }
+            else
+                wrq->u.data.length = BssLen;
+#endif
+            Status = copy_to_user(wrq->u.data.pointer, pBssidList, BssLen);
+            kfree(pBssidList);
+            break;
+        case OID_802_3_CURRENT_ADDRESS:
+            wrq->u.data.length = MAC_ADDR_LEN;
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length);
+            break;
+        case OID_GEN_MEDIA_CONNECT_STATUS:
+            if (pAdapter->IndicateMediaState == NdisMediaStateConnected)
+                MediaState = NdisMediaStateConnected;
+            else
+                MediaState = NdisMediaStateDisconnected;
+
+            wrq->u.data.length = sizeof(NDIS_MEDIA_STATE);
+            Status = copy_to_user(wrq->u.data.pointer, &MediaState, wrq->u.data.length);
+            break;
+        case OID_802_11_BSSID:
+#ifdef RALINK_ATE
+                       if (ATE_ON(pAdapter))
+                       {
+                               DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+                               Status = NDIS_STATUS_RESOURCES;
+                               break;
+                       }
+#endif // RALINK_ATE //
+            if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
+            {
+                Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Bssid, sizeof(NDIS_802_11_MAC_ADDRESS));
+
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID(=EMPTY)\n"));
+                Status = -ENOTCONN;
+            }
+            break;
+        case OID_802_11_SSID:
+                       NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID));
+                       NdisZeroMemory(Ssid.Ssid, MAX_LEN_OF_SSID);
+            Ssid.SsidLength = pAdapter->CommonCfg.SsidLen;
+                       memcpy(Ssid.Ssid, pAdapter->CommonCfg.Ssid,     Ssid.SsidLength);
+            wrq->u.data.length = sizeof(NDIS_802_11_SSID);
+            Status = copy_to_user(wrq->u.data.pointer, &Ssid, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SSID (Len=%d, ssid=%s)\n", Ssid.SsidLength,Ssid.Ssid));
+            break;
+        case RT_OID_802_11_QUERY_LINK_STATUS:
+            pLinkStatus = (RT_802_11_LINK_STATUS *) kmalloc(sizeof(RT_802_11_LINK_STATUS), MEM_ALLOC_FLAG);
+            if (pLinkStatus)
+            {
+                pLinkStatus->CurrTxRate = RateIdTo500Kbps[pAdapter->CommonCfg.TxRate];   // unit : 500 kbps
+                pLinkStatus->ChannelQuality = pAdapter->Mlme.ChannelQuality;
+                pLinkStatus->RxByteCount = pAdapter->RalinkCounters.ReceivedByteCount;
+                pLinkStatus->TxByteCount = pAdapter->RalinkCounters.TransmittedByteCount;
+                       pLinkStatus->CentralChannel = pAdapter->CommonCfg.CentralChannel;
+                wrq->u.data.length = sizeof(RT_802_11_LINK_STATUS);
+                Status = copy_to_user(wrq->u.data.pointer, pLinkStatus, wrq->u.data.length);
+                kfree(pLinkStatus);
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS\n"));
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case OID_802_11_CONFIGURATION:
+            pConfiguration = (NDIS_802_11_CONFIGURATION *) kmalloc(sizeof(NDIS_802_11_CONFIGURATION), MEM_ALLOC_FLAG);
+            if (pConfiguration)
+            {
+                pConfiguration->Length = sizeof(NDIS_802_11_CONFIGURATION);
+                pConfiguration->BeaconPeriod = pAdapter->CommonCfg.BeaconPeriod;
+                pConfiguration->ATIMWindow = pAdapter->StaActive.AtimWin;
+                MAP_CHANNEL_ID_TO_KHZ(pAdapter->CommonCfg.Channel, pConfiguration->DSConfig);
+                wrq->u.data.length = sizeof(NDIS_802_11_CONFIGURATION);
+                Status = copy_to_user(wrq->u.data.pointer, pConfiguration, wrq->u.data.length);
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(BeaconPeriod=%ld,AtimW=%ld,Channel=%d) \n",
+                                        pConfiguration->BeaconPeriod, pConfiguration->ATIMWindow, pAdapter->CommonCfg.Channel));
+                               kfree(pConfiguration);
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+               case RT_OID_802_11_SNR_0:
+                       if ((pAdapter->StaCfg.LastSNR0 > 0))
+                       {
+                               ulInfo = ((0xeb - pAdapter->StaCfg.LastSNR0) * 3) /     16 ;
+                               wrq->u.data.length = sizeof(ulInfo);
+                               Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_SNR_0(0x=%lx)\n", ulInfo));
+                       }
+            else
+                           Status = -EFAULT;
+                       break;
+               case RT_OID_802_11_SNR_1:
+                       if ((pAdapter->Antenna.field.RxPath     > 1) &&
+                (pAdapter->StaCfg.LastSNR1 > 0))
+                       {
+                               ulInfo = ((0xeb - pAdapter->StaCfg.LastSNR1) * 3) /     16 ;
+                               wrq->u.data.length = sizeof(ulInfo);
+                               Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(0x=%lx)\n",ulInfo));
+                       }
+                       else
+                               Status = -EFAULT;
+            DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(pAdapter->StaCfg.LastSNR1=%d)\n",pAdapter->StaCfg.LastSNR1));
+                       break;
+        case OID_802_11_RSSI_TRIGGER:
+            ulInfo = pAdapter->StaCfg.RssiSample.LastRssi0 - pAdapter->BbpRssiToDbmDelta;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RSSI_TRIGGER(=%ld)\n", ulInfo));
+            break;
+               case OID_802_11_RSSI:
+        case RT_OID_802_11_RSSI:
+                       ulInfo = pAdapter->StaCfg.RssiSample.LastRssi0;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       break;
+               case RT_OID_802_11_RSSI_1:
+            ulInfo = pAdapter->StaCfg.RssiSample.LastRssi1;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       break;
+        case RT_OID_802_11_RSSI_2:
+            ulInfo = pAdapter->StaCfg.RssiSample.LastRssi2;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       break;
+        case OID_802_11_STATISTICS:
+            pStatistics = (NDIS_802_11_STATISTICS *) kmalloc(sizeof(NDIS_802_11_STATISTICS), MEM_ALLOC_FLAG);
+            if (pStatistics)
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS \n"));
+                // add the most up-to-date h/w raw counters into software counters
+                           NICUpdateRawCounters(pAdapter);
+
+                // Sanity check for calculation of sucessful count
+                if (pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart < pAdapter->WlanCounters.RetryCount.QuadPart)
+                    pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart;
+
+                pStatistics->TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart;
+                pStatistics->MulticastTransmittedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastTransmittedFrameCount.QuadPart;
+                pStatistics->FailedCount.QuadPart = pAdapter->WlanCounters.FailedCount.QuadPart;
+                pStatistics->RetryCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart;
+                pStatistics->MultipleRetryCount.QuadPart = pAdapter->WlanCounters.MultipleRetryCount.QuadPart;
+                pStatistics->RTSSuccessCount.QuadPart = pAdapter->WlanCounters.RTSSuccessCount.QuadPart;
+                pStatistics->RTSFailureCount.QuadPart = pAdapter->WlanCounters.RTSFailureCount.QuadPart;
+                pStatistics->ACKFailureCount.QuadPart = pAdapter->WlanCounters.ACKFailureCount.QuadPart;
+                pStatistics->FrameDuplicateCount.QuadPart = pAdapter->WlanCounters.FrameDuplicateCount.QuadPart;
+                pStatistics->ReceivedFragmentCount.QuadPart = pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart;
+                pStatistics->MulticastReceivedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastReceivedFrameCount.QuadPart;
+#ifdef DBG
+                pStatistics->FCSErrorCount = pAdapter->RalinkCounters.RealFcsErrCount;
+#else
+                pStatistics->FCSErrorCount.QuadPart = pAdapter->WlanCounters.FCSErrorCount.QuadPart;
+                pStatistics->FrameDuplicateCount.u.LowPart = pAdapter->WlanCounters.FrameDuplicateCount.u.LowPart / 100;
+#endif
+                wrq->u.data.length = sizeof(NDIS_802_11_STATISTICS);
+                Status = copy_to_user(wrq->u.data.pointer, pStatistics, wrq->u.data.length);
+                kfree(pStatistics);
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case OID_GEN_RCV_OK:
+            ulInfo = pAdapter->Counters8023.GoodReceives;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            break;
+        case OID_GEN_RCV_NO_BUFFER:
+            ulInfo = pAdapter->Counters8023.RxNoBuffer;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            break;
+        case RT_OID_802_11_PHY_MODE:
+            ulInfo = (ULONG)pAdapter->CommonCfg.PhyMode;
+            wrq->u.data.length = sizeof(ulInfo);
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PHY_MODE (=%ld)\n", ulInfo));
+            break;
+        case RT_OID_802_11_STA_CONFIG:
+            pStaConfig = (RT_802_11_STA_CONFIG *) kmalloc(sizeof(RT_802_11_STA_CONFIG), MEM_ALLOC_FLAG);
+            if (pStaConfig)
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG\n"));
+                pStaConfig->EnableTxBurst = pAdapter->CommonCfg.bEnableTxBurst;
+                pStaConfig->EnableTurboRate = 0;
+                pStaConfig->UseBGProtection = pAdapter->CommonCfg.UseBGProtection;
+                pStaConfig->UseShortSlotTime = pAdapter->CommonCfg.bUseShortSlotTime;
+                //pStaConfig->AdhocMode = pAdapter->StaCfg.AdhocMode;
+                pStaConfig->HwRadioStatus = (pAdapter->StaCfg.bHwRadio == TRUE) ? 1 : 0;
+                pStaConfig->Rsv1 = 0;
+                pStaConfig->SystemErrorBitmap = pAdapter->SystemErrorBitmap;
+                wrq->u.data.length = sizeof(RT_802_11_STA_CONFIG);
+                Status = copy_to_user(wrq->u.data.pointer, pStaConfig, wrq->u.data.length);
+                kfree(pStaConfig);
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case OID_802_11_RTS_THRESHOLD:
+            RtsThresh = pAdapter->CommonCfg.RtsThreshold;
+            wrq->u.data.length = sizeof(RtsThresh);
+            Status = copy_to_user(wrq->u.data.pointer, &RtsThresh, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RTS_THRESHOLD(=%ld)\n", RtsThresh));
+            break;
+        case OID_802_11_FRAGMENTATION_THRESHOLD:
+            FragThresh = pAdapter->CommonCfg.FragmentThreshold;
+            if (pAdapter->CommonCfg.bUseZeroToDisableFragment == TRUE)
+                FragThresh = 0;
+            wrq->u.data.length = sizeof(FragThresh);
+            Status = copy_to_user(wrq->u.data.pointer, &FragThresh, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_FRAGMENTATION_THRESHOLD(=%ld)\n", FragThresh));
+            break;
+        case OID_802_11_POWER_MODE:
+            PowerMode = pAdapter->StaCfg.WindowsPowerMode;
+            wrq->u.data.length = sizeof(PowerMode);
+            Status = copy_to_user(wrq->u.data.pointer, &PowerMode, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_POWER_MODE(=%d)\n", PowerMode));
+            break;
+        case RT_OID_802_11_RADIO:
+            RadioState = (BOOLEAN) pAdapter->StaCfg.bSwRadio;
+            wrq->u.data.length = sizeof(RadioState);
+            Status = copy_to_user(wrq->u.data.pointer, &RadioState, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_RADIO (=%d)\n", RadioState));
+            break;
+        case OID_802_11_INFRASTRUCTURE_MODE:
+            if (pAdapter->StaCfg.BssType == BSS_ADHOC)
+                BssType = Ndis802_11IBSS;
+            else if (pAdapter->StaCfg.BssType == BSS_INFRA)
+                BssType = Ndis802_11Infrastructure;
+            else if (pAdapter->StaCfg.BssType == BSS_MONITOR)
+                BssType = Ndis802_11Monitor;
+            else
+                BssType = Ndis802_11AutoUnknown;
+
+            wrq->u.data.length = sizeof(BssType);
+            Status = copy_to_user(wrq->u.data.pointer, &BssType, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_INFRASTRUCTURE_MODE(=%d)\n", BssType));
+            break;
+        case RT_OID_802_11_PREAMBLE:
+            PreamType = pAdapter->CommonCfg.TxPreamble;
+            wrq->u.data.length = sizeof(PreamType);
+            Status = copy_to_user(wrq->u.data.pointer, &PreamType, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PREAMBLE(=%d)\n", PreamType));
+            break;
+        case OID_802_11_AUTHENTICATION_MODE:
+            AuthMode = pAdapter->StaCfg.AuthMode;
+            wrq->u.data.length = sizeof(AuthMode);
+            Status = copy_to_user(wrq->u.data.pointer, &AuthMode, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_AUTHENTICATION_MODE(=%d)\n", AuthMode));
+            break;
+        case OID_802_11_WEP_STATUS:
+            WepStatus = pAdapter->StaCfg.WepStatus;
+            wrq->u.data.length = sizeof(WepStatus);
+            Status = copy_to_user(wrq->u.data.pointer, &WepStatus, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEP_STATUS(=%d)\n", WepStatus));
+            break;
+        case OID_802_11_TX_POWER_LEVEL:
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.TxPower, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_TX_POWER_LEVEL %x\n",pAdapter->CommonCfg.TxPower));
+                       break;
+        case RT_OID_802_11_TX_POWER_LEVEL_1:
+            wrq->u.data.length = sizeof(ULONG);
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.TxPowerPercentage, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAdapter->CommonCfg.TxPowerPercentage));
+                       break;
+        case OID_802_11_NETWORK_TYPES_SUPPORTED:
+                       if ((pAdapter->RfIcType == RFIC_2850) || (pAdapter->RfIcType == RFIC_2750))
+                       {
+                               NetworkTypeList[0] = 3;                 // NumberOfItems = 3
+                               NetworkTypeList[1] = Ndis802_11DS;      // NetworkType[1] = 11b
+                               NetworkTypeList[2] = Ndis802_11OFDM24;  // NetworkType[2] = 11g
+                               NetworkTypeList[3] = Ndis802_11OFDM5;   // NetworkType[3] = 11a
+                wrq->u.data.length = 16;
+                               Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length);
+                       }
+                       else
+                       {
+                               NetworkTypeList[0] = 2;                 // NumberOfItems = 2
+                               NetworkTypeList[1] = Ndis802_11DS;      // NetworkType[1] = 11b
+                               NetworkTypeList[2] = Ndis802_11OFDM24;  // NetworkType[2] = 11g
+                           wrq->u.data.length = 12;
+                               Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length);
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_NETWORK_TYPES_SUPPORTED\n"));
+                               break;
+           case OID_802_11_NETWORK_TYPE_IN_USE:
+            wrq->u.data.length = sizeof(ULONG);
+                       if (pAdapter->CommonCfg.PhyMode == PHY_11A)
+                               ulInfo = Ndis802_11OFDM5;
+                       else if ((pAdapter->CommonCfg.PhyMode == PHY_11BG_MIXED) || (pAdapter->CommonCfg.PhyMode == PHY_11G))
+                               ulInfo = Ndis802_11OFDM24;
+                       else
+                               ulInfo = Ndis802_11DS;
+            Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       break;
+        case RT_OID_802_11_QUERY_LAST_RX_RATE:
+            ulInfo = (ULONG)pAdapter->LastRxRate;
+            wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_RX_RATE (=%ld)\n", ulInfo));
+                       break;
+               case RT_OID_802_11_QUERY_LAST_TX_RATE:
+                       //ulInfo = (ULONG)pAdapter->LastTxRate;
+                       ulInfo = (ULONG)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word;
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo,     wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_TX_RATE (=%lx)\n", ulInfo));
+                       break;
+        case RT_OID_802_11_QUERY_EEPROM_VERSION:
+            wrq->u.data.length = sizeof(ULONG);
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->EepromVersion, wrq->u.data.length);
+            break;
+        case RT_OID_802_11_QUERY_FIRMWARE_VERSION:
+            wrq->u.data.length = sizeof(ULONG);
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->FirmwareVersion, wrq->u.data.length);
+                       break;
+           case RT_OID_802_11_QUERY_NOISE_LEVEL:
+                       wrq->u.data.length = sizeof(UCHAR);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->BbpWriteLatch[66], wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_NOISE_LEVEL (=%d)\n", pAdapter->BbpWriteLatch[66]));
+                       break;
+           case RT_OID_802_11_EXTRA_INFO:
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->ExtraInfo, wrq->u.data.length);
+               DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_EXTRA_INFO (=%ld)\n", pAdapter->ExtraInfo));
+               break;
+           case RT_OID_WE_VERSION_COMPILED:
+               wrq->u.data.length = sizeof(UINT);
+               we_version_compiled = WIRELESS_EXT;
+               Status = copy_to_user(wrq->u.data.pointer, &we_version_compiled, wrq->u.data.length);
+               break;
+               case RT_OID_802_11_QUERY_APSD_SETTING:
+                       apsd = (pAdapter->CommonCfg.bAPSDCapable | (pAdapter->CommonCfg.bAPSDAC_BE << 1) | (pAdapter->CommonCfg.bAPSDAC_BK << 2)
+                               | (pAdapter->CommonCfg.bAPSDAC_VI << 3) | (pAdapter->CommonCfg.bAPSDAC_VO << 4) | (pAdapter->CommonCfg.MaxSPLength << 5));
+
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &apsd, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_SETTING (=0x%lx,APSDCap=%d,AC_BE=%d,AC_BK=%d,AC_VI=%d,AC_VO=%d,MAXSPLen=%d)\n",
+                               apsd,pAdapter->CommonCfg.bAPSDCapable,pAdapter->CommonCfg.bAPSDAC_BE,pAdapter->CommonCfg.bAPSDAC_BK,pAdapter->CommonCfg.bAPSDAC_VI,pAdapter->CommonCfg.bAPSDAC_VO,pAdapter->CommonCfg.MaxSPLength));
+                       break;
+               case RT_OID_802_11_QUERY_APSD_PSM:
+                       wrq->u.data.length = sizeof(ULONG);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bAPSDForcePowerSave, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_PSM (=%d)\n", pAdapter->CommonCfg.bAPSDForcePowerSave));
+                       break;
+               case RT_OID_802_11_QUERY_WMM:
+                       wrq->u.data.length = sizeof(BOOLEAN);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bWmmCapable, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_WMM (=%d)\n",     pAdapter->CommonCfg.bWmmCapable));
+                       break;
+#ifdef WPA_SUPPLICANT_SUPPORT
+        case RT_OID_NEW_DRIVER:
+            {
+                UCHAR enabled = 1;
+               wrq->u.data.length = sizeof(UCHAR);
+               Status = copy_to_user(wrq->u.data.pointer, &enabled, wrq->u.data.length);
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_NEW_DRIVER (=%d)\n", enabled));
+            }
+               break;
+        case RT_OID_WPA_SUPPLICANT_SUPPORT:
+               wrq->u.data.length = sizeof(UCHAR);
+               Status = copy_to_user(wrq->u.data.pointer, &pAdapter->StaCfg.WpaSupplicantUP, wrq->u.data.length);
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAdapter->StaCfg.WpaSupplicantUP));
+               break;
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+        case RT_OID_DRIVER_DEVICE_NAME:
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_DRIVER_DEVICE_NAME \n"));
+                       wrq->u.data.length = 16;
+                       if (copy_to_user(wrq->u.data.pointer, pAdapter->StaCfg.dev_name, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+            break;
+        case RT_OID_802_11_QUERY_HT_PHYMODE:
+            pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG);
+            if (pHTPhyMode)
+            {
+                pHTPhyMode->PhyMode = pAdapter->CommonCfg.PhyMode;
+                       pHTPhyMode->HtMode = (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE;
+                       pHTPhyMode->BW = (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.BW;
+                       pHTPhyMode->MCS= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS;
+                       pHTPhyMode->SHORTGI= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI;
+                       pHTPhyMode->STBC= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC;
+
+                       pHTPhyMode->ExtOffset = ((pAdapter->CommonCfg.CentralChannel < pAdapter->CommonCfg.Channel) ? (EXTCHA_BELOW) : (EXTCHA_ABOVE));
+                wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE);
+                if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n",
+                               pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset));
+                       DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word));
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case RT_OID_802_11_COUNTRY_REGION:
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_COUNTRY_REGION \n"));
+                       wrq->u.data.length = sizeof(ulInfo);
+            ulInfo = pAdapter->CommonCfg.CountryRegionForABand;
+            ulInfo = (ulInfo << 8)|(pAdapter->CommonCfg.CountryRegion);
+                       if (copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length))
+            {
+                               Status = -EFAULT;
+            }
+            break;
+        case RT_OID_802_11_QUERY_DAT_HT_PHYMODE:
+            pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG);
+            if (pHTPhyMode)
+            {
+                pHTPhyMode->PhyMode = pAdapter->CommonCfg.PhyMode;
+                       pHTPhyMode->HtMode = (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.HTMODE;
+                       pHTPhyMode->BW = (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.BW;
+                       pHTPhyMode->MCS= (UCHAR)pAdapter->StaCfg.DesiredTransmitSetting.field.MCS;
+                       pHTPhyMode->SHORTGI= (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.ShortGI;
+                       pHTPhyMode->STBC= (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.STBC;
+
+                wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE);
+                if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length))
+                       {
+                               Status = -EFAULT;
+                       }
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n",
+                               pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset));
+                       DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word));
+            }
+            else
+            {
+                DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n"));
+                Status = -EFAULT;
+            }
+            break;
+        case RT_OID_QUERY_MULTIPLE_CARD_SUPPORT:
+                       wrq->u.data.length = sizeof(UCHAR);
+            i = 0;
+#ifdef MULTIPLE_CARD_SUPPORT
+            i = 1;
+#endif // MULTIPLE_CARD_SUPPORT //
+                       if (copy_to_user(wrq->u.data.pointer, &i, wrq->u.data.length))
+            {
+                               Status = -EFAULT;
+            }
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_QUERY_MULTIPLE_CARD_SUPPORT(=%d) \n", i));
+            break;
+#ifdef SNMP_SUPPORT
+               case RT_OID_802_11_MAC_ADDRESS:
+            wrq->u.data.length = MAC_ADDR_LEN;
+            Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_MANUFACTUREROUI:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREROUI \n"));
+                       wrq->u.data.length = ManufacturerOUI_LEN;
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_MANUFACTURERNAME:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTURERNAME \n"));
+                       wrq->u.data.length = strlen(ManufacturerNAME);
+                       Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_RESOURCETYPEIDNAME:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_RESOURCETYPEIDNAME \n"));
+                       wrq->u.data.length = strlen(ResourceTypeIdName);
+                       Status = copy_to_user(wrq->u.data.pointer, ResourceTypeIdName, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED \n"));
+                       ulInfo = 1; // 1 is support wep else 2 is not support.
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_POWERMANAGEMENTMODE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_POWERMANAGEMENTMODE \n"));
+                       if (pAdapter->StaCfg.Psm == PSMP_ACTION)
+                               ulInfo = 1; // 1 is power active else 2 is power save.
+                       else
+                               ulInfo = 2;
+
+                       wrq->u.data.length = sizeof(ulInfo);
+                       Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length);
+                       break;
+
+               case OID_802_11_WEPDEFAULTKEYVALUE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEPDEFAULTKEYVALUE \n"));
+                       //KeyIdxValue.KeyIdx = pAd->PortCfg.MBSSID[pAd->IoctlIF].DefaultKeyId;
+                       pKeyIdxValue = wrq->u.data.pointer;
+                       DBGPRINT(RT_DEBUG_TRACE,("KeyIdxValue.KeyIdx = %d, \n",pKeyIdxValue->KeyIdx));
+                       valueLen = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen;
+                       NdisMoveMemory(pKeyIdxValue->Value,
+                                                  &pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key,
+                                                  valueLen);
+                       pKeyIdxValue->Value[valueLen]='\0';
+
+                       wrq->u.data.length = sizeof(DefaultKeyIdxValue);
+
+                       Status = copy_to_user(wrq->u.data.pointer, pKeyIdxValue, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE,("DefaultKeyId = %d, total len = %d, str len=%d, KeyValue= %02x %02x %02x %02x \n", pAdapter->StaCfg.DefaultKeyId, wrq->u.data.length, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen,
+                       pAdapter->SharedKey[BSS0][0].Key[0],
+                       pAdapter->SharedKey[BSS0][1].Key[0],
+                       pAdapter->SharedKey[BSS0][2].Key[0],
+                       pAdapter->SharedKey[BSS0][3].Key[0]));
+                       break;
+
+               case OID_802_11_WEPDEFAULTKEYID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPDEFAULTKEYID \n"));
+                       wrq->u.data.length = sizeof(UCHAR);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->StaCfg.DefaultKeyId, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyId =%d \n", pAdapter->StaCfg.DefaultKeyId));
+                       break;
+
+               case RT_OID_802_11_WEPKEYMAPPINGLENGTH:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPKEYMAPPINGLENGTH \n"));
+                       wrq->u.data.length = sizeof(UCHAR);
+                       Status = copy_to_user(wrq->u.data.pointer,
+                                                                       &pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen,
+                                                                       wrq->u.data.length);
+                       break;
+
+               case OID_802_11_SHORTRETRYLIMIT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SHORTRETRYLIMIT \n"));
+                       wrq->u.data.length = sizeof(ULONG);
+                       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                       ShortRetryLimit = tx_rty_cfg.field.ShortRtyLimit;
+                       DBGPRINT(RT_DEBUG_TRACE, ("ShortRetryLimit =%ld,  tx_rty_cfg.field.ShortRetryLimit=%d\n", ShortRetryLimit, tx_rty_cfg.field.ShortRtyLimit));
+                       Status = copy_to_user(wrq->u.data.pointer, &ShortRetryLimit, wrq->u.data.length);
+                       break;
+
+               case OID_802_11_LONGRETRYLIMIT:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_LONGRETRYLIMIT \n"));
+                       wrq->u.data.length = sizeof(ULONG);
+                       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+                       LongRetryLimit = tx_rty_cfg.field.LongRtyLimit;
+                       DBGPRINT(RT_DEBUG_TRACE, ("LongRetryLimit =%ld,  tx_rty_cfg.field.LongRtyLimit=%d\n", LongRetryLimit, tx_rty_cfg.field.LongRtyLimit));
+                       Status = copy_to_user(wrq->u.data.pointer, &LongRetryLimit, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_PRODUCTID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRODUCTID \n"));
+
+#ifdef RT2870
+                       sprintf(tmp, "%04x %04x\n", ((POS_COOKIE)pAdapter->OS_Cookie)->pUsb_Dev->descriptor.idVendor ,((POS_COOKIE)pAdapter->OS_Cookie)->pUsb_Dev->descriptor.idProduct);
+
+#endif // RT2870 //
+                       wrq->u.data.length = strlen(tmp);
+                       Status = copy_to_user(wrq->u.data.pointer, tmp, wrq->u.data.length);
+                       break;
+
+               case RT_OID_802_11_MANUFACTUREID:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREID \n"));
+                       wrq->u.data.length = strlen(ManufacturerNAME);
+                       Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length);
+                       break;
+
+               case OID_802_11_CURRENTCHANNEL:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CURRENTCHANNEL \n"));
+                       wrq->u.data.length = sizeof(UCHAR);
+                       DBGPRINT(RT_DEBUG_TRACE, ("sizeof UCHAR=%d, channel=%d \n", sizeof(UCHAR), pAdapter->CommonCfg.Channel));
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Channel, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       break;
+#endif //SNMP_SUPPORT
+
+               case OID_802_11_BUILD_CHANNEL_EX:
+                       {
+                               UCHAR value;
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BUILD_CHANNEL_EX \n"));
+                               wrq->u.data.length = sizeof(UCHAR);
+#ifdef EXT_BUILD_CHANNEL_LIST
+                               DBGPRINT(RT_DEBUG_TRACE, ("Support EXT_BUILD_CHANNEL_LIST.\n"));
+                               value = 1;
+#else
+                               DBGPRINT(RT_DEBUG_TRACE, ("Doesn't support EXT_BUILD_CHANNEL_LIST.\n"));
+                               value = 0;
+#endif // EXT_BUILD_CHANNEL_LIST //
+                               Status = copy_to_user(wrq->u.data.pointer, &value, 1);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       }
+                       break;
+
+               case OID_802_11_GET_CH_LIST:
+                       {
+                               PRT_CHANNEL_LIST_INFO pChListBuf;
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CH_LIST \n"));
+                               if (pAdapter->ChannelListNum == 0)
+                               {
+                                       wrq->u.data.length = 0;
+                                       break;
+                               }
+
+                               pChListBuf = (RT_CHANNEL_LIST_INFO *) kmalloc(sizeof(RT_CHANNEL_LIST_INFO), MEM_ALLOC_FLAG);
+                               if (pChListBuf == NULL)
+                               {
+                                       wrq->u.data.length = 0;
+                                       break;
+                               }
+
+                               pChListBuf->ChannelListNum = pAdapter->ChannelListNum;
+                               for (i = 0; i < pChListBuf->ChannelListNum; i++)
+                                       pChListBuf->ChannelList[i] = pAdapter->ChannelList[i].Channel;
+
+                               wrq->u.data.length = sizeof(RT_CHANNEL_LIST_INFO);
+                               Status = copy_to_user(wrq->u.data.pointer, pChListBuf, sizeof(RT_CHANNEL_LIST_INFO));
+                               DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+
+                               if (pChListBuf)
+                                       kfree(pChListBuf);
+                       }
+                       break;
+
+               case OID_802_11_GET_COUNTRY_CODE:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_COUNTRY_CODE \n"));
+                       wrq->u.data.length = 2;
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.CountryCode, 2);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       break;
+
+               case OID_802_11_GET_CHANNEL_GEOGRAPHY:
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CHANNEL_GEOGRAPHY \n"));
+                       wrq->u.data.length = 1;
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Geography, 1);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status));
+                       break;
+
+
+#ifdef QOS_DLS_SUPPORT
+               case RT_OID_802_11_QUERY_DLS:
+                       wrq->u.data.length = sizeof(BOOLEAN);
+                       Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bDLSCapable, wrq->u.data.length);
+                       DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS(=%d)\n", pAdapter->CommonCfg.bDLSCapable));
+                       break;
+
+               case RT_OID_802_11_QUERY_DLS_PARAM:
+                       {
+                               PRT_802_11_DLS_INFO     pDlsInfo = kmalloc(sizeof(RT_802_11_DLS_INFO), GFP_ATOMIC);
+                               if (pDlsInfo == NULL)
+                                       break;
+
+                               for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
+                               {
+                                       RTMPMoveMemory(&pDlsInfo->Entry[i], &pAdapter->StaCfg.DLSEntry[i], sizeof(RT_802_11_DLS_UI));
+                               }
+
+                               pDlsInfo->num = MAX_NUM_OF_DLS_ENTRY;
+                               wrq->u.data.length = sizeof(RT_802_11_DLS_INFO);
+                               Status = copy_to_user(wrq->u.data.pointer, pDlsInfo, wrq->u.data.length);
+                               DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS_PARAM\n"));
+
+                               if (pDlsInfo)
+                                       kfree(pDlsInfo);
+                       }
+                       break;
+#endif // QOS_DLS_SUPPORT //
+        default:
+            DBGPRINT(RT_DEBUG_TRACE, ("Query::unknown IOCTL's subcmd = 0x%08x\n", cmd));
+            Status = -EOPNOTSUPP;
+            break;
+    }
+    return Status;
+}
+
+INT rt28xx_sta_ioctl(
+       IN      struct net_device       *net_dev,
+       IN      OUT     struct ifreq    *rq,
+       IN      INT                                     cmd)
+{
+       POS_COOKIE                      pObj;
+       VIRTUAL_ADAPTER         *pVirtualAd = NULL;
+       RTMP_ADAPTER        *pAd = NULL;
+       struct iwreq        *wrq = (struct iwreq *) rq;
+       BOOLEAN                         StateMachineTouched = FALSE;
+       INT                                     Status = NDIS_STATUS_SUCCESS;
+       USHORT                          subcmd;
+
+       if (net_dev->priv_flags == INT_MAIN)
+       {
+               pAd = net_dev->priv;
+       }
+       else
+       {
+               pVirtualAd = net_dev->priv;
+               pAd = pVirtualAd->RtmpDev->priv;
+       }
+       pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+       if (pAd == NULL)
+       {
+               /* if 1st open fail, pAd will be free;
+                  So the net_dev->priv will be NULL in 2rd open */
+               return -ENETDOWN;
+       }
+
+    //check if the interface is down
+    if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+    {
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+           if (wrq->u.data.pointer == NULL)
+           {
+                   return Status;
+           }
+
+           if (strstr(wrq->u.data.pointer, "OpMode") == NULL)
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+        {
+            DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+                   return -ENETDOWN;
+        }
+    }
+
+       {       // determine this ioctl command is comming from which interface.
+               pObj->ioctl_if_type = INT_MAIN;
+               pObj->ioctl_if = MAIN_MBSSID;
+       }
+
+       switch(cmd)
+       {
+#ifdef RALINK_ATE
+#ifdef RALINK_28xx_QA
+               case RTPRIV_IOCTL_ATE:
+                       {
+                               RtmpDoAte(pAd, wrq);
+                       }
+                       break;
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+        case SIOCGIFHWADDR:
+                       DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIFHWADDR\n"));
+                       memcpy(wrq->u.name, pAd->CurrentAddress, ETH_ALEN);
+                       break;
+               case SIOCGIWNAME:
+        {
+               char *name=&wrq->u.name[0];
+               rt_ioctl_giwname(net_dev, NULL, name, NULL);
+                       break;
+               }
+               case SIOCGIWESSID:  //Get ESSID
+        {
+               struct iw_point *essid=&wrq->u.essid;
+               rt_ioctl_giwessid(net_dev, NULL, essid, essid->pointer);
+                       break;
+               }
+               case SIOCSIWESSID:  //Set ESSID
+        {
+               struct iw_point *essid=&wrq->u.essid;
+               rt_ioctl_siwessid(net_dev, NULL, essid, essid->pointer);
+                       break;
+               }
+               case SIOCSIWNWID:   // set network id (the cell)
+               case SIOCGIWNWID:   // get network id
+                       Status = -EOPNOTSUPP;
+                       break;
+               case SIOCSIWFREQ:   //set channel/frequency (Hz)
+        {
+               struct iw_freq *freq=&wrq->u.freq;
+               rt_ioctl_siwfreq(net_dev, NULL, freq, NULL);
+                       break;
+               }
+               case SIOCGIWFREQ:   // get channel/frequency (Hz)
+        {
+               struct iw_freq *freq=&wrq->u.freq;
+               rt_ioctl_giwfreq(net_dev, NULL, freq, NULL);
+                       break;
+               }
+               case SIOCSIWNICKN: //set node name/nickname
+        {
+               struct iw_point *data=&wrq->u.data;
+               rt_ioctl_siwnickn(net_dev, NULL, data, NULL);
+                       break;
+               }
+               case SIOCGIWNICKN: //get node name/nickname
+        {
+               struct iw_point *data=&wrq->u.data;
+               rt_ioctl_giwnickn(net_dev, NULL, data, NULL);
+                       break;
+               }
+               case SIOCGIWRATE:   //get default bit rate (bps)
+                   rt_ioctl_giwrate(net_dev, NULL, &wrq->u, NULL);
+            break;
+           case SIOCSIWRATE:  //set default bit rate (bps)
+               rt_ioctl_siwrate(net_dev, NULL, &wrq->u, NULL);
+            break;
+        case SIOCGIWRTS:  // get RTS/CTS threshold (bytes)
+        {
+               struct iw_param *rts=&wrq->u.rts;
+               rt_ioctl_giwrts(net_dev, NULL, rts, NULL);
+                       break;
+               }
+        case SIOCSIWRTS:  //set RTS/CTS threshold (bytes)
+        {
+               struct iw_param *rts=&wrq->u.rts;
+               rt_ioctl_siwrts(net_dev, NULL, rts, NULL);
+                       break;
+               }
+        case SIOCGIWFRAG:  //get fragmentation thr (bytes)
+        {
+               struct iw_param *frag=&wrq->u.frag;
+               rt_ioctl_giwfrag(net_dev, NULL, frag, NULL);
+                       break;
+               }
+        case SIOCSIWFRAG:  //set fragmentation thr (bytes)
+        {
+               struct iw_param *frag=&wrq->u.frag;
+               rt_ioctl_siwfrag(net_dev, NULL, frag, NULL);
+                       break;
+               }
+        case SIOCGIWENCODE:  //get encoding token & mode
+        {
+               struct iw_point *erq=&wrq->u.encoding;
+               if(erq->pointer)
+                       rt_ioctl_giwencode(net_dev, NULL, erq, erq->pointer);
+                       break;
+               }
+        case SIOCSIWENCODE:  //set encoding token & mode
+        {
+               struct iw_point *erq=&wrq->u.encoding;
+               if(erq->pointer)
+                       rt_ioctl_siwencode(net_dev, NULL, erq, erq->pointer);
+                       break;
+               }
+               case SIOCGIWAP:     //get access point MAC addresses
+        {
+               struct sockaddr *ap_addr=&wrq->u.ap_addr;
+               rt_ioctl_giwap(net_dev, NULL, ap_addr, ap_addr->sa_data);
+                       break;
+               }
+           case SIOCSIWAP:  //set access point MAC addresses
+        {
+               struct sockaddr *ap_addr=&wrq->u.ap_addr;
+               rt_ioctl_siwap(net_dev, NULL, ap_addr, ap_addr->sa_data);
+                       break;
+               }
+               case SIOCGIWMODE:   //get operation mode
+        {
+               __u32 *mode=&wrq->u.mode;
+               rt_ioctl_giwmode(net_dev, NULL, mode, NULL);
+                       break;
+               }
+               case SIOCSIWMODE:   //set operation mode
+        {
+               __u32 *mode=&wrq->u.mode;
+               rt_ioctl_siwmode(net_dev, NULL, mode, NULL);
+                       break;
+               }
+               case SIOCGIWSENS:   //get sensitivity (dBm)
+               case SIOCSIWSENS:       //set sensitivity (dBm)
+               case SIOCGIWPOWER:  //get Power Management settings
+               case SIOCSIWPOWER:  //set Power Management settings
+               case SIOCGIWTXPOW:  //get transmit power (dBm)
+               case SIOCSIWTXPOW:  //set transmit power (dBm)
+               case SIOCGIWRANGE:      //Get range of parameters
+               case SIOCGIWRETRY:      //get retry limits and lifetime
+               case SIOCSIWRETRY:      //set retry limits and lifetime
+                       Status = -EOPNOTSUPP;
+                       break;
+               case RT_PRIV_IOCTL:
+                       subcmd = wrq->u.data.flags;
+                       if( subcmd & OID_GET_SET_TOGGLE)
+                               Status = RTMPSetInformation(pAd, rq, subcmd);
+                       else
+                               Status = RTMPQueryInformation(pAd, rq, subcmd);
+                       break;
+               case SIOCGIWPRIV:
+                       if (wrq->u.data.pointer)
+                       {
+                               if ( access_ok(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab)) != TRUE)
+                                       break;
+                               wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
+                               if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
+                                       Status = -EFAULT;
+                       }
+                       break;
+               case RTPRIV_IOCTL_SET:
+                       if(access_ok(VERIFY_READ, wrq->u.data.pointer, wrq->u.data.length) != TRUE)
+                               break;
+                       rt_ioctl_setparam(net_dev, NULL, NULL, wrq->u.data.pointer);
+                       break;
+               case RTPRIV_IOCTL_GSITESURVEY:
+                       RTMPIoctlGetSiteSurvey(pAd, wrq);
+                   break;
+#ifdef DBG
+               case RTPRIV_IOCTL_MAC:
+                       RTMPIoctlMAC(pAd, wrq);
+                       break;
+               case RTPRIV_IOCTL_E2P:
+                       RTMPIoctlE2PROM(pAd, wrq);
+                       break;
+#endif // DBG //
+        case SIOCETHTOOL:
+                break;
+               default:
+                       DBGPRINT(RT_DEBUG_ERROR, ("IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd));
+                       Status = -EOPNOTSUPP;
+                       break;
+       }
+
+    if(StateMachineTouched) // Upper layer sent a MLME-related operations
+       RT28XX_MLME_HANDLER(pAd);
+
+       return Status;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set SSID
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_SSID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    NDIS_802_11_SSID                    Ssid, *pSsid=NULL;
+    BOOLEAN                             StateMachineTouched = FALSE;
+    int                                 success = TRUE;
+
+    if( strlen(arg) <= MAX_LEN_OF_SSID)
+    {
+        NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID));
+        if (strlen(arg) != 0)
+        {
+            NdisMoveMemory(Ssid.Ssid, arg, strlen(arg));
+            Ssid.SsidLength = strlen(arg);
+        }
+        else   //ANY ssid
+        {
+            Ssid.SsidLength = 0;
+                   memcpy(Ssid.Ssid, "", 0);
+                       pAdapter->StaCfg.BssType = BSS_INFRA;
+                       pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+               pAdapter->StaCfg.WepStatus  = Ndis802_11EncryptionDisabled;
+               }
+        pSsid = &Ssid;
+
+        if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+        {
+            RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+            DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
+        }
+
+        pAdapter->MlmeAux.CurrReqIsFromNdis = TRUE;
+        pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE;
+               pAdapter->bConfigChanged = TRUE;
+
+        MlmeEnqueue(pAdapter,
+                    MLME_CNTL_STATE_MACHINE,
+                    OID_802_11_SSID,
+                    sizeof(NDIS_802_11_SSID),
+                    (VOID *)pSsid);
+
+        StateMachineTouched = TRUE;
+        DBGPRINT(RT_DEBUG_TRACE, ("Set_SSID_Proc::(Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid));
+    }
+    else
+        success = FALSE;
+
+    if (StateMachineTouched) // Upper layer sent a MLME-related operations
+       RT28XX_MLME_HANDLER(pAdapter);
+
+    return success;
+}
+
+#ifdef WMM_SUPPORT
+/*
+    ==========================================================================
+    Description:
+        Set WmmCapable Enable or Disable
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT    Set_WmmCapable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+       BOOLEAN bWmmCapable;
+
+       bWmmCapable = simple_strtol(arg, 0, 10);
+
+       if ((bWmmCapable == 1)
+#ifdef RT2870
+               && (pAd->NumberOfPipes >= 5)
+#endif // RT2870 //
+               )
+               pAd->CommonCfg.bWmmCapable = TRUE;
+       else if (bWmmCapable == 0)
+               pAd->CommonCfg.bWmmCapable = FALSE;
+       else
+               return FALSE;  //Invalid argument
+
+       DBGPRINT(RT_DEBUG_TRACE, ("Set_WmmCapable_Proc::(bWmmCapable=%d)\n",
+               pAd->CommonCfg.bWmmCapable));
+
+       return TRUE;
+}
+#endif // WMM_SUPPORT //
+
+/*
+    ==========================================================================
+    Description:
+        Set Network Type(Infrastructure/Adhoc mode)
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_NetworkType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    UINT32     Value = 0;
+
+    if (strcmp(arg, "Adhoc") == 0)
+       {
+               if (pAdapter->StaCfg.BssType != BSS_ADHOC)
+               {
+                       // Config has changed
+                       pAdapter->bConfigChanged = TRUE;
+            if (MONITOR_ON(pAdapter))
+            {
+                RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL);
+                RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value);
+                               Value &= (~0x80);
+                               RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value);
+                OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED);
+                pAdapter->StaCfg.bAutoReconnect = TRUE;
+                LinkDown(pAdapter, FALSE);
+            }
+                       if (INFRA_ON(pAdapter))
+                       {
+                               //BOOLEAN Cancelled;
+                               // Set the AutoReconnectSsid to prevent it reconnect to old SSID
+                               // Since calling this indicate user don't want to connect to that SSID anymore.
+                               pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+                               NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen);
+
+                               LinkDown(pAdapter, FALSE);
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event BB!\n"));
+                       }
+               }
+               pAdapter->StaCfg.BssType = BSS_ADHOC;
+        pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType;
+               DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(AD-HOC)\n"));
+       }
+    else if (strcmp(arg, "Infra") == 0)
+       {
+               if (pAdapter->StaCfg.BssType != BSS_INFRA)
+               {
+                       // Config has changed
+                       pAdapter->bConfigChanged = TRUE;
+            if (MONITOR_ON(pAdapter))
+            {
+                RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL);
+                RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value);
+                               Value &= (~0x80);
+                               RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value);
+                OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED);
+                pAdapter->StaCfg.bAutoReconnect = TRUE;
+                LinkDown(pAdapter, FALSE);
+            }
+                       if (ADHOC_ON(pAdapter))
+                       {
+                               // Set the AutoReconnectSsid to prevent it reconnect to old SSID
+                               // Since calling this indicate user don't want to connect to that SSID anymore.
+                               pAdapter->MlmeAux.AutoReconnectSsidLen= 32;
+                               NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen);
+
+                               LinkDown(pAdapter, FALSE);
+                       }
+               }
+               pAdapter->StaCfg.BssType = BSS_INFRA;
+        pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType;
+               DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(INFRA)\n"));
+
+        pAdapter->StaCfg.BssType = BSS_INFRA;
+       }
+    else if (strcmp(arg, "Monitor") == 0)
+    {
+               UCHAR   bbpValue = 0;
+               BCN_TIME_CFG_STRUC csr;
+               OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_INFRA_ON);
+        OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_ADHOC_ON);
+               OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED);
+               // disable all periodic state machine
+               pAdapter->StaCfg.bAutoReconnect = FALSE;
+               // reset all mlme state machine
+               RT28XX_MLME_RESET_STATE_MACHINE(pAdapter);
+               DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_MEDIA_STATE_CONNECTED \n"));
+        if (pAdapter->CommonCfg.CentralChannel == 0)
+        {
+#ifdef DOT11_N_SUPPORT
+            if (pAdapter->CommonCfg.PhyMode == PHY_11AN_MIXED)
+                pAdapter->CommonCfg.CentralChannel = 36;
+            else
+#endif // DOT11_N_SUPPORT //
+                pAdapter->CommonCfg.CentralChannel = 6;
+        }
+#ifdef DOT11_N_SUPPORT
+        else
+            N_ChannelCheck(pAdapter);
+#endif // DOT11_N_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+       if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED &&
+            pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 &&
+            pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE)
+               {
+                       // 40MHz ,control channel at lower
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue);
+                       bbpValue &= (~0x18);
+                       bbpValue |= 0x10;
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue);
+                       pAdapter->CommonCfg.BBPCurrentBW = BW_40;
+                       //  RX : control channel at lower
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue);
+                       bbpValue &= (~0x20);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue);
+
+                       RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value);
+                       Value &= 0xfffffffe;
+                       RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value);
+                       pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel + 2;
+            AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE);
+                   AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel);
+            DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n",
+                                       pAdapter->CommonCfg.Channel,
+                                       pAdapter->CommonCfg.CentralChannel));
+               }
+               else if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED &&
+                 pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 &&
+                 pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)
+               {
+                       // 40MHz ,control channel at upper
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue);
+                       bbpValue &= (~0x18);
+                       bbpValue |= 0x10;
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue);
+                       pAdapter->CommonCfg.BBPCurrentBW = BW_40;
+                       RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value);
+                       Value |= 0x1;
+                       RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value);
+
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue);
+                       bbpValue |= (0x20);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue);
+                       pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel - 2;
+            AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE);
+                   AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel);
+            DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n",
+                                       pAdapter->CommonCfg.Channel,
+                                       pAdapter->CommonCfg.CentralChannel));
+               }
+               else
+#endif // DOT11_N_SUPPORT //
+               {
+                       // 20MHz
+                       RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue);
+                       bbpValue &= (~0x18);
+                       RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue);
+                       pAdapter->CommonCfg.BBPCurrentBW = BW_20;
+                       AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.Channel, FALSE);
+                       AsicLockChannel(pAdapter, pAdapter->CommonCfg.Channel);
+                       DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAdapter->CommonCfg.Channel));
+               }
+               // Enable Rx with promiscuous reception
+               RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, 0x3);
+               // ASIC supporsts sniffer function with replacing RSSI with timestamp.
+               //RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value);
+               //Value |= (0x80);
+               //RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value);
+               // disable sync
+               RTMP_IO_READ32(pAdapter, BCN_TIME_CFG, &csr.word);
+               csr.field.bBeaconGen = 0;
+               csr.field.bTBTTEnable = 0;
+               csr.field.TsfSyncMode = 0;
+               RTMP_IO_WRITE32(pAdapter, BCN_TIME_CFG, csr.word);
+
+               pAdapter->StaCfg.BssType = BSS_MONITOR;
+        pAdapter->net_dev->type = ARPHRD_IEEE80211_PRISM; //ARPHRD_IEEE80211; // IEEE80211
+               DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(MONITOR)\n"));
+    }
+
+    // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key
+    pAdapter->StaCfg.WpaState = SS_NOTUSE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_NetworkType_Proc::(NetworkType=%d)\n", pAdapter->StaCfg.BssType));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Authentication mode
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_AuthMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch;
+    else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+    else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared;
+    else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK;
+    else if ((strcmp(arg, "WPANONE") == 0) || (strcmp(arg, "wpanone") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone;
+    else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK;
+#ifdef WPA_SUPPLICANT_SUPPORT
+    else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA;
+    else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0))
+        pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2;
+#endif // WPA_SUPPLICANT_SUPPORT //
+    else
+        return FALSE;
+
+    pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_AuthMode_Proc::(AuthMode=%d)\n", pAdapter->StaCfg.AuthMode));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Encryption Type
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_EncrypType_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11WEPDisabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11WEPDisabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11WEPDisabled;
+    }
+    else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11WEPEnabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11WEPEnabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11WEPEnabled;
+    }
+    else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11Encryption2Enabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11Encryption2Enabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11Encryption2Enabled;
+    }
+    else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0))
+    {
+        if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
+            return TRUE;    // do nothing
+
+        pAdapter->StaCfg.WepStatus     = Ndis802_11Encryption3Enabled;
+        pAdapter->StaCfg.PairCipher    = Ndis802_11Encryption3Enabled;
+           pAdapter->StaCfg.GroupCipher   = Ndis802_11Encryption3Enabled;
+    }
+    else
+        return FALSE;
+
+    pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_EncrypType_Proc::(EncrypType=%d)\n", pAdapter->StaCfg.WepStatus));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Default Key ID
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_DefaultKeyID_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    ULONG                               KeyIdx;
+
+    KeyIdx = simple_strtol(arg, 0, 10);
+    if((KeyIdx >= 1 ) && (KeyIdx <= 4))
+        pAdapter->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1 );
+    else
+        return FALSE;  //Invalid argument
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_DefaultKeyID_Proc::(DefaultKeyID=%d)\n", pAdapter->StaCfg.DefaultKeyId));
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set WEP KEY1
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key1_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex"));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex"));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+
+    pAdapter->SharedKey[BSS0][0].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              0,
+                              pAdapter->SharedKey[BSS0][0].CipherAlg,
+                              pAdapter->SharedKey[BSS0][0].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+/*
+    ==========================================================================
+
+    Description:
+        Set WEP KEY2
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key2_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex"));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex"));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+    pAdapter->SharedKey[BSS0][1].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              1,
+                              pAdapter->SharedKey[BSS0][1].CipherAlg,
+                              pAdapter->SharedKey[BSS0][1].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+/*
+    ==========================================================================
+    Description:
+        Set WEP KEY3
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key3_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+    pAdapter->SharedKey[BSS0][2].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              2,
+                              pAdapter->SharedKey[BSS0][2].CipherAlg,
+                              pAdapter->SharedKey[BSS0][2].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+/*
+    ==========================================================================
+    Description:
+        Set WEP KEY4
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Key4_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    int                                 KeyLen;
+    int                                 i;
+    UCHAR                               CipherAlg=CIPHER_WEP64;
+
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        return TRUE;    // do nothing
+
+    KeyLen = strlen(arg);
+
+    switch (KeyLen)
+    {
+        case 5: //wep 40 Ascii type
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 10: //wep 40 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP64;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex"));
+            break;
+        case 13: //wep 104 Ascii type
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen;
+            memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii"));
+            break;
+        case 26: //wep 104 Hex type
+            for(i=0; i < KeyLen; i++)
+            {
+                if( !isxdigit(*(arg+i)) )
+                    return FALSE;  //Not Hex value;
+            }
+            pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ;
+            AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2);
+            CipherAlg = CIPHER_WEP128;
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex"));
+            break;
+        default: //Invalid argument
+            DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::Invalid argument (=%s)\n", arg));
+            return FALSE;
+    }
+    pAdapter->SharedKey[BSS0][3].CipherAlg = CipherAlg;
+
+    // Set keys (into ASIC)
+    if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+        ;   // not support
+    else    // Old WEP stuff
+    {
+        AsicAddSharedKeyEntry(pAdapter,
+                              0,
+                              3,
+                              pAdapter->SharedKey[BSS0][3].CipherAlg,
+                              pAdapter->SharedKey[BSS0][3].Key,
+                              NULL,
+                              NULL);
+    }
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set WPA PSK key
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_WPAPSK_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    UCHAR                   keyMaterial[40];
+
+    if ((pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) &&
+        (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) &&
+           (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone)
+               )
+        return TRUE;    // do nothing
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc::(WPAPSK=%s)\n", arg));
+
+    NdisZeroMemory(keyMaterial, 40);
+
+    if ((strlen(arg) < 8) || (strlen(arg) > 64))
+    {
+        DBGPRINT(RT_DEBUG_TRACE, ("Set failed!!(WPAPSK=%s), WPAPSK key-string required 8 ~ 64 characters \n", arg));
+        return FALSE;
+    }
+
+    if (strlen(arg) == 64)
+    {
+        AtoH(arg, keyMaterial, 32);
+        NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32);
+
+    }
+    else
+    {
+        PasswordHash((char *)arg, pAdapter->MlmeAux.Ssid, pAdapter->MlmeAux.SsidLen, keyMaterial);
+        NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32);
+    }
+
+
+
+    if(pAdapter->StaCfg.BssType == BSS_ADHOC &&
+       pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+    {
+         pAdapter->StaCfg.WpaState = SS_NOTUSE;
+    }
+    else
+    {
+        // Start STA supplicant state machine
+        pAdapter->StaCfg.WpaState = SS_START;
+    }
+
+    return TRUE;
+}
+
+/*
+    ==========================================================================
+    Description:
+        Set Power Saving mode
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_PSMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if (pAdapter->StaCfg.BssType == BSS_INFRA)
+    {
+        if ((strcmp(arg, "Max_PSP") == 0) ||
+                       (strcmp(arg, "max_psp") == 0) ||
+                       (strcmp(arg, "MAX_PSP") == 0))
+        {
+            // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+            // to exclude certain situations.
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP;
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            pAdapter->StaCfg.DefaultListenCount = 5;
+
+        }
+        else if ((strcmp(arg, "Fast_PSP") == 0) ||
+                                (strcmp(arg, "fast_psp") == 0) ||
+                 (strcmp(arg, "FAST_PSP") == 0))
+        {
+            // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+            // to exclude certain situations.
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP;
+            pAdapter->StaCfg.DefaultListenCount = 3;
+        }
+        else if ((strcmp(arg, "Legacy_PSP") == 0) ||
+                 (strcmp(arg, "legacy_psp") == 0) ||
+                 (strcmp(arg, "LEGACY_PSP") == 0))
+        {
+            // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+            // to exclude certain situations.
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP;
+            pAdapter->StaCfg.DefaultListenCount = 3;
+        }
+        else
+        {
+            //Default Ndis802_11PowerModeCAM
+            // clear PSM bit immediately
+            MlmeSetPsmBit(pAdapter, PWR_ACTIVE);
+            OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM);
+            if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE)
+                pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM;
+            pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM;
+        }
+
+        DBGPRINT(RT_DEBUG_TRACE, ("Set_PSMode_Proc::(PSMode=%ld)\n", pAdapter->StaCfg.WindowsPowerMode));
+    }
+    else
+        return FALSE;
+
+
+    return TRUE;
+}
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+/*
+    ==========================================================================
+    Description:
+        Set WpaSupport flag.
+    Value:
+        0: Driver ignore wpa_supplicant.
+        1: wpa_supplicant initiates scanning and AP selection.
+        2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters.
+    Return:
+        TRUE if all parameters are OK, FALSE otherwise
+    ==========================================================================
+*/
+INT Set_Wpa_Support(
+    IN PRTMP_ADAPTER   pAd,
+       IN      PUCHAR                  arg)
+{
+
+    if ( simple_strtol(arg, 0, 10) == 0)
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE;
+    else if ( simple_strtol(arg, 0, 10) == 1)
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE;
+    else if ( simple_strtol(arg, 0, 10) == 2)
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE_WITH_WEB_UI;
+    else
+        pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_Wpa_Support::(WpaSupplicantUP=%d)\n", pAd->StaCfg.WpaSupplicantUP));
+
+    return TRUE;
+}
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef DBG
+/*
+    ==========================================================================
+    Description:
+        Read / Write MAC
+    Arguments:
+        pAdapter                    Pointer to our adapter
+        wrq                         Pointer to the ioctl argument
+
+    Return Value:
+        None
+
+    Note:
+        Usage:
+               1.) iwpriv ra0 mac 0        ==> read MAC where Addr=0x0
+               2.) iwpriv ra0 mac 0=12     ==> write MAC where Addr=0x0, value=12
+    ==========================================================================
+*/
+VOID RTMPIoctlMAC(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq)
+{
+       CHAR                            *this_char;
+       CHAR                            *value;
+       INT                                     j = 0, k = 0;
+       CHAR                            msg[1024];
+       CHAR                            arg[255];
+       ULONG                           macAddr = 0;
+       UCHAR                           temp[16], temp2[16];
+       UINT32                          macValue = 0;
+       INT                                     Status;
+
+
+       memset(msg, 0x00, 1024);
+       if (wrq->u.data.length > 1) //No parameters.
+       {
+           Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length);
+               sprintf(msg, "\n");
+
+               //Parsing Read or Write
+           this_char = arg;
+               if (!*this_char)
+                       goto next;
+
+               if ((value = rtstrchr(this_char, '=')) != NULL)
+                       *value++ = 0;
+
+               if (!value || !*value)
+               { //Read
+                       // Sanity check
+                       if(strlen(this_char) > 4)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+
+                       // Mac Addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       if(strlen(this_char) == 4)
+                       {
+                               AtoH(this_char, temp, 2);
+                               macAddr = *temp*256 + temp[1];
+                               if (macAddr < 0xFFFF)
+                               {
+                                       RTMP_IO_READ32(pAdapter, macAddr, &macValue);
+                                       DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%lx, MacValue=%x\n", macAddr, macValue));
+                                       sprintf(msg+strlen(msg), "[0x%08lX]:%08X  ", macAddr , macValue);
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       goto next;
+                               }
+                       }
+               }
+               else
+               { //Write
+                       memcpy(&temp2, value, strlen(value));
+                       temp2[strlen(value)] = '\0';
+
+                       // Sanity check
+                       if((strlen(this_char) > 4) || strlen(temp2) > 8)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+
+                       j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               if(temp2[j] > 'f' || temp2[j] < '0')
+                                       return;
+                       }
+
+                       //MAC Addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       //MAC value
+                       k = j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               temp2[8-k+j] = temp2[j];
+                       }
+
+                       while(k < 8)
+                               temp2[7-k++]='0';
+                       temp2[8]='\0';
+
+                       {
+                               AtoH(this_char, temp, 2);
+                               macAddr = *temp*256 + temp[1];
+
+                               AtoH(temp2, temp, 4);
+                               macValue = *temp*256*256*256 + temp[1]*256*256 + temp[2]*256 + temp[3];
+
+                               // debug mode
+                               if (macAddr == (HW_DEBUG_SETTING_BASE + 4))
+                               {
+                                       // 0x2bf4: byte0 non-zero: enable R17 tuning, 0: disable R17 tuning
+                    if (macValue & 0x000000ff)
+                    {
+                        pAdapter->BbpTuning.bEnable = TRUE;
+                        DBGPRINT(RT_DEBUG_TRACE,("turn on R17 tuning\n"));
+                    }
+                    else
+                    {
+                        UCHAR R66;
+                        pAdapter->BbpTuning.bEnable = FALSE;
+                        R66 = 0x26 + GET_LNA_GAIN(pAdapter);
+#ifdef RALINK_ATE
+                                               if (ATE_ON(pAdapter))
+                                               {
+                                                       ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter)));
+                                               }
+                                               else
+#endif // RALINK_ATE //
+                                               RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter)));
+                        DBGPRINT(RT_DEBUG_TRACE,("turn off R17 tuning, restore to 0x%02x\n", R66));
+                    }
+                                       return;
+                               }
+
+                               DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%02lx, MacValue=0x%x\n", macAddr, macValue));
+
+                               RTMP_IO_WRITE32(pAdapter, macAddr, macValue);
+                               sprintf(msg+strlen(msg), "[0x%08lX]:%08X  ", macAddr, macValue);
+                       }
+               }
+       }
+next:
+       if(strlen(msg) == 1)
+               sprintf(msg+strlen(msg), "===>Error command format!");
+
+       // Copy the information into the user buffer
+       wrq->u.data.length = strlen(msg);
+       Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlMAC\n\n"));
+}
+
+/*
+    ==========================================================================
+    Description:
+        Read / Write E2PROM
+    Arguments:
+        pAdapter                    Pointer to our adapter
+        wrq                         Pointer to the ioctl argument
+
+    Return Value:
+        None
+
+    Note:
+        Usage:
+               1.) iwpriv ra0 e2p 0            ==> read E2PROM where Addr=0x0
+               2.) iwpriv ra0 e2p 0=1234    ==> write E2PROM where Addr=0x0, value=1234
+    ==========================================================================
+*/
+VOID RTMPIoctlE2PROM(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      struct iwreq    *wrq)
+{
+       CHAR                            *this_char;
+       CHAR                            *value;
+       INT                                     j = 0, k = 0;
+       CHAR                            msg[1024];
+       CHAR                            arg[255];
+       USHORT                          eepAddr = 0;
+       UCHAR                           temp[16], temp2[16];
+       USHORT                          eepValue;
+       int                                     Status;
+
+
+       memset(msg, 0x00, 1024);
+       if (wrq->u.data.length > 1) //No parameters.
+       {
+           Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length);
+               sprintf(msg, "\n");
+
+           //Parsing Read or Write
+               this_char = arg;
+
+
+               if (!*this_char)
+                       goto next;
+
+               if ((value = rtstrchr(this_char, '=')) != NULL)
+                       *value++ = 0;
+
+               if (!value || !*value)
+               { //Read
+
+                       // Sanity check
+                       if(strlen(this_char) > 4)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+
+                       // E2PROM addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       if(strlen(this_char) == 4)
+                       {
+                               AtoH(this_char, temp, 2);
+                               eepAddr = *temp*256 + temp[1];
+                               if (eepAddr < 0xFFFF)
+                               {
+                                       RT28xx_EEPROM_READ16(pAdapter, eepAddr, eepValue);
+                                       sprintf(msg+strlen(msg), "[0x%04X]:0x%04X  ", eepAddr , eepValue);
+                               }
+                               else
+                               {//Invalid parametes, so default printk all bbp
+                                       goto next;
+                               }
+                       }
+               }
+               else
+               { //Write
+                       memcpy(&temp2, value, strlen(value));
+                       temp2[strlen(value)] = '\0';
+
+                       // Sanity check
+                       if((strlen(this_char) > 4) || strlen(temp2) > 8)
+                               goto next;
+
+                       j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               if(this_char[j] > 'f' || this_char[j] < '0')
+                                       return;
+                       }
+                       j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               if(temp2[j] > 'f' || temp2[j] < '0')
+                                       return;
+                       }
+
+                       //MAC Addr
+                       k = j = strlen(this_char);
+                       while(j-- > 0)
+                       {
+                               this_char[4-k+j] = this_char[j];
+                       }
+
+                       while(k < 4)
+                               this_char[3-k++]='0';
+                       this_char[4]='\0';
+
+                       //MAC value
+                       k = j = strlen(temp2);
+                       while(j-- > 0)
+                       {
+                               temp2[4-k+j] = temp2[j];
+                       }
+
+                       while(k < 4)
+                               temp2[3-k++]='0';
+                       temp2[4]='\0';
+
+                       AtoH(this_char, temp, 2);
+                       eepAddr = *temp*256 + temp[1];
+
+                       AtoH(temp2, temp, 2);
+                       eepValue = *temp*256 + temp[1];
+
+                       RT28xx_EEPROM_WRITE16(pAdapter, eepAddr, eepValue);
+                       sprintf(msg+strlen(msg), "[0x%02X]:%02X  ", eepAddr, eepValue);
+               }
+       }
+next:
+       if(strlen(msg) == 1)
+               sprintf(msg+strlen(msg), "===>Error command format!");
+
+
+       // Copy the information into the user buffer
+       wrq->u.data.length = strlen(msg);
+       Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length);
+
+       DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlE2PROM\n"));
+}
+#endif // DBG //
+
+
+
+
+INT Set_TGnWifiTest_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg)
+{
+    if (simple_strtol(arg, 0, 10) == 0)
+        pAd->StaCfg.bTGnWifiTest = FALSE;
+    else
+        pAd->StaCfg.bTGnWifiTest = TRUE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("IF Set_TGnWifiTest_Proc::(bTGnWifiTest=%d)\n", pAd->StaCfg.bTGnWifiTest));
+       return TRUE;
+}
+
+INT Set_LongRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg)
+{
+       TX_RTY_CFG_STRUC        tx_rty_cfg;
+       UCHAR                           LongRetryLimit = (UCHAR)simple_strtol(arg, 0, 10);
+
+       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+       tx_rty_cfg.field.LongRtyLimit = LongRetryLimit;
+       RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+       DBGPRINT(RT_DEBUG_TRACE, ("IF Set_LongRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word));
+       return TRUE;
+}
+
+INT Set_ShortRetryLimit_Proc(
+       IN      PRTMP_ADAPTER   pAdapter,
+       IN      PUCHAR                  arg)
+{
+       TX_RTY_CFG_STRUC        tx_rty_cfg;
+       UCHAR                           ShortRetryLimit = (UCHAR)simple_strtol(arg, 0, 10);
+
+       RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+       tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit;
+       RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+       DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ShortRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word));
+       return TRUE;
+}
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+INT Set_Ieee80211dClientMode_Proc(
+    IN  PRTMP_ADAPTER   pAdapter,
+    IN  PUCHAR          arg)
+{
+    if (simple_strtol(arg, 0, 10) == 0)
+        pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_None;
+    else if (simple_strtol(arg, 0, 10) == 1)
+        pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Flexible;
+    else if (simple_strtol(arg, 0, 10) == 2)
+        pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Strict;
+    else
+        return FALSE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("Set_Ieee802dMode_Proc::(IEEEE0211dMode=%d)\n", pAdapter->StaCfg.IEEE80211dClientMode));
+    return TRUE;
+}
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+#ifdef CARRIER_DETECTION_SUPPORT
+INT Set_CarrierDetect_Proc(
+    IN  PRTMP_ADAPTER   pAd,
+    IN  PUCHAR          arg)
+{
+    if (simple_strtol(arg, 0, 10) == 0)
+        pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+    else
+        pAd->CommonCfg.CarrierDetect.Enable = TRUE;
+
+    DBGPRINT(RT_DEBUG_TRACE, ("IF Set_CarrierDetect_Proc::(CarrierDetect.Enable=%d)\n", pAd->CommonCfg.CarrierDetect.Enable));
+       return TRUE;
+}
+#endif // CARRIER_DETECTION_SUPPORT //
+
+
+INT    Show_Adhoc_MacTable_Proc(
+       IN      PRTMP_ADAPTER   pAd,
+       IN      PCHAR                   extra)
+{
+       INT i;
+
+       sprintf(extra, "\n");
+
+#ifdef DOT11_N_SUPPORT
+       sprintf(extra, "%sHT Operating Mode : %d\n", extra, pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode);
+#endif // DOT11_N_SUPPORT //
+
+       sprintf(extra, "%s\n%-19s%-4s%-4s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s\n", extra,
+                       "MAC", "AID", "BSS", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC");
+
+       for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
+       {
+               PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+
+               if (strlen(extra) > (IW_PRIV_SIZE_MASK - 30))
+                   break;
+               if ((pEntry->ValidAsCLI || pEntry->ValidAsApCli) && (pEntry->Sst == SST_ASSOC))
+               {
+                       sprintf(extra, "%s%02X:%02X:%02X:%02X:%02X:%02X  ", extra,
+                               pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+                               pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]);
+                       sprintf(extra, "%s%-4d", extra, (int)pEntry->Aid);
+                       sprintf(extra, "%s%-4d", extra, (int)pEntry->apidx);
+                       sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi0);
+                       sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi1);
+                       sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi2);
+                       sprintf(extra, "%s%-10s", extra, GetPhyMode(pEntry->HTPhyMode.field.MODE));
+                       sprintf(extra, "%s%-6s", extra, GetBW(pEntry->HTPhyMode.field.BW));
+                       sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.MCS);
+                       sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.ShortGI);
+                       sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.STBC);
+                       sprintf(extra, "%s%-10d, %d, %d%%\n", extra, pEntry->DebugFIFOCount, pEntry->DebugTxCount,
+                                               (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0);
+                       sprintf(extra, "%s\n", extra);
+               }
+       }
+
+       return TRUE;
+}
+
+
diff --git a/drivers/staging/rt2870/wpa.h b/drivers/staging/rt2870/wpa.h
new file mode 100644 (file)
index 0000000..0134ae6
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify  *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * This program is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * You should have received a copy of the GNU General Public License     *
+ * along with this program; if not, write to the                         *
+ * Free Software Foundation, Inc.,                                       *
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                       *
+ *************************************************************************
+
+       Module Name:
+       wpa.h
+
+       Abstract:
+
+       Revision History:
+       Who                     When                    What
+       --------        ----------              ----------------------------------------------
+       Name            Date                    Modification logs
+*/
+
+#ifndef        __WPA_H__
+#define        __WPA_H__
+
+// EAPOL Key descripter frame format related length
+#define LEN_KEY_DESC_NONCE                     32
+#define LEN_KEY_DESC_IV                                16
+#define LEN_KEY_DESC_RSC                       8
+#define LEN_KEY_DESC_ID                                8
+#define LEN_KEY_DESC_REPLAY                    8
+#define LEN_KEY_DESC_MIC                       16
+
+// The length is the EAPoL-Key frame except key data field.
+// Please refer to 802.11i-2004 ,Figure 43u in p.78
+#define LEN_EAPOL_KEY_MSG                      (sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE)
+
+// EAP Code Type.
+#define EAP_CODE_REQUEST       1
+#define EAP_CODE_RESPONSE      2
+#define EAP_CODE_SUCCESS    3
+#define EAP_CODE_FAILURE    4
+
+// EAPOL frame Protocol Version
+#define        EAPOL_VER                                       1
+#define        EAPOL_VER2                                      2
+
+// EAPOL-KEY Descriptor Type
+#define        WPA1_KEY_DESC                           0xfe
+#define WPA2_KEY_DESC               0x02
+
+// Key Descriptor Version of Key Information
+#define        DESC_TYPE_TKIP                          1
+#define        DESC_TYPE_AES                           2
+#define DESC_TYPE_MESH                         3
+
+#define LEN_MSG1_2WAY               0x7f
+#define MAX_LEN_OF_EAP_HS           256
+
+#define LEN_MASTER_KEY                         32
+
+// EAPOL EK, MK
+#define LEN_EAP_EK                                     16
+#define LEN_EAP_MICK                           16
+#define LEN_EAP_KEY                                    ((LEN_EAP_EK)+(LEN_EAP_MICK))
+// TKIP key related
+#define LEN_PMKID                                      16
+#define LEN_TKIP_EK                                    16
+#define LEN_TKIP_RXMICK                                8
+#define LEN_TKIP_TXMICK                                8
+#define LEN_AES_EK                                     16
+#define LEN_AES_KEY                                    LEN_AES_EK
+#define LEN_TKIP_KEY                           ((LEN_TKIP_EK)+(LEN_TKIP_RXMICK)+(LEN_TKIP_TXMICK))
+#define TKIP_AP_TXMICK_OFFSET          ((LEN_EAP_KEY)+(LEN_TKIP_EK))
+#define TKIP_AP_RXMICK_OFFSET          (TKIP_AP_TXMICK_OFFSET+LEN_TKIP_TXMICK)
+#define TKIP_GTK_LENGTH                                ((LEN_TKIP_EK)+(LEN_TKIP_RXMICK)+(LEN_TKIP_TXMICK))
+#define LEN_PTK                                                ((LEN_EAP_KEY)+(LEN_TKIP_KEY))
+#define MIN_LEN_OF_GTK                         5
+
+// RSN IE Length definition
+#define MAX_LEN_OF_RSNIE               90
+#define MIN_LEN_OF_RSNIE               8
+
+//EAP Packet Type
+#define        EAPPacket               0
+#define        EAPOLStart              1
+#define        EAPOLLogoff             2
+#define        EAPOLKey                3
+#define        EAPOLASFAlert   4
+#define        EAPTtypeMax             5
+
+#define        EAPOL_MSG_INVALID       0
+#define        EAPOL_PAIR_MSG_1        1
+#define        EAPOL_PAIR_MSG_2        2
+#define        EAPOL_PAIR_MSG_3        3
+#define        EAPOL_PAIR_MSG_4        4
+#define        EAPOL_GROUP_MSG_1       5
+#define        EAPOL_GROUP_MSG_2       6
+
+#define PAIRWISEKEY                                    1
+#define GROUPKEY                                       0
+
+// Retry timer counter initial value
+#define PEER_MSG1_RETRY_TIMER_CTR           0
+#define PEER_MSG3_RETRY_TIMER_CTR           10
+#define GROUP_MSG1_RETRY_TIMER_CTR          20
+
+
+#define EAPOL_START_DISABLE                                    0
+#define EAPOL_START_PSK                                                1
+#define EAPOL_START_1X                                         2
+
+#define MIX_CIPHER_WPA_TKIP_ON(x)       (((x) & 0x08) != 0)
+#define MIX_CIPHER_WPA_AES_ON(x)        (((x) & 0x04) != 0)
+#define MIX_CIPHER_WPA2_TKIP_ON(x)      (((x) & 0x02) != 0)
+#define MIX_CIPHER_WPA2_AES_ON(x)       (((x) & 0x01) != 0)
+
+#define ROUND_UP(__x, __y) \
+       (((ULONG)((__x)+((__y)-1))) & ((ULONG)~((__y)-1)))
+
+#define        ADD_ONE_To_64BIT_VAR(_V)                \
+{                                                                              \
+       UCHAR   cnt = LEN_KEY_DESC_REPLAY;      \
+       do                                                                      \
+       {                                                                       \
+               cnt--;                                                  \
+               _V[cnt]++;                                              \
+               if (cnt == 0)                                   \
+                       break;                                          \
+       }while (_V[cnt] == 0);                          \
+}
+
+#define IS_WPA_CAPABILITY(a)       (((a) >= Ndis802_11AuthModeWPA) && ((a) <= Ndis802_11AuthModeWPA1PSKWPA2PSK))
+
+// EAPOL Key Information definition within Key descriptor format
+typedef        struct PACKED _KEY_INFO
+{
+#ifdef RT_BIG_ENDIAN
+       UCHAR   KeyAck:1;
+    UCHAR      Install:1;
+    UCHAR      KeyIndex:2;
+    UCHAR      KeyType:1;
+    UCHAR      KeyDescVer:3;
+    UCHAR      Rsvd:3;
+    UCHAR      EKD_DL:1;               // EKD for AP; DL for STA
+    UCHAR      Request:1;
+    UCHAR      Error:1;
+    UCHAR      Secure:1;
+    UCHAR      KeyMic:1;
+#else
+       UCHAR   KeyMic:1;
+       UCHAR   Secure:1;
+       UCHAR   Error:1;
+       UCHAR   Request:1;
+       UCHAR   EKD_DL:1;       // EKD for AP; DL for STA
+       UCHAR   Rsvd:3;
+       UCHAR   KeyDescVer:3;
+       UCHAR   KeyType:1;
+       UCHAR   KeyIndex:2;
+       UCHAR   Install:1;
+       UCHAR   KeyAck:1;
+#endif
+}      KEY_INFO, *PKEY_INFO;
+
+// EAPOL Key descriptor format
+typedef        struct PACKED _KEY_DESCRIPTER
+{
+       UCHAR           Type;
+       KEY_INFO        KeyInfo;
+       UCHAR           KeyLength[2];
+       UCHAR           ReplayCounter[LEN_KEY_DESC_REPLAY];
+       UCHAR           KeyNonce[LEN_KEY_DESC_NONCE];
+       UCHAR           KeyIv[LEN_KEY_DESC_IV];
+       UCHAR           KeyRsc[LEN_KEY_DESC_RSC];
+       UCHAR           KeyId[LEN_KEY_DESC_ID];
+       UCHAR           KeyMic[LEN_KEY_DESC_MIC];
+       UCHAR           KeyDataLen[2];
+       UCHAR           KeyData[MAX_LEN_OF_RSNIE];
+}      KEY_DESCRIPTER, *PKEY_DESCRIPTER;
+
+typedef        struct PACKED _EAPOL_PACKET
+{
+       UCHAR                           ProVer;
+       UCHAR                           ProType;
+       UCHAR                           Body_Len[2];
+       KEY_DESCRIPTER          KeyDesc;
+}      EAPOL_PACKET, *PEAPOL_PACKET;
+
+//802.11i D10 page 83
+typedef struct PACKED _GTK_ENCAP
+{
+#ifndef RT_BIG_ENDIAN
+    UCHAR               Kid:2;
+    UCHAR               tx:1;
+    UCHAR               rsv:5;
+    UCHAR               rsv1;
+#else
+    UCHAR               rsv:5;
+    UCHAR               tx:1;
+    UCHAR               Kid:2;
+    UCHAR               rsv1;
+#endif
+    UCHAR               GTK[TKIP_GTK_LENGTH];
+}   GTK_ENCAP, *PGTK_ENCAP;
+
+typedef struct PACKED _KDE_ENCAP
+{
+    UCHAR               Type;
+    UCHAR               Len;
+    UCHAR               OUI[3];
+    UCHAR               DataType;
+    GTK_ENCAP      GTKEncap;
+}   KDE_ENCAP, *PKDE_ENCAP;
+
+// For WPA1
+typedef struct PACKED _RSNIE {
+    UCHAR   oui[4];
+    USHORT  version;
+    UCHAR   mcast[4];
+    USHORT  ucount;
+    struct PACKED {
+        UCHAR oui[4];
+    }ucast[1];
+} RSNIE, *PRSNIE;
+
+// For WPA2
+typedef struct PACKED _RSNIE2 {
+    USHORT  version;
+    UCHAR   mcast[4];
+    USHORT  ucount;
+    struct PACKED {
+        UCHAR oui[4];
+    }ucast[1];
+} RSNIE2, *PRSNIE2;
+
+// AKM Suite
+typedef struct PACKED _RSNIE_AUTH {
+    USHORT acount;
+    struct PACKED {
+        UCHAR oui[4];
+    }auth[1];
+} RSNIE_AUTH,*PRSNIE_AUTH;
+
+typedef        union PACKED _RSN_CAPABILITIES  {
+       struct  PACKED {
+#ifdef RT_BIG_ENDIAN
+        USHORT         Rsvd:10;
+        USHORT         GTKSA_R_Counter:2;
+        USHORT         PTKSA_R_Counter:2;
+        USHORT         No_Pairwise:1;
+               USHORT          PreAuth:1;
+#else
+        USHORT         PreAuth:1;
+               USHORT          No_Pairwise:1;
+               USHORT          PTKSA_R_Counter:2;
+               USHORT          GTKSA_R_Counter:2;
+               USHORT          Rsvd:10;
+#endif
+       }       field;
+       USHORT                  word;
+}      RSN_CAPABILITIES, *PRSN_CAPABILITIES;
+
+typedef struct PACKED _EAP_HDR {
+    UCHAR   ProVer;
+    UCHAR   ProType;
+    UCHAR   Body_Len[2];
+    UCHAR   code;
+    UCHAR   identifier;
+    UCHAR   length[2]; // including code and identifier, followed by length-2 octets of data
+} EAP_HDR, *PEAP_HDR;
+
+// For supplicant state machine states. 802.11i Draft 4.1, p. 97
+// We simplified it
+typedef        enum    _WpaState
+{
+       SS_NOTUSE,                              // 0
+       SS_START,                               // 1
+       SS_WAIT_MSG_3,                  // 2
+       SS_WAIT_GROUP,                  // 3
+       SS_FINISH,                      // 4
+       SS_KEYUPDATE,                   // 5
+}      WPA_STATE;
+
+//
+//     The definition of the cipher combination
+//
+//      bit3   bit2  bit1   bit0
+//     +------------+------------+
+//     |         WPA    |         WPA2   |
+//     +------+-----+------+-----+
+//     | TKIP | AES | TKIP | AES |
+//     |       0  |  1  |   1  |  0  | -> 0x06
+//     |       0  |  1  |   1  |  1  | -> 0x07
+//     |       1  |  0  |   0  |  1  | -> 0x09
+//     |       1  |  0  |   1  |  1  | -> 0x0B
+//     |       1  |  1  |   0  |  1  | -> 0x0D
+//     |       1  |  1  |   1  |  0  | -> 0x0E
+//     |       1  |  1  |   1  |  1  | -> 0x0F
+//     +------+-----+------+-----+
+//
+typedef        enum    _WpaMixPairCipher
+{
+       MIX_CIPHER_NOTUSE                       = 0x00,
+       WPA_NONE_WPA2_TKIPAES           = 0x03,         // WPA2-TKIPAES
+       WPA_AES_WPA2_TKIP                       = 0x06,
+       WPA_AES_WPA2_TKIPAES            = 0x07,
+       WPA_TKIP_WPA2_AES                       = 0x09,
+       WPA_TKIP_WPA2_TKIPAES           = 0x0B,
+       WPA_TKIPAES_WPA2_NONE           = 0x0C,         // WPA-TKIPAES
+       WPA_TKIPAES_WPA2_AES            = 0x0D,
+       WPA_TKIPAES_WPA2_TKIP           = 0x0E,
+       WPA_TKIPAES_WPA2_TKIPAES        = 0x0F,
+}      WPA_MIX_PAIR_CIPHER;
+
+typedef struct PACKED _RSN_IE_HEADER_STRUCT    {
+       UCHAR           Eid;
+       UCHAR           Length;
+       USHORT          Version;        // Little endian format
+}      RSN_IE_HEADER_STRUCT, *PRSN_IE_HEADER_STRUCT;
+
+// Cipher suite selector types
+typedef struct PACKED _CIPHER_SUITE_STRUCT     {
+       UCHAR           Oui[3];
+       UCHAR           Type;
+}      CIPHER_SUITE_STRUCT, *PCIPHER_SUITE_STRUCT;
+
+// Authentication and Key Management suite selector
+typedef struct PACKED _AKM_SUITE_STRUCT        {
+       UCHAR           Oui[3];
+       UCHAR           Type;
+}      AKM_SUITE_STRUCT, *PAKM_SUITE_STRUCT;
+
+// RSN capability
+typedef struct PACKED _RSN_CAPABILITY  {
+       USHORT          Rsv:10;
+       USHORT          GTKSAReplayCnt:2;
+       USHORT          PTKSAReplayCnt:2;
+       USHORT          NoPairwise:1;
+       USHORT          PreAuth:1;
+}      RSN_CAPABILITY, *PRSN_CAPABILITY;
+
+#endif