--- /dev/null
+From 0d43598686dd4b9c4ef8fe9027ac60b5335feaa8 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Date: Wed, 17 Dec 2008 17:04:23 -0800
+Subject: [PATCH 1/4] Staging: add rt2870 wireless driver
+
+From: Greg Kroah-Hartman <gregkh@suse.de>
+
+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>
+---
+ drivers/staging/Kconfig | 2
+ drivers/staging/Makefile | 1
+ drivers/staging/rt2870/2870_main_dev.c | 1612 ++++
+ drivers/staging/rt2870/Kconfig | 6
+ drivers/staging/rt2870/Makefile | 47
+ drivers/staging/rt2870/TODO | 10
+ drivers/staging/rt2870/aironet.h | 210
+ drivers/staging/rt2870/ap.h | 562 +
+ drivers/staging/rt2870/chlist.h | 1296 +++
+ drivers/staging/rt2870/common/2870_rtmp_init.c | 1778 +++++
+ drivers/staging/rt2870/common/action.c | 1046 +++
+ drivers/staging/rt2870/common/action.h | 68
+ drivers/staging/rt2870/common/ba_action.c | 1798 +++++
+ drivers/staging/rt2870/common/cmm_data.c | 2734 +++++++
+ drivers/staging/rt2870/common/cmm_data_2870.c | 963 ++
+ drivers/staging/rt2870/common/cmm_info.c | 3712 ++++++++++
+ drivers/staging/rt2870/common/cmm_sanity.c | 1663 ++++
+ drivers/staging/rt2870/common/cmm_sync.c | 711 ++
+ drivers/staging/rt2870/common/cmm_wpa.c | 1654 ++++
+ drivers/staging/rt2870/common/dfs.c | 453 +
+ drivers/staging/rt2870/common/eeprom.c | 254
+ drivers/staging/rt2870/common/firmware.h | 558 +
+ drivers/staging/rt2870/common/md5.c | 1427 ++++
+ drivers/staging/rt2870/common/mlme.c | 8609 +++++++++++++++++++++++++
+ drivers/staging/rt2870/common/netif_block.c | 144
+ drivers/staging/rt2870/common/rtmp_init.c | 4132 +++++++++++
+ drivers/staging/rt2870/common/rtmp_tkip.c | 1613 ++++
+ drivers/staging/rt2870/common/rtmp_wep.c | 508 +
+ drivers/staging/rt2870/common/rtusb_bulk.c | 1981 +++++
+ drivers/staging/rt2870/common/rtusb_data.c | 229
+ drivers/staging/rt2870/common/rtusb_io.c | 2006 +++++
+ drivers/staging/rt2870/common/spectrum.c | 1876 +++++
+ drivers/staging/rt2870/dfs.h | 100
+ drivers/staging/rt2870/leap.h | 215
+ drivers/staging/rt2870/link_list.h | 134
+ drivers/staging/rt2870/md4.h | 42
+ drivers/staging/rt2870/md5.h | 107
+ drivers/staging/rt2870/mlme.h | 1471 ++++
+ drivers/staging/rt2870/netif_block.h | 58
+ drivers/staging/rt2870/oid.h | 1091 +++
+ drivers/staging/rt2870/rt2870.h | 761 ++
+ drivers/staging/rt2870/rt28xx.h | 2689 +++++++
+ drivers/staging/rt2870/rt_ate.c | 6452 ++++++++++++++++++
+ drivers/staging/rt2870/rt_ate.h | 315
+ drivers/staging/rt2870/rt_config.h | 104
+ drivers/staging/rt2870/rt_linux.c | 1095 +++
+ drivers/staging/rt2870/rt_linux.h | 908 ++
+ drivers/staging/rt2870/rt_main_dev.c | 1863 +++++
+ drivers/staging/rt2870/rt_profile.c | 2016 +++++
+ drivers/staging/rt2870/rtmp.h | 7586 ++++++++++++++++++++++
+ drivers/staging/rt2870/rtmp_ckipmic.h | 113
+ drivers/staging/rt2870/rtmp_def.h | 1622 ++++
+ drivers/staging/rt2870/rtmp_type.h | 94
+ drivers/staging/rt2870/spectrum.h | 322
+ drivers/staging/rt2870/spectrum_def.h | 95
+ drivers/staging/rt2870/sta/aironet.c | 1312 +++
+ drivers/staging/rt2870/sta/assoc.c | 2039 +++++
+ drivers/staging/rt2870/sta/auth.c | 474 +
+ drivers/staging/rt2870/sta/auth_rsp.c | 166
+ drivers/staging/rt2870/sta/connect.c | 2822 ++++++++
+ drivers/staging/rt2870/sta/dls.c | 2210 ++++++
+ drivers/staging/rt2870/sta/rtmp_data.c | 2619 +++++++
+ drivers/staging/rt2870/sta/sanity.c | 420 +
+ drivers/staging/rt2870/sta/sync.c | 1753 +++++
+ drivers/staging/rt2870/sta/wpa.c | 2107 ++++++
+ drivers/staging/rt2870/sta_ioctl.c | 7068 ++++++++++++++++++++
+ drivers/staging/rt2870/sta_ioctl.c.patch | 18
+ drivers/staging/rt2870/tmp60 | 7037 ++++++++++++++++++++
+ drivers/staging/rt2870/tmp61 | 7037 ++++++++++++++++++++
+ drivers/staging/rt2870/wpa.h | 357 +
+ 70 files changed, 110355 insertions(+)
+ create mode 100644 drivers/staging/rt2870/2870_main_dev.c
+ create mode 100644 drivers/staging/rt2870/Kconfig
+ create mode 100644 drivers/staging/rt2870/Makefile
+ create mode 100644 drivers/staging/rt2870/TODO
+ create mode 100644 drivers/staging/rt2870/aironet.h
+ create mode 100644 drivers/staging/rt2870/ap.h
+ create mode 100644 drivers/staging/rt2870/chlist.h
+ create mode 100644 drivers/staging/rt2870/common/2870_rtmp_init.c
+ create mode 100644 drivers/staging/rt2870/common/action.c
+ create mode 100644 drivers/staging/rt2870/common/action.h
+ create mode 100644 drivers/staging/rt2870/common/ba_action.c
+ create mode 100644 drivers/staging/rt2870/common/cmm_data.c
+ create mode 100644 drivers/staging/rt2870/common/cmm_data_2870.c
+ create mode 100644 drivers/staging/rt2870/common/cmm_info.c
+ create mode 100644 drivers/staging/rt2870/common/cmm_sanity.c
+ create mode 100644 drivers/staging/rt2870/common/cmm_sync.c
+ create mode 100644 drivers/staging/rt2870/common/cmm_wpa.c
+ create mode 100644 drivers/staging/rt2870/common/dfs.c
+ create mode 100644 drivers/staging/rt2870/common/eeprom.c
+ create mode 100644 drivers/staging/rt2870/common/firmware.h
+ create mode 100644 drivers/staging/rt2870/common/md5.c
+ create mode 100644 drivers/staging/rt2870/common/mlme.c
+ create mode 100644 drivers/staging/rt2870/common/netif_block.c
+ create mode 100644 drivers/staging/rt2870/common/rtmp_init.c
+ create mode 100644 drivers/staging/rt2870/common/rtmp_tkip.c
+ create mode 100644 drivers/staging/rt2870/common/rtmp_wep.c
+ create mode 100644 drivers/staging/rt2870/common/rtusb_bulk.c
+ create mode 100644 drivers/staging/rt2870/common/rtusb_data.c
+ create mode 100644 drivers/staging/rt2870/common/rtusb_io.c
+ create mode 100644 drivers/staging/rt2870/common/spectrum.c
+ create mode 100644 drivers/staging/rt2870/dfs.h
+ create mode 100644 drivers/staging/rt2870/leap.h
+ create mode 100644 drivers/staging/rt2870/link_list.h
+ create mode 100644 drivers/staging/rt2870/md4.h
+ create mode 100644 drivers/staging/rt2870/md5.h
+ create mode 100644 drivers/staging/rt2870/mlme.h
+ create mode 100644 drivers/staging/rt2870/netif_block.h
+ create mode 100644 drivers/staging/rt2870/oid.h
+ create mode 100644 drivers/staging/rt2870/rt2870.h
+ create mode 100644 drivers/staging/rt2870/rt28xx.h
+ create mode 100644 drivers/staging/rt2870/rt_ate.c
+ create mode 100644 drivers/staging/rt2870/rt_ate.h
+ create mode 100644 drivers/staging/rt2870/rt_config.h
+ create mode 100644 drivers/staging/rt2870/rt_linux.c
+ create mode 100644 drivers/staging/rt2870/rt_linux.h
+ create mode 100644 drivers/staging/rt2870/rt_main_dev.c
+ create mode 100644 drivers/staging/rt2870/rt_profile.c
+ create mode 100644 drivers/staging/rt2870/rtmp.h
+ create mode 100644 drivers/staging/rt2870/rtmp_ckipmic.h
+ create mode 100644 drivers/staging/rt2870/rtmp_def.h
+ create mode 100644 drivers/staging/rt2870/rtmp_type.h
+ create mode 100644 drivers/staging/rt2870/spectrum.h
+ create mode 100644 drivers/staging/rt2870/spectrum_def.h
+ create mode 100644 drivers/staging/rt2870/sta/aironet.c
+ create mode 100644 drivers/staging/rt2870/sta/assoc.c
+ create mode 100644 drivers/staging/rt2870/sta/auth.c
+ create mode 100644 drivers/staging/rt2870/sta/auth_rsp.c
+ create mode 100644 drivers/staging/rt2870/sta/connect.c
+ create mode 100644 drivers/staging/rt2870/sta/dls.c
+ create mode 100644 drivers/staging/rt2870/sta/rtmp_data.c
+ create mode 100644 drivers/staging/rt2870/sta/sanity.c
+ create mode 100644 drivers/staging/rt2870/sta/sync.c
+ create mode 100644 drivers/staging/rt2870/sta/wpa.c
+ create mode 100644 drivers/staging/rt2870/sta_ioctl.c
+ create mode 100644 drivers/staging/rt2870/sta_ioctl.c.patch
+ create mode 100644 drivers/staging/rt2870/tmp60
+ create mode 100644 drivers/staging/rt2870/tmp61
+ create mode 100644 drivers/staging/rt2870/wpa.h
+
+--- a/drivers/staging/Kconfig
++++ b/drivers/staging/Kconfig
+@@ -49,6 +49,8 @@ source "drivers/staging/otus/Kconfig"
+
+ source "drivers/staging/rt2860/Kconfig"
+
++source "drivers/staging/rt2870/Kconfig"
++
+ source "drivers/staging/benet/Kconfig"
+
+ source "drivers/staging/rtl8187se/Kconfig"
+--- a/drivers/staging/Makefile
++++ b/drivers/staging/Makefile
+@@ -16,5 +16,6 @@ obj-$(CONFIG_USB_ATMEL) += at76_usb/
+ obj-$(CONFIG_AGNX) += agnx/
+ obj-$(CONFIG_OTUS) += otus/
+ obj-$(CONFIG_RT2860) += rt2860/
++obj-$(CONFIG_RT2870) += rt2870/
+ obj-$(CONFIG_BENET) += benet/
+ obj-$(CONFIG_RTL8187SE) += rtl8187se/
+--- /dev/null
++++ b/drivers/staging/rt2870/2870_main_dev.c
+@@ -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;
++
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/aironet.h
+@@ -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__
+--- /dev/null
++++ b/drivers/staging/rt2870/ap.h
+@@ -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__
++
+--- /dev/null
++++ b/drivers/staging/rt2870/chlist.h
+@@ -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__
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/2870_rtmp_init.c
+@@ -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 */
+--- /dev/null
++++ b/drivers/staging/rt2870/common/action.c
+@@ -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;
++}
+--- /dev/null
++++ b/drivers/staging/rt2870/common/action.h
+@@ -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__ */
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/ba_action.c
+@@ -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 //
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/cmm_data_2870.c
+@@ -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 //
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/cmm_data.c
+@@ -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);
++ }
++ }
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/cmm_info.c
+@@ -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;
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/cmm_sanity.c
+@@ -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 //
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/cmm_sync.c
+@@ -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);
++}
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/cmm_wpa.c
+@@ -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;
++
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/dfs.c
+@@ -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;
++}
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/eeprom.c
+@@ -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);
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/firmware.h
+@@ -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, } ;
+--- /dev/null
++++ b/drivers/staging/rt2870/common/md5.c
+@@ -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;
++}
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/mlme.c
+@@ -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));
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/netif_block.c
+@@ -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;
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/rtmp_init.c
+@@ -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"));
++}
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/rtmp_tkip.c
+@@ -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);
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/rtmp_wep.c
+@@ -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);
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/rtusb_bulk.c
+@@ -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]);
++ }
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/rtusb_data.c
+@@ -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;
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/rtusb_io.c
+@@ -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 */
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/common/spectrum.c
+@@ -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;
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/dfs.h
+@@ -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);
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/Kconfig
+@@ -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.
++
+--- /dev/null
++++ b/drivers/staging/rt2870/leap.h
+@@ -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__
+--- /dev/null
++++ b/drivers/staging/rt2870/link_list.h
+@@ -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__ //
++
+--- /dev/null
++++ b/drivers/staging/rt2870/Makefile
+@@ -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
++
+--- /dev/null
++++ b/drivers/staging/rt2870/md4.h
+@@ -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
+--- /dev/null
++++ b/drivers/staging/rt2870/md5.h
+@@ -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 */
++
+--- /dev/null
++++ b/drivers/staging/rt2870/mlme.h
+@@ -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__
+--- /dev/null
++++ b/drivers/staging/rt2870/netif_block.h
+@@ -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__
++
+--- /dev/null
++++ b/drivers/staging/rt2870/oid.h
+@@ -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_
++
+--- /dev/null
++++ b/drivers/staging/rt2870/rt2870.h
+@@ -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__
+--- /dev/null
++++ b/drivers/staging/rt2870/rt28xx.h
+@@ -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__
+--- /dev/null
++++ b/drivers/staging/rt2870/rt_ate.c
+@@ -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 //
++
+--- /dev/null
++++ b/drivers/staging/rt2870/rt_ate.h
+@@ -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__ //
+--- /dev/null
++++ b/drivers/staging/rt2870/rt_config.h
+@@ -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__
++
+--- /dev/null
++++ b/drivers/staging/rt2870/rt_linux.c
+@@ -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(¤t->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(¤t->sigmask_lock, flags);
++ flush_signals(current);
++ recalc_sigpending(current);
++ spin_unlock_irqrestore(¤t->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);
++ }
++ }
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/rt_linux.h
+@@ -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);
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/rt_main_dev.c
+@@ -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, ®); // clear garbage interrupts
++ printk("0x1300 = %08x\n", reg);
++ }
++
++ {
++// u32 reg;
++// u8 byte;
++// u16 tmp;
++
++// RTMP_IO_READ32(pAd, XIFS_TIME_CFG, ®);
++
++// 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;
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/rtmp_ckipmic.h
+@@ -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__
+--- /dev/null
++++ b/drivers/staging/rt2870/rtmp_def.h
+@@ -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__
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/rtmp.h
+@@ -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__
++
+--- /dev/null
++++ b/drivers/staging/rt2870/rtmp_type.h
+@@ -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__
++
+--- /dev/null
++++ b/drivers/staging/rt2870/rt_profile.c
+@@ -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 //
++
+--- /dev/null
++++ b/drivers/staging/rt2870/spectrum_def.h
+@@ -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__ //
++
+--- /dev/null
++++ b/drivers/staging/rt2870/spectrum.h
+@@ -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__ //
++
+--- /dev/null
++++ b/drivers/staging/rt2870/sta/aironet.c
+@@ -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;
++ }
++}
+--- /dev/null
++++ b/drivers/staging/rt2870/sta/assoc.c
+@@ -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;
++}
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/sta/auth.c
+@@ -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);
++}
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/sta/auth_rsp.c
+@@ -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"));
++ }
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/sta/connect.c
+@@ -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;
++}
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/sta/dls.c
+@@ -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;
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/sta_ioctl.c
+@@ -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, ®BBP);
++ }
++ else
++#endif // RALINK_ATE //
++ {
++ RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP);
++ }
++ 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, ®BBP);
++ }
++ 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, ®BBP);
++ }
++ 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, ®BBP);
++ }
++ else
++#endif // RALINK_ATE //
++ RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP);
++ 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;
++}
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/sta_ioctl.c.patch
+@@ -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[];
+--- /dev/null
++++ b/drivers/staging/rt2870/sta/rtmp_data.c
+@@ -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);
++ }
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/sta/sanity.c
+@@ -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;
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/sta/sync.c
+@@ -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;
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/sta/wpa.c
+@@ -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, >K[16], LEN_TKIP_RXMICK);
++ NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, >K[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;
++}
++
+--- /dev/null
++++ b/drivers/staging/rt2870/tmp60
+@@ -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, ®BBP);
++ }
++ else
++#endif // RALINK_ATE //
++ {
++ RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP);
++ }
++ 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, ®BBP);
++ }
++ 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, ®BBP);
++ }
++ 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, ®BBP);
++ }
++ else
++#endif // RALINK_ATE //
++ RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP);
++ 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;
++}
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/tmp61
+@@ -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, ®BBP);
++ }
++ else
++#endif // RALINK_ATE //
++ {
++ RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP);
++ }
++ 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, ®BBP);
++ }
++ 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, ®BBP);
++ }
++ 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, ®BBP);
++ }
++ else
++#endif // RALINK_ATE //
++ RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP);
++ 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;
++}
++
++
+--- /dev/null
++++ b/drivers/staging/rt2870/TODO
+@@ -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.
+--- /dev/null
++++ b/drivers/staging/rt2870/wpa.h
+@@ -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