/*************************************************************************** 
 * RT2x00 SourceForge Project - http://rt2x00.sourceforge.net              * 
 *                                                                         * 
 *   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.             * 
 *                                                                         * 
 *   Licensed under the GNU GPL                                            * 
 *   Original code supplied under license from RaLink Inc, 2004.           * 
 ***************************************************************************/

/*************************************************************************** 
 *	Module Name:	rtusb_init.c
 *	
 *	Abstract:
 *
 *	Revision History:
 *	Who		When		What
 *	--------	----------	-------------------------------
 *	Name		Date		Modification logs
 *	Jan Lee		2005-06-01	Release
 *	RobinC		02-06-2005	usb_kill_urb fixes for kernels =>2.6.7
 ***************************************************************************/

#include	"rt_config.h"

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#include <linux/kthread.h>
#define RT2570_USB_ALLOC_URB(iso)	usb_alloc_urb(iso, GFP_ATOMIC);	
#else
#define RT2570_USB_ALLOC_URB(iso)	usb_alloc_urb(iso);
#endif

USHORT	 BBPRegTable[] = {
	0x0302,  // R03
	0x0419,  // R04
	0x0E1C,  // R14
	0x0F30,  // R15
	0x10ac,  // R16
	0x1148,  // R17
	0x1218,  // R18
	0x13ff,  // R19
	0x141E,  // R20
	0x1508,  // R21
	0x1608,  // R22
	0x1708,  // R23
//modified by david    0x1870,	// R24
	0x1880,  // R24	modified by david
//modified by gary	  0x1940,  // R25
	0x1950,  // R25	//modified by gary
	0x1A08,  // R26
	0x1B23,  // R27
	0x1E10,  // R30
	0x1F2B,  // R31
	0x20B9,  // R32
	0x2212,  // R34
	0x2350,  // R35
	0x27c4,  // R39
	0x2802,  // R40
	0x2960,  // R41
	0x3510,  // R53
	0x3618,  // R54
	0x3808,  // R56
	0x3910,  // R57
	0x3A08,  // R58
	0x3D60,  // R61
	0x3E10,  // R62
	0x4BFF,  // R75//by MAX
};
#define	NUM_BBP_REG_PARMS	(sizeof(BBPRegTable) / sizeof(USHORT))
VOID RTMPReadParametersFromFile(PRT2570ADAPTER pAd)
{
#if 0
	UCHAR					src[70];
	struct file				*srcf;
	INT 						retval, orgfsuid, orgfsgid;
	mm_segment_t			orgfs;
	CHAR									buffer[MAX_INI_BUFFER_SIZE];
	CHAR									tmpbuf[255];	
	UCHAR									Channel;
	ULONG									ulInfo;
	RT_802_11_PREAMBLE						Preamble;
	int 									KeyLen;
	int 									i;
	BOOLEAN 								bIsHex = TRUE;
	UCHAR									keyMaterial[40];	
	ULONG		rate_mapping[12] = {1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54}; //according to README
	// Save uid and gid used for filesystem access.
	// Set user and group to 0 (root)	
	memset(src, 0, sizeof(src));
	memcpy(src, PROFILE_PATH, sizeof(PROFILE_PATH));
	DBGPRINT(RT_DEBUG_TEMP, "--> Read %s \n", src);
	orgfsuid = current->fsuid;
	DBGPRINT(RT_DEBUG_TEMP, "1. orgfsuid = %x\n",orgfsuid);
	orgfsgid = current->fsgid;
	DBGPRINT(RT_DEBUG_TEMP, "2. %x\n",orgfsgid);
	current->fsuid= 0;
	current->fsgid = 0;
	orgfs = get_fs();
	DBGPRINT(RT_DEBUG_TEMP, "4. read_orgfs=0x%x\n",orgfs);
	set_fs(KERNEL_DS);
	if (src && *src) 
	{
		DBGPRINT(RT_DEBUG_TRACE, "--> Read %s \n", src);
		srcf = filp_open(src, O_RDONLY , 0);
		if (IS_ERR(srcf)) 
		{
			DBGPRINT(RT_DEBUG_TRACE, "--> 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) 
			{
				retval=srcf->f_op->read(srcf, buffer, MAX_INI_BUFFER_SIZE, &srcf->f_pos);
				if (retval < 0)
				{
					DBGPRINT(RT_DEBUG_TEMP, "--> Read %s error %d\n", src, -retval);
				}
				else
				{
					//CountryRegion
					if (RTMPGetKeyParameter("Default", "CountryRegion", tmpbuf, 255, buffer))
					{
						ulInfo = simple_strtol(tmpbuf, 0, 10);
						if ((ulInfo >= REGION_MIN) && (ulInfo <= REGION_MAX) )
						{
							pAd->PortCfg.CountryRegion = (UCHAR) ulInfo;
							DBGPRINT(RT_DEBUG_TRACE, "%s::(CountryRegion=%d)\n", __FUNCTION__, pAd->PortCfg.CountryRegion);
						}
					}
					//SSID
					memset(tmpbuf, 0x00, 255);
					if (RTMPGetKeyParameter("Default", "SSID", pAd->PortCfg.Ssid, 32, buffer))
					{
						pAd->PortCfg.SsidLen = strlen(pAd->PortCfg.Ssid);
						pAd->Mlme.CntlAux.SsidLen = pAd->PortCfg.SsidLen;
						memcpy(pAd->Mlme.CntlAux.Ssid, pAd->PortCfg.Ssid, pAd->Mlme.CntlAux.SsidLen);

						DBGPRINT(RT_DEBUG_TRACE, "%s::(SSID=%s Len=%d)\n", __FUNCTION__, pAd->PortCfg.Ssid, pAd->PortCfg.SsidLen);
					}
					 //NetworkType
					if (RTMPGetKeyParameter("Default", "NetworkType", tmpbuf, 255, buffer))
					{
						pAd->bConfigChanged = TRUE;
						if (strcmp(tmpbuf, "Adhoc") == 0)
							pAd->PortCfg.BssType = BSS_INDEP;
						else //Default Infrastructure mode
							pAd->PortCfg.BssType = BSS_INFRA;
						// Reset Ralink supplicant to not use, it will be set to start when UI set PMK key
						pAd->PortCfg.WpaState = SS_NOTUSE;
						DBGPRINT(RT_DEBUG_TEMP, "%s::(NetworkType=%d)\n", __FUNCTION__, pAd->PortCfg.BssType);
					}
					//WirelessMode
					if (RTMPGetKeyParameter("Default", "WirelessMode", tmpbuf, 10, buffer))
					{
						ulInfo = simple_strtol(tmpbuf, 0, 10);
						if ((ulInfo == PHY_11BG_MIXED) || (ulInfo == PHY_11B) ||
							(ulInfo == PHY_11A) || (ulInfo == PHY_11ABG_MIXED))
						{
							RTMPSetPhyMode(pAd, ulInfo);
							DBGPRINT(RT_DEBUG_TEMP, "%s::(WirelessMode=%d)\n", __FUNCTION__, ulInfo);
						}
					}
					//TxRate
					if (RTMPGetKeyParameter("Default", "TxRate", tmpbuf, 10, buffer))
					{
						ulInfo = simple_strtol(tmpbuf, 0, 10);
						{
							if (ulInfo == 0)
								RT2570SetDesiredRates(pAd, -1);
							else if (ulInfo < 13){
					RT2570SetDesiredRates(pAd, (LONG) (rate_mapping[ulInfo-1] * 1000000));
							DBGPRINT(RT_DEBUG_TEMP, "1. %s::(TxRate=%d Mbps %d)\n", __FUNCTION__, rate_mapping[ulInfo-1],ulInfo);
								}
							DBGPRINT(RT_DEBUG_TEMP, "3. %s::(TxRate=%d Mbps %d)\n", __FUNCTION__, rate_mapping[ulInfo-1],ulInfo);
						}
					}
					//Channel
					if (RTMPGetKeyParameter("Default", "Channel", tmpbuf, 10, buffer))
					{
						Channel = (UCHAR) simple_strtol(tmpbuf, 0, 10);
						if (ChannelSanity(pAd, Channel) == TRUE)
						{
							pAd->PortCfg.Channel = Channel;
							// If default profile in Registry is an ADHOC network, driver should use the specified channel 
							// number when starting IBSS the first time, because RaConfig is passive and will not set this
							// via OID_802_11_CONFIGURATION upon driver bootup.
							pAd->PortCfg.IbssConfig.Channel = pAd->PortCfg.Channel;
							DBGPRINT(RT_DEBUG_TEMP, "%s::(Channel=%d)\n", __FUNCTION__, Channel);
						}
					}
					//BGProtection
					if (RTMPGetKeyParameter("Default", "BGProtection", tmpbuf, 10, buffer))
					{
						switch (simple_strtol(tmpbuf, 0, 10))
						{
							case 1: //Always On
								pAd->PortCfg.UseBGProtection = 1;
								break;
							case 2: //Always OFF
								pAd->PortCfg.UseBGProtection = 2;
								break;
							case 0: //AUTO
							default:
								pAd->PortCfg.UseBGProtection = 0;
								break;
						}
								pAd->PortCfg.UseBGProtection = 2;
						DBGPRINT(RT_DEBUG_TEMP, "%s::(BGProtection=%d)\n", __FUNCTION__, pAd->PortCfg.UseBGProtection);
					}
					//TxPreamble
					if (RTMPGetKeyParameter("Default", "TxPreamble", tmpbuf, 10, buffer))
					{
						Preamble = simple_strtol(tmpbuf, 0, 10);
						switch (Preamble)
						{
							case Rt802_11PreambleShort:
								pAd->PortCfg.WindowsTxPreamble = Preamble;
								MlmeSetTxPreamble(pAd, Rt802_11PreambleShort);
								break;
							case Rt802_11PreambleLong:
							case Rt802_11PreambleAuto:
							default:
								// if user wants AUTO, initialize to LONG here, then change according to AP's
								// capability upon association.
								pAd->PortCfg.WindowsTxPreamble = Preamble;
								MlmeSetTxPreamble(pAd, Rt802_11PreambleLong);
						}
						DBGPRINT(RT_DEBUG_TEMP, "%s::(TxPreamble=%d)\n", __FUNCTION__, Preamble);
					}
					//RTSThreshold
					if (RTMPGetKeyParameter("Default", "RTSThreshold", tmpbuf, 10, buffer))
					{
						ulInfo = simple_strtol(tmpbuf, 0, 10);

						if((ulInfo > 0) && (ulInfo <= MAX_RTS_THRESHOLD))
							pAd->PortCfg.RtsThreshold = (USHORT)ulInfo;
						else 
							pAd->PortCfg.RtsThreshold = MAX_RTS_THRESHOLD;

						DBGPRINT(RT_DEBUG_TEMP, "%s::(RTSThreshold=%d)\n", __FUNCTION__, pAd->PortCfg.RtsThreshold);
					}
					//FragThreshold
					if (RTMPGetKeyParameter("Default", "FragThreshold", tmpbuf, 10, buffer))
					{
						ulInfo = simple_strtol(tmpbuf, 0, 10);

						if ( (ulInfo >= MIN_FRAG_THRESHOLD) && (ulInfo <= MAX_FRAG_THRESHOLD))
							pAd->PortCfg.FragmentThreshold = (USHORT)ulInfo;
						else
							pAd->PortCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;

						if (pAd->PortCfg.FragmentThreshold == MAX_FRAG_THRESHOLD)
							pAd->PortCfg.bFragmentZeroDisable = TRUE;
						else
							pAd->PortCfg.bFragmentZeroDisable = FALSE;

						DBGPRINT(RT_DEBUG_TEMP, "%s::(FragThreshold=%d)\n", __FUNCTION__, ulInfo);
					}
					//TxBurst
					if (RTMPGetKeyParameter("Default", "TxBurst", tmpbuf, 10, buffer))
					{
						ulInfo = simple_strtol(tmpbuf, 0, 10);

						if (ulInfo == 1)
							pAd->PortCfg.EnableTxBurst = TRUE;
						else
							pAd->PortCfg.EnableTxBurst = FALSE;

						DBGPRINT(RT_DEBUG_TEMP, "%s::(TxBurst=%d)\n", __FUNCTION__, pAd->PortCfg.EnableTxBurst);
					}
					//TurboRate
					if (RTMPGetKeyParameter("Default", "TurboRate", tmpbuf, 10, buffer))
					{
						ulInfo = simple_strtol(tmpbuf, 0, 10);

						if (ulInfo == 1)
							pAd->PortCfg.EnableTurboRate = TRUE;
						else
							pAd->PortCfg.EnableTurboRate = FALSE;

						DBGPRINT(RT_DEBUG_TEMP, "%s::(TurboRate=%d)\n", __FUNCTION__, pAd->PortCfg.EnableTurboRate);
					}
					//ShortSlot
					if (RTMPGetKeyParameter("Default", "ShortSlot", tmpbuf, 10, buffer))
					{
						ulInfo = simple_strtol(tmpbuf, 0, 10);

						if (ulInfo == 1)
							pAd->PortCfg.UseShortSlotTime = TRUE;
						else
							pAd->PortCfg.UseShortSlotTime = FALSE;

						DBGPRINT(RT_DEBUG_TEMP, "%s::(ShortSlot=%d)\n", __FUNCTION__, pAd->PortCfg.UseShortSlotTime);
					}
					//POWER_MODE
					if (RTMPGetKeyParameter("Default", "PSMode", tmpbuf, 10, buffer))
					{
						if (pAd->PortCfg.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.
								//	   MlmeSetPsmBit(pAdapter, PWR_SAVE);
									pAd->PortCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP;
								pAd->PortCfg.RecvDtim = TRUE;  // FALSE;
								pAd->PortCfg.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(pAdapter, PWR_SAVE);
								pAd->PortCfg.RecvDtim = TRUE;
									pAd->PortCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP;
								pAd->PortCfg.DefaultListenCount = 3;
							}
							else
							{ //Default Ndis802_11PowerModeCAM
								// clear PSM bit immediately
								MlmeSetPsmBit(pAd, PWR_ACTIVE);
								pAd->PortCfg.RecvDtim = TRUE;
									pAd->PortCfg.WindowsPowerMode = Ndis802_11PowerModeCAM;
							}
							DBGPRINT(RT_DEBUG_TRACE, "%s::(PSMode=%d)\n", __FUNCTION__, pAd->PortCfg.WindowsPowerMode);
						}
					}
					//AuthMode
					if (RTMPGetKeyParameter("Default", "AuthMode", tmpbuf, 10, buffer))
					{
						if ((strcmp(tmpbuf, "SHARED") == 0) || (strcmp(tmpbuf, "shared") == 0)){
							pAd->PortCfg.AuthMode = Ndis802_11AuthModeShared;
						DBGPRINT(RT_DEBUG_INFO, "%s::(AuthMode=shared)\n", __FUNCTION__);
							}
						else if ((strcmp(tmpbuf, "WPAPSK") == 0) || (strcmp(tmpbuf, "wpapsk") == 0))
							pAd->PortCfg.AuthMode = Ndis802_11AuthModeWPAPSK;
						else if ((strcmp(tmpbuf, "WPANONE") == 0) || (strcmp(tmpbuf, "wpanone") == 0))
							pAd->PortCfg.AuthMode = Ndis802_11AuthModeWPANone;
						else{
							pAd->PortCfg.AuthMode = Ndis802_11AuthModeOpen;
						DBGPRINT(RT_DEBUG_INFO, "%s::(AuthMode=open    buf = %s)\n", __FUNCTION__,tmpbuf);
							}

						pAd->PortCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
						DBGPRINT(RT_DEBUG_TEMP, "%s::(AuthMode=%d)\n", __FUNCTION__, pAd->PortCfg.AuthMode);
					}
					//WPAPSK_KEY
					if (RTMPGetKeyParameter("Default", "WPAPSK", tmpbuf, 255, buffer))
					{
						if ((strlen(tmpbuf) >= 8) && (strlen(tmpbuf) <= 64))
						{
							PasswordHash((char *)tmpbuf, pAd->PortCfg.Ssid, pAd->PortCfg.SsidLen, keyMaterial);
							memcpy(pAd->PortCfg.PskKey.Key, keyMaterial, 32);
							// Use RaConfig as PSK agent.
							// Start STA supplicant state machine
							pAd->PortCfg.WpaState = SS_START;
							DBGPRINT(RT_DEBUG_LOUD, "%s WPAPSK Key => \n", __FUNCTION__);
							DBGPRINT(RT_DEBUG_LOUD, "    ");
							for (i = 0; i < 32; i++)
							{
								DBGPRINT_RAW(RT_DEBUG_LOUD, "%02x:", pAd->PortCfg.PskKey.Key[i]);
								if (i%16 == 15) {
								  DBGPRINT_RAW(RT_DEBUG_LOUD, "\n");
								  DBGPRINT(RT_DEBUG_LOUD, "    ");
							}
							DBGPRINT_RAW(RT_DEBUG_LOUD, "\n");
						}
					}
					//DefaultKeyID
					if (RTMPGetKeyParameter("Default", "DefaultKeyID", tmpbuf, 10, buffer))
					{
						ulInfo = simple_strtol(tmpbuf, 0, 10);
						if((ulInfo >= 1 ) && (ulInfo <= 4))
							pAd->PortCfg.DefaultKeyId = (UCHAR) (ulInfo - 1 );
						else
							pAd->PortCfg.DefaultKeyId = 0;

						DBGPRINT(RT_DEBUG_TEMP, "%s::(DefaultKeyID=%d)\n", __FUNCTION__, pAd->PortCfg.DefaultKeyId);
					}
					//Key1Str
					if (RTMPGetKeyParameter("Default", "Key1Str", tmpbuf, 26, buffer))
					{
						KeyLen = strlen(tmpbuf);
						switch (KeyLen)
						{
							case 0:
								pAd->PortCfg.SharedKey[0].KeyLen = 0;
								break;
							case 5: //wep 40 Ascii type
								pAd->PortCfg.SharedKey[0].KeyLen = KeyLen;
								memcpy(pAd->PortCfg.SharedKey[0].Key, tmpbuf, KeyLen);
								DBGPRINT(RT_DEBUG_TEMP, "%s::(11Key1=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Ascii");
								break;
							case 10: //wep 40 Hex type
								for(i=0; i < KeyLen; i++)
								{
									if( !isxdigit(*(tmpbuf+i)) )
									{
										bIsHex = FALSE;
										break;
									}
								}
								
								if (bIsHex)
								{
									pAd->PortCfg.SharedKey[0].KeyLen = KeyLen / 2 ;
									AtoH(tmpbuf, pAd->PortCfg.SharedKey[0].Key, KeyLen / 2);
									DBGPRINT(RT_DEBUG_TEMP, "%s::(Key1=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Hex");
								}
								break;
							case 13: //wep 104 Ascii type
								pAd->PortCfg.SharedKey[0].KeyLen = KeyLen;
								memcpy(pAd->PortCfg.SharedKey[0].Key, tmpbuf, KeyLen);	
								DBGPRINT(RT_DEBUG_TEMP, "%s::(Key1=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Ascii");
								break;
							case 26: //wep 104 Hex type
								for(i=0; i < KeyLen; i++)
								{
									if( !isxdigit(*(tmpbuf+i)) )
									{
										bIsHex = FALSE;
										break;
									}
								}

								if (bIsHex)
								{
									pAd->PortCfg.SharedKey[0].KeyLen = KeyLen / 2 ;
									AtoH(tmpbuf, pAd->PortCfg.SharedKey[0].Key, KeyLen / 2);
									DBGPRINT(RT_DEBUG_TEMP, "%s::(Key1=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Hex");
								}
								break;
							default:
								pAd->PortCfg.SharedKey[0].KeyLen = 0;
								DBGPRINT(RT_DEBUG_TRACE, "%s::Invalid Key (=%s)\n", __FUNCTION__, tmpbuf);
						}
						DBGPRINT(RT_DEBUG_TRACE,"!!!!!!!!!!!!!!!!!\n");
					   RTUSBMultiWrite(pAd, (USHORT)(SEC_CSR0 + 0 * 0x10), pAd->PortCfg.SharedKey[0].Key, 16);	
						DBGPRINT(RT_DEBUG_TRACE,"!!!!!!!!!!!!!!!!!\n");
				   }
					//Key2Str
					if (RTMPGetKeyParameter("Default", "Key2Str", tmpbuf, 26, buffer))
					{
						KeyLen = strlen(tmpbuf);
						switch (KeyLen)
						{
							case 0:
								pAd->PortCfg.SharedKey[1].KeyLen = 0;
								break;
							case 5: //wep 40 Ascii type
								pAd->PortCfg.SharedKey[1].KeyLen = KeyLen;
								memcpy(pAd->PortCfg.SharedKey[1].Key, tmpbuf, KeyLen);
								DBGPRINT(RT_DEBUG_TRACE, "%s::(Key2=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Ascii");
							case 10: //wep 40 Hex type
								for(i=0; i < KeyLen; i++)
								{
									if( !isxdigit(*(tmpbuf+i)) )
									{
										bIsHex = FALSE;
										break;
									}
								}
								
								if (bIsHex)
								{
									pAd->PortCfg.SharedKey[1].KeyLen = KeyLen / 2 ;
									AtoH(tmpbuf, pAd->PortCfg.SharedKey[1].Key, KeyLen / 2);
									DBGPRINT(RT_DEBUG_TRACE, "%s::(Key2=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Hex");
								}
								break;
							case 13: //wep 104 Ascii type
								pAd->PortCfg.SharedKey[1].KeyLen = KeyLen;
								memcpy(pAd->PortCfg.SharedKey[1].Key, tmpbuf, KeyLen);	
								DBGPRINT(RT_DEBUG_TRACE, "%s::(Key2=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Ascii");
								break;
							case 26: //wep 104 Hex type
								for(i=0; i < KeyLen; i++)
								{
									if( !isxdigit(*(tmpbuf+i)) )
									{
										bIsHex = FALSE;
										break;
									}
								}

								if (bIsHex)
								{
									pAd->PortCfg.SharedKey[1].KeyLen = KeyLen / 2 ;
									AtoH(tmpbuf, pAd->PortCfg.SharedKey[1].Key, KeyLen / 2);
									DBGPRINT(RT_DEBUG_TRACE, "%s::(Key2=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Hex");
								}
								break;
							default:
								pAd->PortCfg.SharedKey[1].KeyLen = 0;
								DBGPRINT(RT_DEBUG_TRACE, "%s::Invalid argument (=%s)\n", __FUNCTION__, tmpbuf);
						}
						RTUSBMultiWrite(pAd, (USHORT)(SEC_CSR0 + 1 * 0x10), pAd->PortCfg.SharedKey[1].Key, 16);	
					}
					//Key3Str
					if (RTMPGetKeyParameter("Default", "Key3Str", tmpbuf, 26, buffer))
					{
						KeyLen = strlen(tmpbuf);
						switch (KeyLen)
						{
							case 0:
								pAd->PortCfg.SharedKey[2].KeyLen = 0;
								break;
							case 5: //wep 40 Ascii type
								pAd->PortCfg.SharedKey[2].KeyLen = KeyLen;
								memcpy(pAd->PortCfg.SharedKey[2].Key, tmpbuf, KeyLen);
								DBGPRINT(RT_DEBUG_TRACE, "%s::(Key3=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Ascii");
							case 10: //wep 40 Hex type
								for(i=0; i < KeyLen; i++)
								{
									if( !isxdigit(*(tmpbuf+i)) )
									{
										bIsHex = FALSE;
										break;
									}
								}

								if (bIsHex)
								{
									pAd->PortCfg.SharedKey[2].KeyLen = KeyLen / 2 ;
									AtoH(tmpbuf, pAd->PortCfg.SharedKey[2].Key, KeyLen / 2);
									DBGPRINT(RT_DEBUG_INFO, "%s::(Key3=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Hex");
								}
								break;
							case 13: //wep 104 Ascii type
								pAd->PortCfg.SharedKey[2].KeyLen = KeyLen;
								memcpy(pAd->PortCfg.SharedKey[2].Key, tmpbuf, KeyLen);	
								DBGPRINT(RT_DEBUG_TRACE, "%s::(Key3=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Ascii");
								break;
							case 26: //wep 104 Hex type
								for(i=0; i < KeyLen; i++)
								{
									if( !isxdigit(*(tmpbuf+i)) )
									{
										bIsHex = FALSE;
										break;
									}
								}

								if (bIsHex)
								{
									pAd->PortCfg.SharedKey[2].KeyLen = KeyLen / 2 ;
									AtoH(tmpbuf, pAd->PortCfg.SharedKey[2].Key, KeyLen / 2);
									DBGPRINT(RT_DEBUG_TRACE, "%s::(Key3=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Hex");
								}
								break;
							default:
								pAd->PortCfg.SharedKey[2].KeyLen = 0;
								DBGPRINT(RT_DEBUG_INFO, "%s::Invalid argument (=%s)\n", __FUNCTION__, tmpbuf);
						}
						RTUSBMultiWrite(pAd, (USHORT)(SEC_CSR0 + 2 * 0x10), pAd->PortCfg.SharedKey[2].Key, 16);	
					}
					//Key4Str
					if (RTMPGetKeyParameter("Default", "Key4Str", tmpbuf, 26, buffer))
					{
						KeyLen = strlen(tmpbuf);
						switch (KeyLen)
						{
							case 0:
								pAd->PortCfg.SharedKey[3].KeyLen = 0;
								break;
							case 5: //wep 40 Ascii type
								pAd->PortCfg.SharedKey[3].KeyLen = KeyLen;
								memcpy(pAd->PortCfg.SharedKey[3].Key, tmpbuf, KeyLen);
								DBGPRINT(RT_DEBUG_TRACE, "%s::(Key4=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Ascii");
							case 10: //wep 40 Hex type
								for(i=0; i < KeyLen; i++)
								{
									if( !isxdigit(*(tmpbuf+i)) )
									{
										bIsHex = FALSE;
										break;
									}
								}

								if (bIsHex)
								{
									pAd->PortCfg.SharedKey[3].KeyLen = KeyLen / 2 ;
									AtoH(tmpbuf, pAd->PortCfg.SharedKey[3].Key, KeyLen / 2);
									DBGPRINT(RT_DEBUG_TRACE, "%s::(Key4=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Hex");
								}
								break;
							case 13: //wep 104 Ascii type
								pAd->PortCfg.SharedKey[3].KeyLen = KeyLen;
								memcpy(pAd->PortCfg.SharedKey[3].Key, tmpbuf, KeyLen);	
								DBGPRINT(RT_DEBUG_TRACE, "%s::(Key4=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Ascii");
								break;
							case 26: //wep 104 Hex type
								for(i=0; i < KeyLen; i++)
								{
									if( !isxdigit(*(tmpbuf+i)) )
									{
										bIsHex = FALSE;
										break;
									}
								}

								if (bIsHex)
								{
									pAd->PortCfg.SharedKey[3].KeyLen = KeyLen / 2 ;
									AtoH(tmpbuf, pAd->PortCfg.SharedKey[3].Key, KeyLen / 2);
									DBGPRINT(RT_DEBUG_TRACE, "%s::(Key4=%s and type=%s)\n", __FUNCTION__, tmpbuf, "Hex");
								}
								break;
							default:
								pAd->PortCfg.SharedKey[3].KeyLen = 0;
								DBGPRINT(RT_DEBUG_TRACE, "%s::Invalid argument (=%s)\n", __FUNCTION__, tmpbuf);
						}
						RTUSBMultiWrite(pAd, (USHORT)(SEC_CSR0 + 3 * 0x10), pAd->PortCfg.SharedKey[3].Key, 16);	
					}
					//EncrypType
					if (RTMPGetKeyParameter("Default", "EncrypType", tmpbuf, 10, buffer))
					{
						Set_EncrypType_Proc(pAd,(PUCHAR)tmpbuf);
						DBGPRINT(RT_DEBUG_TEMP, "%s::(EncrypType=%d)\n", __FUNCTION__, pAd->PortCfg.WepStatus);

					}
				}
			}
			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;
#endif	
}


/*
	========================================================================
	
	Routine Description:
		Read additional information from EEPROM, such as MAC address

	Arguments:
		Adapter						Pointer to our adapter

	Return Value:
		NDIS_STATUS_SUCCESS
		NDIS_STATUS_FAILURE

	Note:
	
	========================================================================
*/
NDIS_STATUS	RTUSBWriteHWMACAddress(
	IN	PRT2570ADAPTER		pAdapter)
{
	MAC_CSR2_STRUC		StaMacReg0;
	MAC_CSR3_STRUC		StaMacReg1;
	MAC_CSR4_STRUC		StaMacReg2;
	NDIS_STATUS		Status = NDIS_STATUS_SUCCESS;

	StaMacReg0.field.Byte0 = pAdapter->CurrentAddress[0];
	StaMacReg0.field.Byte1 = pAdapter->CurrentAddress[1];
	StaMacReg1.field.Byte2 = pAdapter->CurrentAddress[2];
	StaMacReg1.field.Byte3 = pAdapter->CurrentAddress[3];
	StaMacReg2.field.Byte4 = pAdapter->CurrentAddress[4];
	StaMacReg2.field.Byte5 = pAdapter->CurrentAddress[5];

	RTUSBWriteMACRegister(pAdapter, MAC_CSR2, StaMacReg0.value);
	RTUSBWriteMACRegister(pAdapter, MAC_CSR3, StaMacReg1.value);
	RTUSBWriteMACRegister(pAdapter, MAC_CSR4, StaMacReg2.value);
	return Status;
}

/*
	========================================================================
	
	Routine Description:
		Read initial parameters from EEPROM
		
	Arguments:
		Adapter						Pointer to our adapter

	Return Value:
		None

	Note:
		
	========================================================================
*/
VOID	NICReadEEPROMParameters(
	IN	PRT2570ADAPTER	pAdapter)
{
	USHORT			i;
	int			value;
	UCHAR			TmpPhy;
	EEPROM_TX_PWR_STRUC	Power;
	EEPROM_ANTENNA_STRUC	Antenna;//blue
//	EEPROM_VERSION_STRUC	Version;
	
	DBGPRINT(RT_DEBUG_TRACE,"--> NICReadEEPROMParameters\n");

	//Read MAC address.
	RTUSBReadEEPROM(pAdapter, EEPROM_MAC_ADDRESS_BASE_OFFSET, pAdapter->PermanentAddress, ETH_LENGTH_OF_ADDRESS);
	DBGPRINT_RAW(RT_DEBUG_TRACE,"MAC address:\n");
	for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++)
		DBGPRINT_RAW(RT_DEBUG_TRACE,"%02x ", pAdapter->PermanentAddress[i]);
	DBGPRINT_RAW(RT_DEBUG_TRACE,"\n");

	if (pAdapter->PortCfg.bLocalAdminMAC != TRUE)
	{
		pAdapter->CurrentAddress[0] = pAdapter->PermanentAddress[0];
		pAdapter->CurrentAddress[1] = pAdapter->PermanentAddress[1];
		pAdapter->CurrentAddress[2] = pAdapter->PermanentAddress[2];
		pAdapter->CurrentAddress[3] = pAdapter->PermanentAddress[3];
		pAdapter->CurrentAddress[4] = pAdapter->PermanentAddress[4];
		pAdapter->CurrentAddress[5] = pAdapter->PermanentAddress[5];
	}

	// Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAdapter
	RTUSBReadEEPROM(pAdapter, EEPROM_BBP_BASE_OFFSET, (PUCHAR)(pAdapter->EEPROMDefaultValue), 2 * NUM_EEPROM_BBP_PARMS);

	// 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 = pAdapter->EEPROMDefaultValue[0];
	if (Antenna.field.DynamicTxAgcControl == 1)
		pAdapter->PortCfg.bAutoTxAgc = TRUE;
	else
		pAdapter->PortCfg.bAutoTxAgc = FALSE;		
	

	// Read Tx power value for all 14 channels
	// Value from 1 - 0x7f. Default value is 24.
	RTUSBReadEEPROM(pAdapter, EEPROM_TX_PWR_OFFSET, pAdapter->PortCfg.ChannelTxPower, 2 * NUM_EEPROM_TX_PARMS);
	for (i = 0; i < 2 * NUM_EEPROM_TX_PARMS; i++)
	{
		if (pAdapter->PortCfg.ChannelTxPower[i] > 31)
			pAdapter->PortCfg.ChannelTxPower[i] = 24;
		DBGPRINT(RT_DEBUG_INFO, "Tx power for channel %d : %0x\n", i, pAdapter->PortCfg.ChannelTxPower[i]);
	}

	// Read Tx TSSI reference value, OK to reuse Power data structure
	RTUSBReadEEPROM(pAdapter, EEPROM_TSSI_REF_OFFSET, pAdapter->PortCfg.ChannelTssiRef, 2 * NUM_EEPROM_TX_PARMS);
	for (i = 0; i < 2 * NUM_EEPROM_TX_PARMS; i++)
	{
		if (pAdapter->PortCfg.ChannelTssiRef[i] == 0xff)
			pAdapter->PortCfg.bAutoTxAgc = FALSE;					
		DBGPRINT(RT_DEBUG_INFO, "TSSI reference for channel %d : %0x\n", i, pAdapter->PortCfg.ChannelTssiRef[i]);
	}
	
	// Tx Tssi delta offset 0x24
	RTUSBReadEEPROM(pAdapter, EEPROM_TSSI_DELTA_OFFSET, (PUCHAR)(&(Power.word)), 2);
	pAdapter->PortCfg.ChannelTssiDelta = Power.field.Byte0;
	
	//CountryRegion byte offset = 0x35
	value = pAdapter->EEPROMDefaultValue[2] >> 8;
	DBGPRINT(RT_DEBUG_TRACE,"  CountryRegion= 0x%x \n",value);
	if ((value >= 0) && (value <= 7))
	{
		pAdapter->PortCfg.CountryRegion = (UCHAR) value;
		TmpPhy = pAdapter->PortCfg.PhyMode;
		pAdapter->PortCfg.PhyMode = 0xff;
		RTMPSetPhyMode(pAdapter, TmpPhy);
	}
	else
	{
		// set default country region 
		pAdapter->PortCfg.CountryRegion = 6;
		TmpPhy = pAdapter->PortCfg.PhyMode;
		pAdapter->PortCfg.PhyMode = 0xff;
		RTMPSetPhyMode(pAdapter, TmpPhy);
	}

	RTUSBReadEEPROM(pAdapter, EEPROM_BBP_TUNING_OFFSET, (PUCHAR)(pAdapter->EEPROMBBPTuningParameters), 2 * NUM_EEPROM_BBP_TUNING_PARMS);
	if ((pAdapter->EEPROMBBPTuningParameters[0] != 0xffff) && (pAdapter->EEPROMBBPTuningParameters[0] != 0))
	{
		pAdapter->BBPTuningParameters.BBPTuningThreshold = (UCHAR)((pAdapter->EEPROMBBPTuningParameters[0]) & 0xff);
		DBGPRINT(RT_DEBUG_INFO, "BBPTuningThreshold = %d\n", pAdapter->BBPTuningParameters.BBPTuningThreshold);
	}
	if ((pAdapter->EEPROMBBPTuningParameters[1] != 0xffff) && (pAdapter->EEPROMBBPTuningParameters[1] != 0))
	{
		pAdapter->BBPTuningParameters.R24LowerValue = (UCHAR)(pAdapter->EEPROMBBPTuningParameters[1] & 0xff);
		pAdapter->BBPTuningParameters.R24HigherValue = (UCHAR)((pAdapter->EEPROMBBPTuningParameters[1] & 0xff00) >> 8);
		DBGPRINT(RT_DEBUG_INFO, "R24LowerValue = 0x%x\n", pAdapter->BBPTuningParameters.R24LowerValue);
		DBGPRINT(RT_DEBUG_INFO, "R24HigherValue = 0x%x\n", pAdapter->BBPTuningParameters.R24HigherValue);
	}
	if ((pAdapter->EEPROMBBPTuningParameters[2] != 0xffff) && (pAdapter->EEPROMBBPTuningParameters[2] != 0))
	{
		pAdapter->BBPTuningParameters.R25LowerValue = (UCHAR)(pAdapter->EEPROMBBPTuningParameters[2] & 0xff);
		pAdapter->BBPTuningParameters.R25HigherValue = (UCHAR)((pAdapter->EEPROMBBPTuningParameters[2] & 0xff00) >> 8);
		DBGPRINT(RT_DEBUG_INFO, "R25LowerValue = 0x%x\n", pAdapter->BBPTuningParameters.R25LowerValue);
		DBGPRINT(RT_DEBUG_INFO, "R25HigherValue = 0x%x\n", pAdapter->BBPTuningParameters.R25HigherValue);
	}
	if ((pAdapter->EEPROMBBPTuningParameters[3] != 0xffff) && (pAdapter->EEPROMBBPTuningParameters[3] != 0))
	{
		pAdapter->BBPTuningParameters.R61LowerValue = (UCHAR)(pAdapter->EEPROMBBPTuningParameters[3] & 0xff);
		pAdapter->BBPTuningParameters.R61HigherValue = (UCHAR)((pAdapter->EEPROMBBPTuningParameters[3] & 0xff00) >> 8);
		DBGPRINT(RT_DEBUG_INFO, "R61LowerValue = 0x%x\n", pAdapter->BBPTuningParameters.R61LowerValue);
		DBGPRINT(RT_DEBUG_INFO, "R61HigherValue = 0x%x\n", pAdapter->BBPTuningParameters.R61HigherValue);
	}
	if ((pAdapter->EEPROMBBPTuningParameters[4] != 0xffff) && (pAdapter->EEPROMBBPTuningParameters[4] != 0))
	{
		pAdapter->PortCfg.BbpTuning.VgcUpperBound = (UCHAR)(pAdapter->EEPROMBBPTuningParameters[4] & 0xff);
		DBGPRINT_RAW(RT_DEBUG_INFO, "VgcUpperBound = 0x%x\n", pAdapter->PortCfg.BbpTuning.VgcUpperBound);
	}
	if ((pAdapter->EEPROMBBPTuningParameters[5] != 0xffff) && (pAdapter->EEPROMBBPTuningParameters[5] != 0))
	{
		pAdapter->BBPTuningParameters.BBPR17LowSensitivity = (UCHAR)(pAdapter->EEPROMBBPTuningParameters[5] & 0xff);
		pAdapter->BBPTuningParameters.BBPR17MidSensitivity = (UCHAR)((pAdapter->EEPROMBBPTuningParameters[5] & 0xff00) >> 8);
		DBGPRINT_RAW(RT_DEBUG_INFO, "BBPR17LowSensitivity = 0x%x\n", pAdapter->BBPTuningParameters.BBPR17LowSensitivity);
		DBGPRINT_RAW(RT_DEBUG_INFO, "BBPR17MidSensitivity = 0x%x\n", pAdapter->BBPTuningParameters.BBPR17MidSensitivity);
	}
	if ((pAdapter->EEPROMBBPTuningParameters[6] != 0xffff) && (pAdapter->EEPROMBBPTuningParameters[6] != 0))
	{
		pAdapter->BBPTuningParameters.RSSIToDbmOffset = (UCHAR)(pAdapter->EEPROMBBPTuningParameters[6] & 0xff);
		DBGPRINT_RAW(RT_DEBUG_INFO, "RSSIToDbmOffset = 0x%x\n", pAdapter->BBPTuningParameters.RSSIToDbmOffset);
	}

	DBGPRINT(RT_DEBUG_TRACE,"<-- NICReadEEPROMParameters\n");
}

/*
	========================================================================
	
	Routine Description:
		Set default value from EEPROM
		
	Arguments:
		Adapter						Pointer to our adapter

	Return Value:
		None

	Note:
		
	========================================================================
*/
VOID	NICInitAsicFromEEPROM(
	IN	PRT2570ADAPTER	pAdapter)
{
	USHORT					i, value;
	USHORT	Value5, Value6;
	UCHAR					TxValue,RxValue;
	EEPROM_ANTENNA_STRUC	Antenna;
	EEPROM_NIC_CONFIG2_STRUC	NicConfig2;

	DBGPRINT(RT_DEBUG_TRACE,"--> NICInitAsicFromEEPROM\n");

	//Initialize BBP registers.
	for(i = 3; i < NUM_EEPROM_BBP_PARMS; i++)
	{
		value = pAdapter->EEPROMDefaultValue[i];
		
		if((value != 0xFFFF) && (value != 0))
		{
			//blue,RTUSBWriteMACRegister(pAdapter, PHY_CSR7, value);
			USHORT	id;
			id = ((value & 0xff00) >> 8);
			{
				USHORT	temp;
				UINT	j = 0;
				do
				{
					RTUSBReadMACRegister(pAdapter, PHY_CSR8, &temp);
					if (!(temp & BUSY))
						break;
					j++;
				}
				while (j < RETRY_LIMIT);
				
				RTUSBWriteMACRegister(pAdapter, PHY_CSR7, value);
			}
				
		}
	}

	DBGPRINT(RT_DEBUG_INFO,"pAdapter->BBPTuningParameters.R24LowerValue = %x\n", pAdapter->BBPTuningParameters.R24LowerValue);
	DBGPRINT(RT_DEBUG_INFO, "pAdapter->BBPTuningParameters.R25LowerValue = %x\n", pAdapter->BBPTuningParameters.R25LowerValue);
	DBGPRINT(RT_DEBUG_INFO, "pAdapter->BBPTuningParameters.R61LowerValue = %x\n", pAdapter->BBPTuningParameters.R61LowerValue);
	RTUSBWriteBBPRegister(pAdapter, 24, pAdapter->BBPTuningParameters.R24LowerValue);
	RTUSBWriteBBPRegister(pAdapter, 25, pAdapter->BBPTuningParameters.R25LowerValue);
	RTUSBWriteBBPRegister(pAdapter, 61, pAdapter->BBPTuningParameters.R61LowerValue);


	//Select antennas.
	Antenna.word = pAdapter->EEPROMDefaultValue[0];

	if ((Antenna.word == 0xFFFF) || (Antenna.field.TxDefaultAntenna > 2) || (Antenna.field.RxDefaultAntenna > 2))
	{
		DBGPRINT(RT_DEBUG_ERROR,"E2PROM error(=0x%04x), hard code as 0x0002\n", Antenna.word);
		Antenna.word = 0x0002;
	}

	DBGPRINT(RT_DEBUG_TRACE,"Antenna.word = 0x%x \n", Antenna.word);
	pAdapter->PortCfg.NumberOfAntenna = 2;	// (UCHAR)Antenna.field.NumOfAntenna;
	pAdapter->PortCfg.CurrentTxAntenna = (UCHAR)Antenna.field.TxDefaultAntenna;
	pAdapter->PortCfg.CurrentRxAntenna = (UCHAR)Antenna.field.RxDefaultAntenna;
	   pAdapter->PortCfg.RfType = (UCHAR) Antenna.field.RfType;//blue
	DBGPRINT(RT_DEBUG_TRACE,"pAdapter->PortCfg.RfType = 0x%x \n", pAdapter->PortCfg.RfType);
	RTUSBReadBBPRegister(pAdapter, BBP_Tx_Configure, &TxValue);
	RTUSBReadBBPRegister(pAdapter, BBP_Rx_Configure, &RxValue);
	RTUSBReadMACRegister(pAdapter, PHY_CSR5, &Value5);
	RTUSBReadMACRegister(pAdapter, PHY_CSR6, &Value6);

	// Tx antenna select
	if(Antenna.field.TxDefaultAntenna == 1)   
	{
		TxValue = (TxValue & 0xFC) | 0x00; // Antenna A
		Value5 = (Value5 & 0xFFFC) | 0x0000;
		Value6 = (Value6 & 0xFFFC) | 0x0000;
	}
	else if(Antenna.field.TxDefaultAntenna == 2)  
	{
		TxValue = (TxValue & 0xFC) | 0x02; // Antenna B
		Value5 = (Value5 & 0xFFFC) | 0x0002;
		Value6 = (Value6 & 0xFFFC) | 0x0002;
	}
	else
	{
		TxValue = (TxValue & 0xFC) | 0x01; // Antenna Diversity
		Value5 = (Value5 & 0xFFFC) | 0x0001;
		Value6 = (Value6 & 0xFFFC) | 0x0001;
	}


	// Rx antenna select
	if(Antenna.field.RxDefaultAntenna == 1)
		RxValue = (RxValue & 0xFC) | 0x00; // Antenna A
	else if(Antenna.field.RxDefaultAntenna == 2)
		RxValue = (RxValue & 0xFC) | 0x02; // Antenna B
	else
		RxValue = (RxValue & 0xFC) | 0x01; // Antenna Diversity


	DBGPRINT(RT_DEBUG_TRACE, "<-- NICInitAsicFromEEPROM pAdapter->PortCfg.RfType = %d\n", pAdapter->PortCfg.RfType);
	// RT5222 needs special treatment to swap TX I/Q
	if (pAdapter->PortCfg.RfType == RFIC_5222)
	{
		Value5 |= 0x0004;
		Value6 |= 0x0004;
		TxValue |= 0x04;		 // TX I/Q flip
	}
	// RT2525E need to flip TX I/Q but not RX I/Q
	else if (pAdapter->PortCfg.RfType == RFIC_2525E)	
	{
		Value5 |= 0x0004;
		Value6 |= 0x0004;
		TxValue |= 0x04;		 // TX I/Q flip
		RxValue &= 0xfb;		 // RX I/Q no flip
	}
	
	RTUSBWriteMACRegister(pAdapter, PHY_CSR5, Value5);
	RTUSBWriteMACRegister(pAdapter, PHY_CSR6, Value6);
			
	// Change to match microsoft definition, 0xff: diversity, 0: A, 1: B
	pAdapter->PortCfg.CurrentTxAntenna--;
	pAdapter->PortCfg.CurrentRxAntenna--;

	RTUSBWriteBBPRegister(pAdapter, BBP_Tx_Configure, TxValue);
	RTUSBWriteBBPRegister(pAdapter, BBP_Rx_Configure, RxValue);

	
	//Set LED mode.
	if (Antenna.field.LedMode == LED_MODE_TXRX_ACTIVITY)
		pAdapter->PortCfg.LedMode = LED_MODE_TXRX_ACTIVITY;
	else if (Antenna.field.LedMode == LED_MODE_SINGLE)
	{
		pAdapter->PortCfg.LedMode = LED_MODE_SINGLE;
		ASIC_LED_ACT_ON(pAdapter);
	}
	else if (Antenna.field.LedMode == LED_MODE_ASUS)
	{
		pAdapter->PortCfg.LedMode = LED_MODE_ASUS;
		RTUSBWriteMACRegister(pAdapter, MAC_CSR20, 0x0002);
	}
	else if (Antenna.field.LedMode == LED_MODE_ALPHA)
	{
		pAdapter->PortCfg.LedMode = LED_MODE_ALPHA;
		RTUSBWriteMACRegister(pAdapter, MAC_CSR20, 1);
		pAdapter->PortCfg.LedCntl.fOdd = FALSE;
	}	 
	else
		pAdapter->PortCfg.LedMode = LED_MODE_DEFAULT;


	// Read Hardware controlled Radio state enable bit
	if (Antenna.field.HardwareRadioControl == 1)
	{
		pAdapter->PortCfg.bHardwareRadio = TRUE;
		RTUSBWriteMACRegister(pAdapter, MAC_CSR19, 0);

		// Read GPIO pin0 as Hardware controlled radio state
		RTUSBReadMACRegister(pAdapter, MAC_CSR19, &value);
		if ((value & 0x80) == 0)
		{
			pAdapter->PortCfg.bHwRadio = FALSE;
			pAdapter->PortCfg.bRadio = FALSE;
			RTUSBWriteMACRegister(pAdapter, MAC_CSR13, 0);
			RTUSBWriteMACRegister(pAdapter, MAC_CSR14, 0);
			RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF);
        	DBGPRINT(RT_DEBUG_ERROR, "2Set fRTMP_ADAPTER_RADIO_OFF ");
			if (pAdapter->PortCfg.LedMode == LED_MODE_ASUS)
			{
				// Turn bit 17 for Radio OFF
				RTUSBWriteMACRegister(pAdapter, MAC_CSR20, 1);
			}
		}
	}
	else
		pAdapter->PortCfg.bHardwareRadio = FALSE;		
	
	NicConfig2.word = pAdapter->EEPROMDefaultValue[1];
	if (NicConfig2.word == 0xffff)
		NicConfig2.word = 0;	// empty E2PROM, use default
	
	// for dynamic BBP R17:RX sensibility tuning
	{
		UCHAR r17;
		RTUSBReadBBPRegister(pAdapter, 17, &r17);
		pAdapter->PortCfg.BbpTuningEnable = (NicConfig2.field.DynamicBbpTuning==0)? 1:0;
		pAdapter->PortCfg.VgcLowerBound   = r17;

		// 2004-3-4 per David's request, R7 starts at upper bound
		r17 = pAdapter->PortCfg.BbpTuning.VgcUpperBound;
		pAdapter->PortCfg.LastR17Value = r17;
		RTUSBWriteBBPRegister(pAdapter, 17, r17);

		// 2004-2-2 per David's request, lower R17 low-bound for very good quality NIC
		pAdapter->PortCfg.VgcLowerBound -= 6;  
		DBGPRINT(RT_DEBUG_TRACE,"R17 tuning enable=%d, R17=0x%02x, range=<0x%02x, 0x%02x>\n",
			pAdapter->PortCfg.BbpTuningEnable, r17, pAdapter->PortCfg.VgcLowerBound, pAdapter->PortCfg.BbpTuning.VgcUpperBound);
	}

	    AsicSwitchChannel(pAdapter, pAdapter->PortCfg.Channel);
	DBGPRINT(RT_DEBUG_TRACE,"RF IC=%d, LED mode=%d\n", pAdapter->PortCfg.RfType, pAdapter->PortCfg.LedMode);

	DBGPRINT(RT_DEBUG_TRACE,"<-- NICInitAsicFromEEPROM\n");
}

VOID	RT2570InitializeAsic(
	IN	PRT2570ADAPTER	pAdapter)
{
	ULONG			Index;
	UCHAR			buffer[22];
	USHORT			temp;
	UCHAR			Value = 0xff;
	UINT			i;

	DBGPRINT(RT_DEBUG_TRACE, "--> NICInitializeAsic\n");

	do
	{
		//NdisMSleep(1000);
		RTUSB_VendorRequest(pAdapter,
			0,
			DEVICE_VENDOR_REQUEST_OUT,
			0x1,
			0x4,
			0x1,
			NULL,
			0);

		RTUSBSingleWrite(pAdapter, 0x308, 0xf0);//asked by MAX

		// Disable RX at first beginning. Before BulkInReceive, we will enable RX.
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR2, 1);
		RTUSBWriteMACRegister(pAdapter, MAC_CSR13, 0x1111);//requested by Jerry
		RTUSBWriteMACRegister(pAdapter, MAC_CSR14, 0x1E11);
		RTUSBWriteMACRegister(pAdapter, MAC_CSR1, 3); // reset MAC state machine, requested by Kevin 2003-2-11
		RTUSBWriteMACRegister(pAdapter, MAC_CSR1, 0); // reset MAC state machine, requested by Kevin 2003-2-11
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR5, 0x8C8D);
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR6, 0x8B8A);
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR7, 0x8687);
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR8, 0x0085);
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR21, 0xe78f);
		RTUSBWriteMACRegister(pAdapter, MAC_CSR9, 0xFF1D);

		i = 0;
		RTUSBReadMACRegister(pAdapter, MAC_CSR17, &temp);
		while (((temp & 0x01e0 ) != 0x01e0) && (i < 50))
		{
			NdisMSleep(1000);
			RTUSBReadMACRegister(pAdapter, MAC_CSR17, &temp);

			i++;
		}
		if (i == 50)
		{
			if (RTUSB_ResetDevice(pAdapter) == FALSE)
			{
			//RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
				DBGPRINT(RT_DEBUG_TRACE, "<== NICInitializeAsic ERROR\n");
			return;
			}
			else
				continue;
		}
	
		RTUSBWriteMACRegister(pAdapter, MAC_CSR1, 4);
		RTUSBReadMACRegister(pAdapter, MAC_CSR0, &temp);
		if ( temp >= 3){
		   RTUSBReadMACRegister(pAdapter, PHY_CSR2, &temp);
		   RTUSBWriteMACRegister(pAdapter, PHY_CSR2, temp & 0xFFFD);		   
		}
		else
		{
			DBGPRINT(RT_DEBUG_TRACE, "LNA 3 mode\n");
			RTUSBWriteMACRegister(pAdapter, PHY_CSR2, 0x3002); // LNA 3 mode

		}
		RTUSBWriteMACRegister(pAdapter, MAC_CSR11, 2);
		RTUSBWriteMACRegister(pAdapter, MAC_CSR22, 0x53);
		RTUSBWriteMACRegister(pAdapter, MAC_CSR15, 0x01ee);
		RTUSBWriteMACRegister(pAdapter, MAC_CSR16, 0);
		RTUSBWriteMACRegister(pAdapter, MAC_CSR8, 0x0780);//steven:limit the maximum frame length
		
		RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &temp);
		temp &= 0xe007;
		temp |= ((LENGTH_802_11 << 3) | (0x000f << 9));
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, temp);
		
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR19, 0);
		RTUSBWriteMACRegister(pAdapter, MAC_CSR18, 0x5a);

		//set RF_LE to low when standby
		RTUSBReadMACRegister(pAdapter, PHY_CSR4, &temp);
		RTUSBWriteMACRegister(pAdapter, PHY_CSR4, temp | 1);
		//NdisMSleep(1);//wait for PLL to become stable

		i = 0;
		do
		{
			RTUSBReadBBPRegister(pAdapter, BBP_Version, &Value);
			DBGPRINT(RT_DEBUG_TRACE, "Read BBP_Version Value = %d\n", Value);
			i++;
		}while (((Value == 0xff) || (Value == 0x00)) && (i < 50));
		if (i < 50)//BBP ready
		{
			break;
		}
		else
		{
			if ( RTUSB_ResetDevice(pAdapter) == FALSE)
			{
				RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
				return;
			}
		}
	}while (1);

	// Initialize BBP register to default value
	for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++)
	{
		i = 0;
		do
		{
			RTUSBReadMACRegister(pAdapter, PHY_CSR8, &temp);
			if (!(temp & BUSY))
				break;
			i++;
		}
		while (i < RETRY_LIMIT);
		
		RTUSBWriteMACRegister(pAdapter, PHY_CSR7, BBPRegTable[Index]);
	}


	// Initialize RF register to default value
	AsicSwitchChannel(pAdapter, pAdapter->PortCfg.Channel);
	AsicLockChannel(pAdapter, pAdapter->PortCfg.Channel);

	// Add radio off control
	if (pAdapter->PortCfg.bRadio == FALSE)
	{
		RTUSBWriteMACRegister(pAdapter, MAC_CSR13, 0);
		RTUSBWriteMACRegister(pAdapter, MAC_CSR14, 0);

		RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF);
        	DBGPRINT(RT_DEBUG_ERROR, "1Set fRTMP_ADAPTER_RADIO_OFF ");
	}


	RTUSBMultiRead(pAdapter, STA_CSR0, buffer, 22);
	
	DBGPRINT(RT_DEBUG_TRACE, "<-- NICInitializeAsic\n");
}
/*
	========================================================================
	
	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	PRT2570ADAPTER	pAdapter)
{

	RT2570InitializeAsic(pAdapter);
#ifdef	INIT_FROM_EEPROM
	NICInitAsicFromEEPROM(pAdapter);
#endif
	RTUSBWriteHWMACAddress(pAdapter);
	
	// Switch to current channel, since during reset process, the connection should remains on.	
	AsicSwitchChannel(pAdapter, pAdapter->PortCfg.Channel);
	AsicLockChannel(pAdapter, pAdapter->PortCfg.Channel);
}

VOID CreateThreads( struct net_device *net_dev )
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) net_dev->priv;

	// Creat MLME Thread
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
	// Creat MLME Thread
	pAdapter->MLMEThr_pid= -1;

	pAdapter->MLMEThr_pid = kernel_thread(MlmeThread, pAdapter, CLONE_VM);
	if (pAdapter->MLMEThr_pid < 0)
		printk(KERN_WARNING "%s: unable to start mlme thread\n",pAdapter->net->name);

	// Creat Command Thread
	pAdapter->RTUSBCmdThr_pid= -1;
	pAdapter->RTUSBCmdThr_pid = kernel_thread(RTUSBCmdThread, pAdapter, CLONE_VM);
	if (pAdapter->RTUSBCmdThr_pid < 0)
		printk(KERN_WARNING "%s: unable to start RTUSBCmd thread\n",pAdapter->net->name);
#else
	// Creat MLME Thread
	pAdapter->MLMEThr = kthread_run(MlmeThread, pAdapter, "rtusb-mlme");
	if (IS_ERR(pAdapter->MLMEThr))
		printk(KERN_WARNING "%s: unable to start mlme thread\n",pAdapter->net->name);
	// Creat Command Thread
	pAdapter->RTUSBCmdThr = kthread_run(RTUSBCmdThread, pAdapter, "rtusb-usbcmd");
	if (IS_ERR(pAdapter->RTUSBCmdThr))
		printk(KERN_WARNING "%s: unable to start RTUSBCmd thread\n",pAdapter->net->name);
#endif
}


NDIS_STATUS RTMPAllocAdapterBlock( PRT2570ADAPTER	*ppAdapter	)
{
	NDIS_STATUS 	Status=NDIS_STATUS_SUCCESS;

#if 0
	PRT2570ADAPTER	pAdapter;
	DBGPRINT(RT_DEBUG_TRACE,"--> RTMPAllocAdapterBlock\n");

	*ppAdapter = NULL;

	do
	{
		pAdapter = (PRT2570ADAPTER) kmalloc(sizeof(RT2570ADAPTER), GFP_KERNEL);
		
		if (!pAdapter) {
			DBGPRINT(RT_DEBUG_ERROR,"Not enough memory\n");
			Status = NDIS_STATUS_RESOURCES;
			break;
		}

		
		memset((PUCHAR) pAdapter, 0, sizeof(RT2570ADAPTER));
		
	} while (FALSE);

	*ppAdapter = pAdapter;

	DBGPRINT(RT_DEBUG_ERROR,"<-- RTMPAllocAdapterBlock, Status=%x\n", Status);
#endif
	return Status;
}


NDIS_STATUS NICInitTransmit(  PRT2570ADAPTER	 pAdapter )
{
	UCHAR	i;
	NDIS_STATUS 	Status = NDIS_STATUS_SUCCESS;
	PTX_CONTEXT	pPsPollContext = &(pAdapter->PsPollContext);
	PTX_CONTEXT	pNullContext = &(pAdapter->NullContext);

	DBGPRINT(RT_DEBUG_TRACE,"--> NICInitTransmit\n");

	// Initialize all Transmit releated queues
	skb_queue_head_init(&pAdapter->SendTxWaitQueue);
	
	// Init Ring index pointer
	pAdapter->NextRxBulkInIndex			= 0;
	pAdapter->NextTxIndex			= 0;
	pAdapter->NextBulkOutIndex		= 0;	// Next Local tx ring pointer waiting for buck out
	pAdapter->NextMLMEIndex 		= 0;
	pAdapter->PushMgmtIndex 	   = 0;
	pAdapter->PopMgmtIndex		   = 0;
	atomic_set(&pAdapter->MgmtQueueSize,0);
	pAdapter->BulkOutPending	= FALSE;	
	pAdapter->PrioRingFirstIndex	= 0;
	pAdapter->PrioRingTxCnt 		= 0;

	do
	{
		for ( i= 0; i < TX_RING_SIZE; i++ )
		{
			PTX_CONTEXT pTxContext = &(pAdapter->TxContext[i]);
			
			//Allocate URB
			pTxContext->pUrb = RT2570_USB_ALLOC_URB(0);
			if(pTxContext->pUrb == NULL){
				Status = NDIS_STATUS_RESOURCES;
				goto done;
			}
			pTxContext->TransferBuffer= (PTX_BUFFER) kmalloc(sizeof(TX_BUFFER), GFP_KERNEL);
			Status = NDIS_STATUS_SUCCESS;
			if(!pTxContext->TransferBuffer){
				DBGPRINT(RT_DEBUG_ERROR,"Not enough memory\n");
				Status = NDIS_STATUS_RESOURCES;
				goto out1;
			}

			memset(pTxContext->TransferBuffer, 0, sizeof(TX_BUFFER));

			pTxContext->pAdapter = pAdapter;
			pTxContext->InUse = FALSE;
			pTxContext->IRPPending = FALSE;
		}
		
		for ( i= 0; i < PRIO_RING_SIZE; i++ )
		{
			PTX_CONTEXT	pMLMEContext = &(pAdapter->MLMEContext[i]);
			
			pMLMEContext->pUrb = RT2570_USB_ALLOC_URB(0);
			if(pMLMEContext->pUrb == NULL){
				Status = NDIS_STATUS_RESOURCES;
				goto out1;
			}
			
			pMLMEContext->TransferBuffer= (PTX_BUFFER) kmalloc(sizeof(TX_BUFFER), GFP_KERNEL);
			if(!pMLMEContext->TransferBuffer){
				DBGPRINT(RT_DEBUG_ERROR,"Not enough memory\n");
				Status = NDIS_STATUS_RESOURCES;
				goto out2;
			}
			
			memset(pMLMEContext->TransferBuffer, 0, sizeof(TX_BUFFER));
			pMLMEContext->pAdapter = pAdapter;
			pMLMEContext->InUse = FALSE;
			pMLMEContext->IRPPending = FALSE;
		}

		for (i = 0; i < BEACON_RING_SIZE; i++)
		{
			PTX_CONTEXT	pBeaconContext = &(pAdapter->BeaconContext[i]);
			pBeaconContext->pUrb = RT2570_USB_ALLOC_URB(0);
			if(pBeaconContext->pUrb == NULL){
				Status = NDIS_STATUS_RESOURCES;
				goto out2;
			}
			
			pBeaconContext->TransferBuffer= (PTX_BUFFER) kmalloc(sizeof(TX_BUFFER), GFP_KERNEL);
			if(!pBeaconContext->TransferBuffer){
				DBGPRINT(RT_DEBUG_ERROR,"Not enough memory\n");
				Status = NDIS_STATUS_RESOURCES;
				goto out3;
			}
			memset(pBeaconContext->TransferBuffer, 0, sizeof(TX_BUFFER));

			pBeaconContext->pAdapter = pAdapter;
			pBeaconContext->InUse = FALSE;
			pBeaconContext->IRPPending = FALSE;
		}

		pNullContext->pUrb = RT2570_USB_ALLOC_URB(0);
		if(pNullContext->pUrb == NULL){
			Status = NDIS_STATUS_RESOURCES;
			goto out3;
		}		 
		
		pNullContext->TransferBuffer= (PTX_BUFFER) kmalloc(sizeof(TX_BUFFER), GFP_KERNEL);
		if(!pNullContext->TransferBuffer){
			DBGPRINT(RT_DEBUG_ERROR,"Not enough memory\n");
			Status = NDIS_STATUS_RESOURCES;
			goto out4;
		}

		memset(pNullContext->TransferBuffer, 0, sizeof(TX_BUFFER));
		pNullContext->pAdapter = pAdapter;
		pNullContext->InUse = FALSE;
		pNullContext->IRPPending = FALSE;

		pPsPollContext->pUrb = RT2570_USB_ALLOC_URB(0);
		if(pPsPollContext->pUrb == NULL){
			Status = NDIS_STATUS_RESOURCES;
			goto out4;
		}		 
		
		pPsPollContext->TransferBuffer= (PTX_BUFFER) kmalloc(sizeof(TX_BUFFER), GFP_KERNEL);
		if(!pPsPollContext->TransferBuffer){
			DBGPRINT(RT_DEBUG_ERROR,"Not enough memory\n");
			Status = NDIS_STATUS_RESOURCES;
			goto out5;
		}

		memset(pPsPollContext->TransferBuffer, 0, sizeof(TX_BUFFER));
		pPsPollContext->pAdapter = pAdapter;
		pPsPollContext->InUse = FALSE;
		pPsPollContext->IRPPending = FALSE;

#if 0					

		//Allocate URB
		pWpaPskContext->pUrb = RT2570_USB_ALLOC_URB(0);
		if(pWpaPskContext->pUrb == NULL){
			Status = NDIS_STATUS_RESOURCES;
			goto done;
		}
			
			
	
		pWpaPskContext->TransferBuffer= (PWPAPSK_BUFFER) kmalloc(sizeof(WPAPSK_BUFFER), GFP_KERNEL);
		Status = NDIS_STATUS_SUCCESS;
		if(!pWpaPskContext->TransferBuffer){
			DBGPRINT(RT_DEBUG_ERROR,"Not enough memory\n");
			Status = NDIS_STATUS_RESOURCES;
			goto done;
		}

		memset(pWpaPskContext->TransferBuffer, 0, sizeof(WPAPSK_BUFFER));

		pWpaPskContext->pAdapter = pAdapter;
		pWpaPskContext->InUse = FALSE;
		pWpaPskContext->IRPPending = FALSE;
#endif


#ifdef TEST_MODE_SUPPORT
		Status = RT2570AllocateMemory(&(pAdapter->pTxUrb), sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
		if ((Status != NDIS_STATUS_SUCCESS) || (pAdapter->pTxUrb == NULL))
		{
			Status = NDIS_STATUS_RESOURCES;
			goto done;
		}
		Status = RT2570AllocateMemory(&(pAdapter->TxBuffer), BUFFER_SIZE);
		if ((Status != NDIS_STATUS_SUCCESS) || (pAdapter->TxBuffer == NULL))
		{
			Status = NDIS_STATUS_RESOURCES;
			goto done;
		}
		memset(pAdapter->TxBuffer, 0, BUFFER_SIZE);
		stackSize = pAdapter->pNextDeviceObject->StackSize + 1;
		pAdapter->pTxIrp = IoAllocateIrp(stackSize, FALSE);
#endif
	}
	while (FALSE);

	return Status;

out5:	
	if (NULL != pPsPollContext->pUrb)
	{
		usb_kill_urb(pPsPollContext->pUrb);
		usb_free_urb(pPsPollContext->pUrb);
		pPsPollContext->pUrb = NULL;
	}
	if (NULL != pPsPollContext->TransferBuffer)
	{
		FreeMemory(pPsPollContext->TransferBuffer);
		pPsPollContext->TransferBuffer = NULL;
	}
out4:	
	if (NULL != pNullContext->pUrb)
	{
		usb_kill_urb(pNullContext->pUrb);
		usb_free_urb(pNullContext->pUrb);
		pNullContext->pUrb = NULL;
	}
	if (NULL != pNullContext->TransferBuffer)
	{
		FreeMemory(pNullContext->TransferBuffer);
		pNullContext->TransferBuffer = NULL;
	}
out3:	
	// Free beacon frame resource
	for (i = 0; i < BEACON_RING_SIZE; i++)
	{
		PTX_CONTEXT	pBeaconContext = &(pAdapter->BeaconContext[i]);
		if ( NULL != pBeaconContext->pUrb )
		{
			usb_kill_urb(pBeaconContext->pUrb);
			usb_free_urb(pBeaconContext->pUrb);
			pBeaconContext->pUrb = NULL;
		}
		
		if ( NULL != pBeaconContext->TransferBuffer )
		{
			FreeMemory( pBeaconContext->TransferBuffer);
			pBeaconContext->TransferBuffer = NULL;
		}
	}
out2:	
	for ( i= 0; i < PRIO_RING_SIZE; i++ )
	{
		PTX_CONTEXT pMLMEContext = &(pAdapter->MLMEContext[i]);
		

		if ( NULL != pMLMEContext->pUrb )
		{
			usb_kill_urb(pMLMEContext->pUrb);
			usb_free_urb(pMLMEContext->pUrb);
			pMLMEContext->pUrb = NULL;
		}
		
		if ( NULL != pMLMEContext->TransferBuffer )
		{
			FreeMemory( pMLMEContext->TransferBuffer);
			pMLMEContext->TransferBuffer = NULL;
		}
	} // for
out1:	
	for ( i= 0; i < TX_RING_SIZE; i++ )
	{
		PTX_CONTEXT pTxContext = &(pAdapter->TxContext[i]);

		if ( NULL != pTxContext->pUrb )
		{
			usb_kill_urb(pTxContext->pUrb);
			usb_free_urb(pTxContext->pUrb);
			pTxContext->pUrb = NULL;
		}
		if ( NULL != pTxContext->TransferBuffer )
		{
			FreeMemory( pTxContext->TransferBuffer);
			pTxContext->TransferBuffer = NULL;
		}
	} // for
done:	
	DBGPRINT(RT_DEBUG_TRACE,"<-- NICInitTransmit\n");
	return Status;
}

/*
	========================================================================
	
	Routine Description:
		Initialize receive data structures

	Arguments:
		Adapter 					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( PRT2570ADAPTER	pAdapter)
{
	UCHAR	i;
	NDIS_STATUS 	Status = NDIS_STATUS_SUCCESS;


	DBGPRINT(RT_DEBUG_TRACE,"--> NICInitRecv\n");
	pAdapter->NextRxBulkInIndex = 0;
	atomic_set( &pAdapter->PendingRx, 0);
	for (i = 0; i < RX_RING_SIZE; i++)
	{
		PRX_CONTEXT  pRxContext = &(pAdapter->RxContext[i]);
		pRxContext->pUrb = RT2570_USB_ALLOC_URB(0);
		if(pRxContext->pUrb == NULL)
		{
			Status = NDIS_STATUS_RESOURCES;
			DBGPRINT(RT_DEBUG_TRACE,"--> pRxContext->pUrb == NULL\n");
			break;
		}
						
		pRxContext->TransferBuffer= (PUCHAR) kmalloc(BUFFER_SIZE, GFP_KERNEL);
		if(!pRxContext->TransferBuffer)
		{
			DBGPRINT(RT_DEBUG_ERROR,"Not enough memory\n");
			Status = NDIS_STATUS_RESOURCES;
			break;
		}	

		memset(pRxContext->TransferBuffer, 0, BUFFER_SIZE);
		
		pRxContext->pAdapter = pAdapter;
		pRxContext->InUse = FALSE;
	}

	DBGPRINT(RT_DEBUG_TRACE,"<-- NICInitRecv\n");	
	return Status;
}
NDIS_STATUS RT2570InitAdapterBlock(	PRT2570ADAPTER	pAdapter)
{
	NDIS_STATUS 	Status = NDIS_STATUS_SUCCESS;
	UINT			i;
	PCmdQElmt		cmdqelmt;
	
	do
	{
		for (i = 0; i < COMMAND_QUEUE_SIZE; i++)
		{
			cmdqelmt = &(pAdapter->CmdQElements[i]);
			memset(cmdqelmt, 0, sizeof(CmdQElmt));
			cmdqelmt->buffer = NULL;
			cmdqelmt->CmdFromNdis = FALSE;
			cmdqelmt->InUse = FALSE;
		}
		RTUSBInitializeCmdQ(&pAdapter->CmdQ);

		init_MUTEX(&(pAdapter->usbdev_semaphore));
		init_MUTEX_LOCKED(&(pAdapter->mlme_semaphore));
		init_MUTEX_LOCKED(&(pAdapter->RTUSBCmd_semaphore));
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
		init_completion (&pAdapter->notify);
#endif
		NdisAllocateSpinLock(&pAdapter->CmdQLock);
		NdisAllocateSpinLock(&pAdapter->SendTxWaitQueueLock);
		NdisAllocateSpinLock(&pAdapter->BulkOutLock);
		NdisAllocateSpinLock(&pAdapter->MLMEWaitQueueLock);
		NdisAllocateSpinLock(&pAdapter->MLMEQLock);
	}while(0);

	return Status;
}
////////////////////////////////////////////////////////////////////////////
//
//	FUNCTION
//		ReleaseAdapter
//
//	DESCRIPTION
//		Calls USB_InterfaceStop and frees memory allocated for the URBs
//		calls NdisMDeregisterDevice and frees the memory
//		allocated in VNetInitialize for the Adapter Object
//		
//	INPUT
//		Adapter 	Pointer to RT2570ADAPTER structure
//
//	OUTPUT
//		-
//		
////////////////////////////////////////////////////////////////////////////
VOID ReleaseAdapter(PRT2570ADAPTER pAdapter, BOOLEAN IsF)
{
	UINT	i, IsFree;
	PTX_CONTEXT	pNullContext = &pAdapter->NullContext;
	PTX_CONTEXT	pPsPollContext = &pAdapter->PsPollContext;
	
	IsFree = 1;
	DBGPRINT(RT_DEBUG_TRACE, "==> ReleaseAdapter\n");
	// Free all resources for the RECEIVE buffer queue.
	for (i = 0; i < RX_RING_SIZE; i++)
	{
		PRX_CONTEXT  pRxContext = &(pAdapter->RxContext[i]);

		if (pRxContext->pUrb != NULL)
		{

			usb_kill_urb(pRxContext->pUrb);
			if (IsFree)
			usb_free_urb(pRxContext->pUrb);
			pRxContext->pUrb = NULL;
		}
		if (pRxContext->TransferBuffer != NULL)
		{
			FreeMemory(pRxContext->TransferBuffer); 
			pRxContext->TransferBuffer = NULL;
		}

	}
#if 0

	if (NULL != pWpaPskContext->pUrb)
	{
		usb_free_urb(pWpaPskContext->pUrb);
		pWpaPskContext->pUrb = NULL;
	}
	if (NULL != pWpaPskContext->TransferBuffer)
	{
		FreeMemory(pWpaPskContext->TransferBuffer);
		pWpaPskContext->TransferBuffer = NULL;
	}
#endif

	if (NULL != pPsPollContext->pUrb)
	{
		usb_kill_urb(pPsPollContext->pUrb);
		if (IsFree)
		usb_free_urb(pPsPollContext->pUrb);
		pPsPollContext->pUrb = NULL;
	}
	if (NULL != pPsPollContext->TransferBuffer)
	{
		FreeMemory(pPsPollContext->TransferBuffer);
		pPsPollContext->TransferBuffer = NULL;
	}

	if (NULL != pNullContext->pUrb)
	{
		usb_kill_urb(pNullContext->pUrb);
		if (IsFree)
		usb_free_urb(pNullContext->pUrb);
		pNullContext->pUrb = NULL;
	}
	if (NULL != pNullContext->TransferBuffer)
	{
		FreeMemory(pNullContext->TransferBuffer);
		pNullContext->TransferBuffer = NULL;
	}
	// Free beacon frame resource
	for (i = 0; i < BEACON_RING_SIZE; i++)
	{
		PTX_CONTEXT	pBeaconContext = &(pAdapter->BeaconContext[i]);
		if ( NULL != pBeaconContext->pUrb )
		{
			usb_kill_urb(pBeaconContext->pUrb);
			if (IsFree)
			usb_free_urb(pBeaconContext->pUrb);
			pBeaconContext->pUrb = NULL;
		}
		
		if ( NULL != pBeaconContext->TransferBuffer )
		{
			FreeMemory( pBeaconContext->TransferBuffer);
			pBeaconContext->TransferBuffer = NULL;
		}
	}
	for ( i= 0; i < PRIO_RING_SIZE; i++ )
	{
		PTX_CONTEXT pMLMEContext = &(pAdapter->MLMEContext[i]);
		

		if ( NULL != pMLMEContext->pUrb )
		{
			usb_kill_urb(pMLMEContext->pUrb);
			if (IsFree)
			usb_free_urb(pMLMEContext->pUrb);
			pMLMEContext->pUrb = NULL;
		}
		
		if ( NULL != pMLMEContext->TransferBuffer )
		{
			FreeMemory( pMLMEContext->TransferBuffer);
			pMLMEContext->TransferBuffer = NULL;
		}
	} // for
	for ( i= 0; i < TX_RING_SIZE; i++ )
	{
		PTX_CONTEXT pTxContext = &(pAdapter->TxContext[i]);


		if ( NULL != pTxContext->pUrb )
		{
			usb_kill_urb(pTxContext->pUrb);
			if (IsFree)
			usb_free_urb(pTxContext->pUrb);
			pTxContext->pUrb = NULL;
		}
		
		if ( NULL != pTxContext->TransferBuffer )
		{
			FreeMemory( pTxContext->TransferBuffer);
			pTxContext->TransferBuffer = NULL;
		}
	} // for

	DBGPRINT(RT_DEBUG_TRACE, "<== ReleaseAdapter\n");

}

VOID PortCfgInit(PRT2570ADAPTER pAdapter)
{
	UINT i;
	
	pAdapter->PortCfg.UseBGProtection = 2; // always not use
	pAdapter->PortCfg.CapabilityInfo = 0x0000;
	pAdapter->BulkOutMaxPacketSize = 64;
	//pAdapter->PortCfg.AuthRspTimeout = AUTH_KEY_TIMEOUT;	 // in msec
	pAdapter->PortCfg.Psm = PWR_ACTIVE;
	pAdapter->PortCfg.BeaconPeriod = 100;	  // in mSec
	//	pAdapter->PortCfg.AssocRspTimeout = ASSOC_TIMEOUT;	// in mSec

#if 1
	pAdapter->BBPR17InitValue = 0x32;
#endif
	pAdapter->PortCfg.CfpMaxDuration = 0;	  // never mind, decided by AP later
	pAdapter->PortCfg.CfpDurRemain = 0; 	  // never mind, decided by AP later
	pAdapter->PortCfg.CfpCount = 0; 		  // never mind, decided by AP later
	pAdapter->PortCfg.CfpPeriod = 0;		  // never mind, decided by AP later
	pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeOpen;
	pAdapter->PortCfg.CipherAlg = CIPHER_NONE;
	pAdapter->PortCfg.MlmeRate = RATE_2;
	pAdapter->PortCfg.RtsRate = RATE_2;
	for(i = 0; i < SHARE_KEY_NO; i++)
	{
		pAdapter->PortCfg.SharedKey[i].KeyLen = 0;
	}

	for(i = 0; i < PAIRWISE_KEY_NO; i++) 
	{
		pAdapter->PortCfg.PairwiseKey[i].KeyLen = 0;
	}

	for(i = 0; i < GROUP_KEY_NO; i++) 
	{
		pAdapter->PortCfg.GroupKey[i].KeyLen = 0;
	}
	pAdapter->PortCfg.WepStatus = Ndis802_11EncryptionDisabled;
	pAdapter->PortCfg.OrigWepStatus = Ndis802_11EncryptionDisabled;
	pAdapter->PortCfg.PairCipher = Ndis802_11EncryptionDisabled;
	pAdapter->PortCfg.GroupCipher = Ndis802_11EncryptionDisabled;
	pAdapter->PortCfg.bMixCipher = FALSE;
	pAdapter->PortCfg.DefaultKeyId = 0;
	
	pAdapter->PortCfg.PrivacyFilter = Ndis802_11PrivFilterAcceptAll;

	// 802.1x port control
	pAdapter->PortCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
	pAdapter->PortCfg.LastMicErrorTime = 0;
	pAdapter->PortCfg.MicErrCnt 	   = 0;
	pAdapter->PortCfg.bBlockAssoc	   = FALSE;

	pAdapter->PortCfg.RtsThreshold = 2347;
	pAdapter->PortCfg.FragmentThreshold = 2346;
	pAdapter->PortCfg.bFragmentZeroDisable = FALSE;

	pAdapter->PortCfg.CurrentTxAntenna = 0xff;	// diversity
	pAdapter->PortCfg.CurrentRxAntenna = 0xff;	// diversity
	pAdapter->PortCfg.NumberOfAntenna = 2;

//	pAdapter->PortCfg.TxPowerLevel[0] = 100;
//	pAdapter->PortCfg.NumOfTxPowerLevel = 1;
	pAdapter->PortCfg.TxPower = 100; //mW
	pAdapter->PortCfg.TxPowerPercentage = 0xffffffff; // AUTO

	pAdapter->PortCfg.AntennaSupportTx = TRUE;
	pAdapter->PortCfg.AntennaSupportRx = TRUE;
	pAdapter->PortCfg.AntennaSupportDiversityRx = TRUE;

	pAdapter->PortCfg.RecvDtim = TRUE;
	memset(&pAdapter->PortCfg.Bssid, 0, MAC_ADDR_LEN);
	memset(&pAdapter->PortCfg.Broadcast, 0xff, MAC_ADDR_LEN);
	pAdapter->PortCfg.Pss = PWR_ACTIVE;
	pAdapter->PortCfg.RssiTrigger = 0;
	pAdapter->PortCfg.LastRssi = 0;
	pAdapter->PortCfg.AvgRssi  = 0;
	pAdapter->PortCfg.RssiTriggerMode = RSSI_TRIGGERED_UPON_BELOW_THRESHOLD;
	pAdapter->PortCfg.AtimWin = 0;
	pAdapter->PortCfg.Channel = 1;

	pAdapter->PortCfg.Aid = 1;

	pAdapter->PortCfg.DefaultListenCount = 3;//default listen count;
	pAdapter->PortCfg.BssType = BSS_INFRA;	// BSS_INFRA or BSS_INDEP

	pAdapter->PortCfg.SsidLen = 0;
	memset(pAdapter->PortCfg.Ssid, 0, MAX_LEN_OF_SSID);  // NOT NULL-terminated

	// global variables mXXXX used in MAC protocol state machines
	pAdapter->PortCfg.Mibss = FALSE;
	pAdapter->PortCfg.Massoc = FALSE;
	pAdapter->PortCfg.Mauth = FALSE;
	pAdapter->PortCfg.MallowRFMONTx = FALSE;

	// PHY specification
	pAdapter->PortCfg.PhyMode = PHY_11BG_MIXED;
	//	  RTMPSetPhyMode(pAdapter, PHY_11BG_MIXED);   // default in 11BG mixed mode
	pAdapter->PortCfg.Dsifs = 10;	   // in units of usec 
	pAdapter->PortCfg.TxPreambleInUsed = Rt802_11PreambleLong; // use Long preamble on TX by defaut

	// user desired power mode
	pAdapter->PortCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; // Ndis802_11PowerModeFast_PSP;
	pAdapter->PortCfg.WindowsTxPreamble = Rt802_11PreambleAuto; // use Long preamble on TX by defaut
	//pAdapter->PortCfg.PacketFilter = NDIS_PACKET_TYPE_ALL_MULTICAST | NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_BROADCAST;
	pAdapter->bAcceptDirect = TRUE;
	pAdapter->bAcceptMulticast = FALSE;
	pAdapter->bAcceptBroadcast = TRUE;
	pAdapter->bAcceptAllMulticast = TRUE;
	
#ifdef NDIS51_MINIPORT
	pAdapter->PortCfg.WindowsPowerProfile = NdisPowerProfileAcOnLine; // Ndis802_11PowerModeFast_PSP;
#endif
	// parameters to be used when this STA starts a new ADHOC network
	pAdapter->PortCfg.IbssConfig.BeaconPeriod = 100;
	pAdapter->PortCfg.IbssConfig.AtimWin = 0;
	pAdapter->PortCfg.IbssConfig.Channel = 1;
	pAdapter->PortCfg.RfType = RFIC_2525;
	pAdapter->PortCfg.LedMode = LED_MODE_DEFAULT;
	//steven	NdisMInitializeTimer(&pAdapter->PortCfg.RfTuningTimer, pAdapter->AdapterHandle, AsicRfTuningExec, pAdapter);

	// Patch for Ndtest
	pAdapter->PortCfg.IgnoredScanNumber = 0;
	pAdapter->bTxBusy = FALSE;
		
	pAdapter->PortCfg.bHwRadio	= TRUE;
	pAdapter->PortCfg.bSwRadio	= TRUE;
	pAdapter->PortCfg.bRadio	= TRUE;
	DBGPRINT(RT_DEBUG_TEMP, "INIT bRadio=%d\n", pAdapter->PortCfg.bRadio);
	pAdapter->PortCfg.bHardwareRadio = FALSE;		// Default is OFF
	pAdapter->PortCfg.bAutoTxAgc = FALSE;			// Default is OFF
	pAdapter->PortCfg.bShowHiddenSSID = FALSE;		// Default no show
	pAdapter->PortCfg.AdhocMode = 0; // b/g in adhoc
	
	// Nitro mode control
	pAdapter->PortCfg.EnableTxBurst = 0;		
	pAdapter->PortCfg.AutoReconnect = 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.
	pAdapter->PortCfg.LastScanTime = 0;
	pAdapter->ScanAllowed = TRUE;


	// Default for extra information is not valid
	pAdapter->ExtraInfo = EXTRA_INFO_CLEAR;
	// Default Config change flag
	pAdapter->bConfigChanged = FALSE;

	// dynamic BBP R17:sensibity tuning to overcome background noise
	pAdapter->PortCfg.BbpTuningEnable  = TRUE;	// overwritten by E2PROM setting
	pAdapter->PortCfg.VgcLowerBound    = 0x38;	// overwritten by E2PROM setting
	pAdapter->PortCfg.BbpTuning.FalseCcaLowerThreshold = 100;
	pAdapter->PortCfg.BbpTuning.FalseCcaUpperThreshold = 4;   // unit 128, 4*128 = 512
	pAdapter->PortCfg.BbpTuning.VgcDelta			   = 1;
	pAdapter->PortCfg.BbpTuning.VgcUpperBound		   = BBP_R17_DYNAMIC_UP_BOUND;
	pAdapter->PortCfg.UseShortSlotTime = 1;//steven:for 2/20 demo purpose

	for (i = 0; i < 12; i++)
	{
		pAdapter->TxRateSwitchingStruc[i].LastStableTime = 0;
		pAdapter->TxRateSwitchingStruc[i].DownRate1Ratio = 55;
		pAdapter->TxRateSwitchingStruc[i].DownRate2Ratio = 45;
		pAdapter->TxRateSwitchingStruc[i].UpRateRatio = 85;
		pAdapter->TxRateSwitchingStruc[i].StableTimeRequired = 3;
		pAdapter->TxRateSwitchingStruc[i].PenaltyPeriod = 6;
		pAdapter->TxRateSwitchingStruc[i].DownWaitingTime = 4;
		switch (i)
		{
			case 11:
			pAdapter->TxRateSwitchingStruc[i].DownRate1Ratio = 70;
			break;
		}
	}
	pAdapter->BBPTuningParameters.BBPTuningThreshold = 45;
	pAdapter->BBPTuningParameters.R24LowerValue = 0x80;
	pAdapter->BBPTuningParameters.R25LowerValue = 0x50;
	pAdapter->BBPTuningParameters.R61LowerValue = 0x60;
	pAdapter->BBPTuningParameters.R24HigherValue = 0x70;
	pAdapter->BBPTuningParameters.R25HigherValue = 0x40;
	pAdapter->BBPTuningParameters.R61HigherValue = 0x6d;
	pAdapter->BBPTuningParameters.BBPR17LowSensitivity = BBP_R17_LOW_SENSIBILITY;
	pAdapter->BBPTuningParameters.BBPR17MidSensitivity = BBP_R17_MID_SENSIBILITY;
	pAdapter->BBPTuningParameters.RSSIToDbmOffset = RSSI_TO_DBM_OFFSET;
	pAdapter->BBPTuningParameters.LargeCurrentRSSI = FALSE;

}

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.
//

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++;
	}
}

/*
	========================================================================
	
	Routine Description:
		Init timer objects

	Arguments:
		pAdapter			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	PRT2570ADAPTER			pAdapter,
	IN	PRALINK_TIMER_STRUCT	pTimer,
	IN	PVOID					pTimerFunc)
{
	init_timer(&pTimer->Timer);
	pTimer->Timer.data = (unsigned long)pAdapter;
	pTimer->Timer.function = pTimerFunc;

}

/*
	========================================================================
	
	Routine Description:
		Init timer objects

	Arguments:
		pTimer				Timer structure
		Value				Timer value in milliseconds

	Return Value:
		None

	Note:
		
	========================================================================
*/
VOID	RTMPSetTimer(
	IN	PRT2570ADAPTER			pAdapter,	
	IN	PRALINK_TIMER_STRUCT	pTimer,
	IN	ULONG					Value)
{
	//
	// We should not set a timer when driver is on Halt state.
	// 
	if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_HALT_IN_PROGRESS))
		return;
	pTimer->Timer.expires = jiffies + (Value * HZ)/1000;
	add_timer(&pTimer->Timer);
}

/*
	========================================================================
	
	Routine Description:
		Cancel timer objects

	Arguments:
		Adapter						Pointer to our adapter

	Return Value:
		None

	IRQL = PASSIVE_LEVEL
	IRQL = DISPATCH_LEVEL
	
	Note:
		Reset NIC to initial state AS IS system boot up time.
		
	========================================================================
*/
VOID	RTMPCancelTimer(
	IN	PRALINK_TIMER_STRUCT	pTimer)
{
	del_timer_sync(&pTimer->Timer);
}

