[PATCH 259/342] Staging: rt2860: prepare for rt28[67]0/common/*.[ch] merge

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Bartlomiej Zolnierkiewicz <bzolnier at gmail.com>

Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier at gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
---
 drivers/staging/rt2860/common/action.c    |    6 +
 drivers/staging/rt2860/common/ba_action.c |   63 ++-
 drivers/staging/rt2860/common/cmm_data.c  |  230 +++++-
 drivers/staging/rt2860/common/cmm_info.c  |   45 +-
 drivers/staging/rt2860/common/cmm_sync.c  |   13 +-
 drivers/staging/rt2860/common/cmm_wpa.c   |   12 +-
 drivers/staging/rt2860/common/eeprom.c    | 1268 ++++++++++++++++++++++++++++-
 drivers/staging/rt2860/common/mlme.c      | 1163 ++++++++++++++++++++++++++-
 drivers/staging/rt2860/common/rtmp_init.c |  861 +++++++++++++++++++-
 drivers/staging/rt2860/common/spectrum.c  |    5 +
 10 files changed, 3644 insertions(+), 22 deletions(-)

diff --git a/drivers/staging/rt2860/common/action.c b/drivers/staging/rt2860/common/action.c
index c270ccd..a4d9fdc 100644
--- a/drivers/staging/rt2860/common/action.c
+++ b/drivers/staging/rt2860/common/action.c
@@ -527,9 +527,15 @@ VOID SendRefreshBAR(
 			MakeOutgoingFrame(pOutBuffer,				&FrameLen,
 							  sizeof(FRAME_BAR),	  &FrameBar,
 							  END_OF_ARGS);
+
 			if (1)	// Now we always send BAR.
 			{
+#ifndef RT30xx
 				MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+#endif
+#ifdef RT30xx
+				MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+#endif
 			}
 			MlmeFreeMemory(pAd, pOutBuffer);
 		}
diff --git a/drivers/staging/rt2860/common/ba_action.c b/drivers/staging/rt2860/common/ba_action.c
index 6b0898d..b95a341 100644
--- a/drivers/staging/rt2860/common/ba_action.c
+++ b/drivers/staging/rt2860/common/ba_action.c
@@ -531,6 +531,13 @@ VOID BAOriSessionSetUp(
 	pBAEntry->TimeOutValue = TimeOut;
 	pBAEntry->pAdapter = pAd;
 
+#ifdef RT30xx
+	DBGPRINT(RT_DEBUG_TRACE,("Send AddBA to %02x:%02x:%02x:%02x:%02x:%02x Tid:%d isForced:%d Wcid:%d\n"
+		,pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2]
+		,pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5]
+		,TID,isForced,pEntry->Aid));
+#endif
+
 	if (!(pEntry->TXBAbitmap & (1<<TID)))
 	{
 		RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE);
@@ -1071,8 +1078,16 @@ VOID BAOriSessionSetupTimeout(
 		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);
+#ifndef RT30xx
 		DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token));
-
+#endif
+#ifdef RT30xx
+		DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) to %02x:%02x:%02x:%02x:%02x:%02x Tid:%d Wcid:%d\n"
+		,pBAEntry->Token
+		,pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2]
+		,pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5]
+		,pBAEntry->TID,pEntry->Aid));
+#endif
 		pBAEntry->Token++;
 		RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
 	}
@@ -1376,6 +1391,10 @@ VOID SendPSMPAction(
 	//ULONG           Idx;
 	FRAME_PSMP_ACTION   Frame;
 	ULONG           FrameLen;
+#ifdef RT30xx
+	UCHAR			bbpdata=0;
+	UINT32			macdata;
+#endif // RT30xx //
 
 	NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);	 //Get an unused nonpaged memory
 	if (NStatus != NDIS_STATUS_SUCCESS)
@@ -1391,12 +1410,54 @@ VOID SendPSMPAction(
 	switch (Psmp)
 	{
 		case MMPS_ENABLE:
+#ifdef RT30xx
+			if (IS_RT3090(pAd))
+			{
+				// disable MMPS BBP control register
+				RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata);
+				bbpdata &= ~(0x04);	//bit 2
+				RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata);
+
+				// disable MMPS MAC control register
+				RTMP_IO_READ32(pAd, 0x1210, &macdata);
+				macdata &= ~(0x09);	//bit 0, 3
+				RTMP_IO_WRITE32(pAd, 0x1210, macdata);
+			}
+#endif // RT30xx //
 			Frame.Psmp = 0;
 			break;
 		case MMPS_DYNAMIC:
+#ifdef RT30xx
+			if (IS_RT3090(pAd))
+			{
+				// enable MMPS BBP control register
+				RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata);
+				bbpdata |= 0x04;	//bit 2
+				RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata);
+
+				// enable MMPS MAC control register
+				RTMP_IO_READ32(pAd, 0x1210, &macdata);
+				macdata |= 0x09;	//bit 0, 3
+				RTMP_IO_WRITE32(pAd, 0x1210, macdata);
+			}
+#endif // RT30xx //
 			Frame.Psmp = 3;
 			break;
 		case MMPS_STATIC:
+#ifdef RT30xx
+			if (IS_RT3090(pAd))
+			{
+				// enable MMPS BBP control register
+				RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata);
+				bbpdata |= 0x04;	//bit 2
+				RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata);
+
+				// enable MMPS MAC control register
+				RTMP_IO_READ32(pAd, 0x1210, &macdata);
+				macdata |= 0x09;	//bit 0, 3
+				RTMP_IO_WRITE32(pAd, 0x1210, macdata);
+			}
+#endif // RT30xx //
 			Frame.Psmp = 1;
 			break;
 	}
diff --git a/drivers/staging/rt2860/common/cmm_data.c b/drivers/staging/rt2860/common/cmm_data.c
index d857d06..66eca20 100644
--- a/drivers/staging/rt2860/common/cmm_data.c
+++ b/drivers/staging/rt2860/common/cmm_data.c
@@ -105,7 +105,9 @@ NDIS_STATUS MiniportMMRequest(
 	PNDIS_PACKET	pPacket;
 	NDIS_STATUS  	Status = NDIS_STATUS_SUCCESS;
 	ULONG	 		FreeNum;
+#ifdef RT2860
 	unsigned long	IrqFlags = 0;
+#endif
 	UCHAR			IrqState;
 	UCHAR			rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
 
@@ -117,9 +119,10 @@ NDIS_STATUS MiniportMMRequest(
 
 	IrqState = pAd->irq_disabled;
 
+#ifdef RT2860
 	if ((pAd->MACVersion == 0x28600100) && (!IrqState))
 		RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
-
+#endif
 	do
 	{
 		// Reset is in progress, stop immediately
@@ -172,14 +175,15 @@ NDIS_STATUS MiniportMMRequest(
 
 	} while (FALSE);
 
+#ifdef RT2860
 	// 2860C use Tx Ring
 	if ((pAd->MACVersion == 0x28600100) && (!IrqState))
 		RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
-
+#endif
 	return Status;
 }
 
-
+#ifdef RT2860
 NDIS_STATUS MiniportMMRequestUnlock(
 	IN	PRTMP_ADAPTER	pAd,
 	IN	UCHAR			QueIdx,
@@ -247,8 +251,116 @@ NDIS_STATUS MiniportMMRequestUnlock(
 
 	return Status;
 }
+#endif
+#ifdef RT30xx
+NDIS_STATUS MlmeDataHardTransmit(
+	IN	PRTMP_ADAPTER	pAd,
+	IN	UCHAR	QueIdx,
+	IN	PNDIS_PACKET	pPacket);
+
+#define MAX_DATAMM_RETRY	3
+/*
+	========================================================================
+
+	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 MiniportDataMMRequest(
+							 IN  PRTMP_ADAPTER   pAd,
+							 IN  UCHAR           QueIdx,
+							 IN  PUCHAR          pData,
+							 IN  UINT            Length)
+{
+	PNDIS_PACKET    pPacket;
+	NDIS_STATUS  Status = NDIS_STATUS_SUCCESS;
+	ULONG    FreeNum;
+	int 	retry = 0;
+	UCHAR           IrqState;
+	UCHAR			rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
+
+	ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
+
+	// 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
+
+		// free Tx(QueIdx) resources
+		FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
+
+		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 = MlmeDataHardTransmit(pAd, QueIdx, pPacket);
+			if (Status != NDIS_STATUS_SUCCESS)
+				RTMPFreeNdisPacket(pAd, pPacket);
+			retry = MAX_DATAMM_RETRY;
+		}
+		else
+		{
+			retry ++;
+
+			printk("retry %d\n", retry);
+			pAd->RalinkCounters.MgmtRingFullCount++;
+
+			if (retry >= MAX_DATAMM_RETRY)
+			{
+				DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
+											QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
+			}
+		}
+
+	} while (retry < MAX_DATAMM_RETRY);
+
+
+	return Status;
+}
+#endif /* RT30xx */
+
 /*
 	========================================================================
 
@@ -283,14 +395,16 @@ NDIS_STATUS MlmeHardTransmit(
 		return NDIS_STATUS_FAILURE;
 	}
 
+#ifdef RT2860
 	if ( pAd->MACVersion == 0x28600100 )
 		return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
 	else
+#endif
 		return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
 
 }
 
-
+#ifdef RT2860
 NDIS_STATUS MlmeHardTransmitTxRing(
 	IN	PRTMP_ADAPTER	pAd,
 	IN	UCHAR	QueIdx,
@@ -472,7 +586,25 @@ NDIS_STATUS MlmeHardTransmitTxRing(
 
 	return NDIS_STATUS_SUCCESS;
 }
+#endif /* RT2860 */
+
+#ifdef RT30xx
+NDIS_STATUS MlmeDataHardTransmit(
+	IN	PRTMP_ADAPTER	pAd,
+	IN	UCHAR	QueIdx,
+	IN	PNDIS_PACKET	pPacket)
+{
+	if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
+		)
+	{
+		return NDIS_STATUS_FAILURE;
+	}
 
+#ifdef RT2870
+	return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
+#endif // RT2870 //
+}
+#endif /* RT30xx */
 
 NDIS_STATUS MlmeHardTransmitMgmtRing(
 	IN	PRTMP_ADAPTER	pAd,
@@ -500,7 +632,12 @@ NDIS_STATUS MlmeHardTransmitMgmtRing(
 
 	// outgoing frame always wakeup PHY to prevent frame lost
 	if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+#ifdef RT2860
 		AsicForceWakeup(pAd, FROM_TX);
+#endif
+#ifdef RT2870
+		AsicForceWakeup(pAd, TRUE);
+#endif
 
 	pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA +  TXINFO_SIZE);
 	pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
@@ -823,7 +960,13 @@ BOOLEAN RTMP_FillTxBlkInfo(
 
 		{
 			// If support WMM, enable it.
+#ifdef RT2860
 			if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
+#endif
+#ifdef RT2870
+			if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
+				CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
+#endif
 				TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
 		}
 
@@ -870,6 +1013,11 @@ BOOLEAN RTMP_FillTxBlkInfo(
 	}
 
 	return TRUE;
+
+#ifdef RT30xx
+FillTxBlkErr:
+	return FALSE;
+#endif
 }
 
 
@@ -957,6 +1105,7 @@ VOID RTMPDeQueuePacket(
 	if (QIdx == NUM_OF_TX_RING)
 	{
 		sQIdx = 0;
+//PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
 		eQIdx = 3;	// 4 ACs, start from 0.
 	}
 	else
@@ -999,7 +1148,7 @@ VOID RTMPDeQueuePacket(
 				DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
 				break;
 			}
-
+#ifdef RT2860
 			FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
 
 #ifdef DBG_DIAGNOSE
@@ -1024,7 +1173,7 @@ VOID RTMPDeQueuePacket(
 				RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
 				FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
 			}
-
+#endif /* RT2860 */
 			// probe the Queue Head
 			pQueue = &pAd->TxSwQueue[QueIdx];
 			if ((pEntry = pQueue->Head) == NULL)
@@ -1093,19 +1242,29 @@ VOID RTMPDeQueuePacket(
 					pTxBlk->TxFrameType = TX_LEGACY_FRAME;
 			}
 
+#ifdef RT2870
+			DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+#endif // RT2870 //
 
 			Count += pTxBlk->TxPacketList.Number;
 
 			// Do HardTransmit now.
 			Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
 
+#ifdef RT2860
 			DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
 			// static rate also need NICUpdateFifoStaCounters() function.
 			//if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
 				NICUpdateFifoStaCounters(pAd);
+#endif
 		}
 
 		RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
+
+#ifdef RT2870
+		if (!hasTxDesc)
+			RTUSBKickBulkOut(pAd);
+#endif // RT2870 //
 	}
 
 }
@@ -1633,7 +1792,7 @@ PQUEUE_HEADER	RTMPCheckTxSwQueue(
 	return (NULL);
 }
 
-
+#ifdef RT2860
 BOOLEAN  RTMPFreeTXDUponTxDmaDone(
 	IN PRTMP_ADAPTER	pAd,
 	IN UCHAR			QueIdx)
@@ -2016,6 +2175,7 @@ VOID DBGPRINT_RX_RING(
 	DBGPRINT_RAW(RT_DEBUG_TRACE,(" 	RxSwReadIdx [%d]=", AC0freeIdx));
 	DBGPRINT_RAW(RT_DEBUG_TRACE,("	pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
 }
+#endif /* RT2860 */
 
 /*
 	========================================================================
@@ -2075,7 +2235,15 @@ VOID RTMPResumeMsduTransmission(
 {
 	DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
 
-
+#ifdef RT30xx
+	// After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
+	// R66 should not be 0
+	if (pAd->BbpTuning.R66CurrentValue == 0)
+	{
+		pAd->BbpTuning.R66CurrentValue = 0x38;
+		DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
+	}
+#endif
 	RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
 
 	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
@@ -2298,7 +2466,9 @@ MAC_TABLE_ENTRY *MacTableInsertEntry(
 					pEntry->AuthMode = pAd->StaCfg.AuthMode;
 					pEntry->WepStatus = pAd->StaCfg.WepStatus;
 					pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
+#ifdef RT2860
 					AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
+#endif
 				}
 			}
 
@@ -2306,10 +2476,12 @@ MAC_TABLE_ENTRY *MacTableInsertEntry(
 			pEntry->PairwiseKey.KeyLen = 0;
 			pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
 
+#ifdef RT2860
 			if ((pAd->OpMode == OPMODE_STA) &&
 				(pAd->StaCfg.BssType == BSS_ADHOC))
 				pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
 			else
+#endif
 			pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
 
 			pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
@@ -2445,7 +2617,12 @@ BOOLEAN MacTableDeleteEntry(
 	if (pAd->MacTab.Size == 0)
 	{
 		pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
+#ifndef RT30xx
 		AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
+#endif
+#ifdef RT30xx
+		RT28XX_UPDATE_PROTECT(pAd);  // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
+#endif
 	}
 
 	return TRUE;
@@ -2469,7 +2646,9 @@ VOID MacTableReset(
 
 	for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
 	{
+#ifdef RT2860
 		RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
+#endif
 		if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
 	   {
 			// free resources of BA
@@ -2479,6 +2658,10 @@ VOID MacTableReset(
 
 
 
+#ifdef RT2870
+			NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
+			RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
+#endif // RT2870 //
 
 			//AsicDelWcidTab(pAd, i);
 		}
@@ -2791,6 +2974,37 @@ VOID Indicate_Legacy_Packet(
 
 	STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
 
+#ifdef RT2870
+	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 // RT2870 //
 
 	wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
 
diff --git a/drivers/staging/rt2860/common/cmm_info.c b/drivers/staging/rt2860/common/cmm_info.c
index ea76f5b..306c3a2 100644
--- a/drivers/staging/rt2860/common/cmm_info.c
+++ b/drivers/staging/rt2860/common/cmm_info.c
@@ -762,6 +762,7 @@ INT	Show_DescInfo_Proc(
 	IN	PRTMP_ADAPTER	pAd,
 	IN	PUCHAR			arg)
 {
+#ifdef RT2860
 	INT i, QueIdx=0;
 	PRT28XX_RXD_STRUC pRxD;
     PTXD_STRUC pTxD;
@@ -792,7 +793,7 @@ INT	Show_DescInfo_Proc(
 	    hex_dump("Rx Descriptor", (char *)pRxD, 16);
 		printk("pRxD->DDONE = %x\n", pRxD->DDONE);
 	}
-
+#endif /* RT2860 */
 	return TRUE;
 }
 
@@ -1418,6 +1419,16 @@ VOID	RTMPSetHT(
 		pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0;
 	}
 
+#ifndef RT30xx
+#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 //
+#endif
 
 	if(pHTPhyMode->SHORTGI == GI_400)
 	{
@@ -1696,7 +1707,12 @@ VOID	RTMPAddWcidAttributeEntry(
 	}
 
 	// For key index and ext IV bit, so only need to update the position(offset+3).
+#ifdef RT2860
 	RTMP_IO_WRITE8(pAd, offset+3, IVEIV);
+#endif
+#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));
@@ -2473,13 +2489,26 @@ INT	Set_HtAutoBa_Proc(
 
 	Value = simple_strtol(arg, 0, 10);
 	if (Value == 0)
+	{
 		pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+#ifdef RT30xx
+		pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE;
+#endif
+	}
     else if (Value == 1)
+	{
 		pAd->CommonCfg.BACapability.field.AutoBA = TRUE;
+#ifdef RT30xx
+		pAd->CommonCfg.BACapability.field.Policy = IMMED_BA;
+#endif
+	}
 	else
 		return FALSE; //Invalid argument
 
     pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA;
+#ifdef RT30xx
+    pAd->CommonCfg.REGBACapability.field.Policy = pAd->CommonCfg.BACapability.field.Policy;
+#endif
 	SetCommonHT(pAd);
 
 	DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAutoBa_Proc::(HtAutoBa=%d)\n",pAd->CommonCfg.BACapability.field.AutoBA));
@@ -2696,7 +2725,9 @@ PCHAR   RTMPGetRalinkAuthModeStr(
 	{
 		case Ndis802_11AuthModeOpen:
 			return "OPEN";
+#if defined(RT2860) || defined(RT30xx)
         default:
+#endif
 		case Ndis802_11AuthModeWPAPSK:
 			return "WPAPSK";
 		case Ndis802_11AuthModeShared:
@@ -2711,8 +2742,14 @@ PCHAR   RTMPGetRalinkAuthModeStr(
 			return "WPAPSKWPA2PSK";
         case Ndis802_11AuthModeWPA1WPA2:
 			return "WPA1WPA2";
+#ifndef RT30xx
 		case Ndis802_11AuthModeWPANone:
 			return "WPANONE";
+#ifdef RT2870
+		default:
+			return "UNKNOW";
+#endif
+#endif
 	}
 }
 
@@ -2721,7 +2758,9 @@ PCHAR   RTMPGetRalinkEncryModeStr(
 {
 	switch(encryMode)
 	{
+#if defined(RT2860) || defined(RT30xx)
 	    default:
+#endif
 		case Ndis802_11WEPDisabled:
 			return "NONE";
 		case Ndis802_11WEPEnabled:
@@ -2732,6 +2771,10 @@ PCHAR   RTMPGetRalinkEncryModeStr(
 			return "AES";
         case Ndis802_11Encryption4Enabled:
 			return "TKIPAES";
+#if !defined(RT2860) && !defined(RT30xx)
+		default:
+			return "UNKNOW";
+#endif
 	}
 }
 
diff --git a/drivers/staging/rt2860/common/cmm_sync.c b/drivers/staging/rt2860/common/cmm_sync.c
index 360b3bc..a6e1b6d 100644
--- a/drivers/staging/rt2860/common/cmm_sync.c
+++ b/drivers/staging/rt2860/common/cmm_sync.c
@@ -440,13 +440,24 @@ VOID ScanNextChannel(
 
 		RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
 	}
+#ifdef RT2870
+	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 // RT2870 //
 	else
 	{
 		{
 		// BBP and RF are not accessible in PS mode, we has to wake them up first
 		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+#ifdef RT2860
 				AsicForceWakeup(pAd, FROM_TX);
-
+#endif
+#ifdef RT2870
+			AsicForceWakeup(pAd, TRUE);
+#endif
 			// leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON
 			if (pAd->StaCfg.Psm == PWR_SAVE)
 				MlmeSetPsmBit(pAd, PWR_ACTIVE);
diff --git a/drivers/staging/rt2860/common/cmm_wpa.c b/drivers/staging/rt2860/common/cmm_wpa.c
index e206077..d467f53 100644
--- a/drivers/staging/rt2860/common/cmm_wpa.c
+++ b/drivers/staging/rt2860/common/cmm_wpa.c
@@ -39,10 +39,14 @@
 // WPA OUI
 UCHAR		OUI_WPA_NONE_AKM[4]		= {0x00, 0x50, 0xF2, 0x00};
 UCHAR       OUI_WPA_VERSION[4]      = {0x00, 0x50, 0xF2, 0x01};
+#ifndef RT30xx
 UCHAR       OUI_WPA_WEP40[4]      = {0x00, 0x50, 0xF2, 0x01};
+#endif
 UCHAR       OUI_WPA_TKIP[4]     = {0x00, 0x50, 0xF2, 0x02};
 UCHAR       OUI_WPA_CCMP[4]     = {0x00, 0x50, 0xF2, 0x04};
+#ifndef RT30xx
 UCHAR       OUI_WPA_WEP104[4]      = {0x00, 0x50, 0xF2, 0x05};
+#endif
 UCHAR       OUI_WPA_8021X_AKM[4]	= {0x00, 0x50, 0xF2, 0x01};
 UCHAR       OUI_WPA_PSK_AKM[4]      = {0x00, 0x50, 0xF2, 0x02};
 // WPA2 OUI
@@ -51,7 +55,9 @@ 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};
+#ifndef RT30xx
 UCHAR       OUI_WPA2_WEP104[4]   = {0x00, 0x0F, 0xAC, 0x05};
+#endif
 // 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
@@ -370,6 +376,7 @@ static VOID RTMPInsertRsnIeCipher(
                 break;
         }
 
+#ifndef RT30xx
 		if ((pAd->OpMode == OPMODE_STA) &&
 			(pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
 			(pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
@@ -385,7 +392,7 @@ static VOID RTMPInsertRsnIeCipher(
 					break;
 			}
 		}
-
+#endif
 		// swap for big-endian platform
 		pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
 	    pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
@@ -446,6 +453,7 @@ static VOID RTMPInsertRsnIeCipher(
                 break;
         }
 
+#ifndef RT30xx
 		if ((pAd->OpMode == OPMODE_STA) &&
 			(pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
 			(pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
@@ -461,7 +469,7 @@ static VOID RTMPInsertRsnIeCipher(
 					break;
 			}
 		}
-
+#endif
 		// swap for big-endian platform
 		pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
 	    pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
diff --git a/drivers/staging/rt2860/common/eeprom.c b/drivers/staging/rt2860/common/eeprom.c
index bed2d66..9729323 100644
--- a/drivers/staging/rt2860/common/eeprom.c
+++ b/drivers/staging/rt2860/common/eeprom.c
@@ -73,12 +73,16 @@ USHORT ShiftInBits(
         RaiseClock(pAd, &x);
 
         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
-
+#ifdef RT30xx
+		LowerClock(pAd, &x); //prevent read failed
+#endif
         x &= ~(EEDI);
         if(x & EEDO)
             data |= 1;
 
+#ifndef RT30xx
         LowerClock(pAd, &x);
+#endif
     }
 
     return data;
@@ -181,6 +185,15 @@ USHORT RTMP_EEPROM_READ16(
     UINT32		x;
     USHORT		data;
 
+#ifdef RT30xx
+	if (pAd->NicConfig2.field.AntDiversity)
+    {
+    	pAd->EepromAccess = TRUE;
+    }
+//2008/09/11:KH add to support efuse<--
+//2008/09/11:KH add to support efuse-->
+{
+#endif
     Offset /= 2;
     // reset bits and set EECS
     RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
@@ -188,9 +201,17 @@ USHORT RTMP_EEPROM_READ16(
     x |= EECS;
     RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
 
+#ifdef RT30xx
+	// patch can not access e-Fuse issue
+    if (!IS_RT3090(pAd))
+    {
+#endif
 	// kick a pulse
 	RaiseClock(pAd, &x);
 	LowerClock(pAd, &x);
+#ifdef RT30xx
+    }
+#endif
 
     // output the read_opcode and register number in that order
     ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3);
@@ -201,6 +222,17 @@ USHORT RTMP_EEPROM_READ16(
 
     EEpromCleanup(pAd);
 
+#ifdef RT30xx
+	// Antenna and EEPROM access are both using EESK pin,
+    // Therefor we should avoid accessing EESK at the same time
+    // Then restore antenna after EEPROM access
+	if ((pAd->NicConfig2.field.AntDiversity) || (pAd->RfIcType == RFIC_3020))
+    {
+	    pAd->EepromAccess = FALSE;
+	    AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
+    }
+}
+#endif
     return data;
 }	//ReadEEprom
 
@@ -211,6 +243,15 @@ VOID RTMP_EEPROM_WRITE16(
 {
     UINT32 x;
 
+#ifdef RT30xx
+	if (pAd->NicConfig2.field.AntDiversity)
+    {
+    	pAd->EepromAccess = TRUE;
+    }
+	//2008/09/11:KH add to support efuse<--
+//2008/09/11:KH add to support efuse-->
+	{
+#endif
 	Offset /= 2;
 
 	EWEN(pAd);
@@ -221,9 +262,17 @@ VOID RTMP_EEPROM_WRITE16(
     x |= EECS;
     RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
 
+#ifdef RT30xx
+	// patch can not access e-Fuse issue
+    if (!IS_RT3090(pAd))
+    {
+#endif
 	// kick a pulse
 	RaiseClock(pAd, &x);
 	LowerClock(pAd, &x);
+#ifdef RT30xx
+    }
+#endif
 
     // output the read_opcode ,register number and data in that order
     ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3);
@@ -240,5 +289,1222 @@ VOID RTMP_EEPROM_WRITE16(
 	EWDS(pAd);
 
     EEpromCleanup(pAd);
+
+#ifdef RT30xx
+	// Antenna and EEPROM access are both using EESK pin,
+    // Therefor we should avoid accessing EESK at the same time
+    // Then restore antenna after EEPROM access
+	if ((pAd->NicConfig2.field.AntDiversity) || (pAd->RfIcType == RFIC_3020))
+    {
+	    pAd->EepromAccess = FALSE;
+	    AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
+    }
+}
+#endif
+}
+
+//2008/09/11:KH add to support efuse<--
+#ifdef RT30xx
+/*
+	========================================================================
+
+	Routine Description:
+
+	Arguments:
+
+	Return Value:
+
+	IRQL =
+
+	Note:
+
+	========================================================================
+*/
+UCHAR eFuseReadRegisters(
+	IN	PRTMP_ADAPTER	pAd,
+	IN	USHORT Offset,
+	IN	USHORT Length,
+	OUT	USHORT* pData)
+{
+	EFUSE_CTRL_STRUC		eFuseCtrlStruc;
+	int	i;
+	USHORT	efuseDataOffset;
+	UINT32	data;
+
+	RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+
+	//Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.
+	//Use the eeprom logical address and covert to address to block number
+	eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
+
+	//Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0.
+	eFuseCtrlStruc.field.EFSROM_MODE = 0;
+
+	//Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.
+	eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+	NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+	RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
+
+	//Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.
+	i = 0;
+	while(i < 100)
+	{
+		//rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4);
+		RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+		if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+		{
+			break;
+		}
+		RTMPusecDelay(2);
+		i++;
+	}
+
+	//if EFSROM_AOUT is not found in physical address, write 0xffff
+	if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f)
+	{
+		for(i=0; i<Length/2; i++)
+			*(pData+2*i) = 0xffff;
+	}
+	else
+	{
+		//Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x590-0x59C)
+		efuseDataOffset =  EFUSE_DATA3 - (Offset & 0xC)  ;
+		//data hold 4 bytes data.
+		//In RTMP_IO_READ32 will automatically execute 32-bytes swapping
+		RTMP_IO_READ32(pAd, efuseDataOffset, &data);
+		//Decide the upper 2 bytes or the bottom 2 bytes.
+		// Little-endian		S	|	S	Big-endian
+		// addr	3	2	1	0	|	0	1	2	3
+		// Ori-V	D	C	B	A	|	A	B	C	D
+		//After swapping
+		//		D	C	B	A	|	D	C	B	A
+		//Return 2-bytes
+		//The return byte statrs from S. Therefore, the little-endian will return BA, the Big-endian will return DC.
+		//For returning the bottom 2 bytes, the Big-endian should shift right 2-bytes.
+		data = data >> (8*(Offset & 0x3));
+
+		NdisMoveMemory(pData, &data, Length);
+	}
+
+	return (UCHAR) eFuseCtrlStruc.field.EFSROM_AOUT;
+
+}
+
+/*
+	========================================================================
+
+	Routine Description:
+
+	Arguments:
+
+	Return Value:
+
+	IRQL =
+
+	Note:
+
+	========================================================================
+*/
+VOID eFusePhysicalReadRegisters(
+	IN	PRTMP_ADAPTER	pAd,
+	IN	USHORT Offset,
+	IN	USHORT Length,
+	OUT	USHORT* pData)
+{
+	EFUSE_CTRL_STRUC		eFuseCtrlStruc;
+	int	i;
+	USHORT	efuseDataOffset;
+	UINT32	data;
+
+	RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+
+	//Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.
+	eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
+
+	//Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1.
+	//Read in physical view
+	eFuseCtrlStruc.field.EFSROM_MODE = 1;
+
+	//Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.
+	eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+	NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+	RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
+
+	//Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.
+	i = 0;
+	while(i < 100)
+	{
+		RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+		if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+			break;
+		RTMPusecDelay(2);
+		i++;
+	}
+
+	//Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590)
+	//Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits.
+	//The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes
+	//Decide which EFUSE_DATA to read
+	//590:F E D C
+	//594:B A 9 8
+	//598:7 6 5 4
+	//59C:3 2 1 0
+	efuseDataOffset =  EFUSE_DATA3 - (Offset & 0xC)  ;
+
+	RTMP_IO_READ32(pAd, efuseDataOffset, &data);
+
+	data = data >> (8*(Offset & 0x3));
+
+	NdisMoveMemory(pData, &data, Length);
+
+}
+
+/*
+	========================================================================
+
+	Routine Description:
+
+	Arguments:
+
+	Return Value:
+
+	IRQL =
+
+	Note:
+
+	========================================================================
+*/
+VOID eFuseReadPhysical(
+	IN	PRTMP_ADAPTER	pAd,
+  	IN	PUSHORT lpInBuffer,
+  	IN	ULONG nInBufferSize,
+  	OUT	PUSHORT lpOutBuffer,
+  	IN	ULONG nOutBufferSize
+)
+{
+	USHORT* pInBuf = (USHORT*)lpInBuffer;
+	USHORT* pOutBuf = (USHORT*)lpOutBuffer;
+
+	USHORT Offset = pInBuf[0];					//addr
+	USHORT Length = pInBuf[1];					//length
+	int 		i;
+
+	for(i=0; i<Length; i+=2)
+	{
+		eFusePhysicalReadRegisters(pAd,Offset+i, 2, &pOutBuf[i/2]);
+	}
+}
+
+/*
+	========================================================================
+
+	Routine Description:
+
+	Arguments:
+
+	Return Value:
+
+	IRQL =
+
+	Note:
+
+	========================================================================
+*/
+NTSTATUS eFuseRead(
+	IN	PRTMP_ADAPTER	pAd,
+	IN	USHORT			Offset,
+	OUT	PUCHAR			pData,
+	IN	USHORT			Length)
+{
+	USHORT* pOutBuf = (USHORT*)pData;
+	NTSTATUS	Status = STATUS_SUCCESS;
+	UCHAR	EFSROM_AOUT;
+	int	i;
+
+	for(i=0; i<Length; i+=2)
+	{
+		EFSROM_AOUT = eFuseReadRegisters(pAd, Offset+i, 2, &pOutBuf[i/2]);
+	}
+	return Status;
+}
+
+/*
+	========================================================================
+
+	Routine Description:
+
+	Arguments:
+
+	Return Value:
+
+	IRQL =
+
+	Note:
+
+	========================================================================
+*/
+VOID eFusePhysicalWriteRegisters(
+	IN	PRTMP_ADAPTER	pAd,
+	IN	USHORT Offset,
+	IN	USHORT Length,
+	OUT	USHORT* pData)
+{
+	EFUSE_CTRL_STRUC		eFuseCtrlStruc;
+	int	i;
+	USHORT	efuseDataOffset;
+	UINT32	data, eFuseDataBuffer[4];
+
+	//Step0. Write 16-byte of data to EFUSE_DATA0-3 (0x590-0x59C), where EFUSE_DATA0 is the LSB DW, EFUSE_DATA3 is the MSB DW.
+
+	/////////////////////////////////////////////////////////////////
+	//read current values of 16-byte block
+	RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+
+	//Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.
+	eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
+
+	//Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1.
+	eFuseCtrlStruc.field.EFSROM_MODE = 1;
+
+	//Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.
+	eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+	NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+	RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
+
+	//Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.
+	i = 0;
+	while(i < 100)
+	{
+		RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+
+		if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+			break;
+		RTMPusecDelay(2);
+		i++;
+	}
+
+	//Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590)
+	efuseDataOffset =  EFUSE_DATA3;
+	for(i=0; i< 4; i++)
+	{
+		RTMP_IO_READ32(pAd, efuseDataOffset, (PUINT32) &eFuseDataBuffer[i]);
+		efuseDataOffset -=  4;
+	}
+
+	//Update the value, the offset is multiple of 2, length is 2
+	efuseDataOffset = (Offset & 0xc) >> 2;
+	data = pData[0] & 0xffff;
+	//The offset should be 0x***10 or 0x***00
+	if((Offset % 4) != 0)
+	{
+		eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff) | (data << 16);
+	}
+	else
+	{
+		eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff0000) | data;
+	}
+
+	efuseDataOffset =  EFUSE_DATA3;
+	for(i=0; i< 4; i++)
+	{
+		RTMP_IO_WRITE32(pAd, efuseDataOffset, eFuseDataBuffer[i]);
+		efuseDataOffset -= 4;
+	}
+	/////////////////////////////////////////////////////////////////
+
+	//Step1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.
+	eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
+
+	//Step2. Write EFSROM_MODE (0x580, bit7:bit6) to 3.
+	eFuseCtrlStruc.field.EFSROM_MODE = 3;
+
+	//Step3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure.
+	eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+	NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+	RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
+
+	//Step4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. It??????s done.
+	i = 0;
+	while(i < 100)
+	{
+		RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+
+		if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+			break;
+
+		RTMPusecDelay(2);
+		i++;
+	}
+}
+
+/*
+	========================================================================
+
+	Routine Description:
+
+	Arguments:
+
+	Return Value:
+
+	IRQL =
+
+	Note:
+
+	========================================================================
+*/
+NTSTATUS eFuseWriteRegisters(
+	IN	PRTMP_ADAPTER	pAd,
+	IN	USHORT Offset,
+	IN	USHORT Length,
+	IN	USHORT* pData)
+{
+	USHORT	i;
+	USHORT	eFuseData;
+	USHORT	LogicalAddress, BlkNum = 0xffff;
+	UCHAR	EFSROM_AOUT;
+
+	USHORT addr,tmpaddr, InBuf[3], tmpOffset;
+	USHORT buffer[8];
+	BOOLEAN		bWriteSuccess = TRUE;
+
+	DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters Offset=%x, pData=%x\n", Offset, *pData));
+
+	//Step 0. find the entry in the mapping table
+	//The address of EEPROM is 2-bytes alignment.
+	//The last bit is used for alignment, so it must be 0.
+	tmpOffset = Offset & 0xfffe;
+	EFSROM_AOUT = eFuseReadRegisters(pAd, tmpOffset, 2, &eFuseData);
+
+	if( EFSROM_AOUT == 0x3f)
+	{	//find available logical address pointer
+		//the logical address does not exist, find an empty one
+		//from the first address of block 45=16*45=0x2d0 to the last address of block 47
+		//==>48*16-3(reserved)=2FC
+		for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2)
+		{
+			//Retrive the logical block nubmer form each logical address pointer
+			//It will access two logical address pointer each time.
+			eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
+			if( (LogicalAddress & 0xff) == 0)
+			{//Not used logical address pointer
+				BlkNum = i-EFUSE_USAGE_MAP_START;
+				break;
+			}
+			else if(( (LogicalAddress >> 8) & 0xff) == 0)
+			{//Not used logical address pointer
+				if (i != EFUSE_USAGE_MAP_END)
+				{
+					BlkNum = i-EFUSE_USAGE_MAP_START+1;
+				}
+				break;
+			}
+		}
+	}
+	else
+	{
+		BlkNum = EFSROM_AOUT;
+	}
+
+	DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum));
+
+	if(BlkNum == 0xffff)
+	{
+		DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n"));
+		return FALSE;
+	}
+
+	//Step 1. Save data of this block	which is pointed by the avaible logical address pointer
+	// read and save the original block data
+	for(i =0; i<8; i++)
+	{
+		addr = BlkNum * 0x10 ;
+
+		InBuf[0] = addr+2*i;
+		InBuf[1] = 2;
+		InBuf[2] = 0x0;
+
+		eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+
+		buffer[i] = InBuf[2];
+	}
+
+	//Step 2. Update the data in buffer, and write the data to Efuse
+	buffer[ (Offset >> 1) % 8] = pData[0];
+
+	do
+	{
+		//Step 3. Write the data to Efuse
+		if(!bWriteSuccess)
+		{
+			for(i =0; i<8; i++)
+			{
+				addr = BlkNum * 0x10 ;
+
+				InBuf[0] = addr+2*i;
+				InBuf[1] = 2;
+				InBuf[2] = buffer[i];
+
+				eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2);
+			}
+		}
+		else
+		{
+				addr = BlkNum * 0x10 ;
+
+				InBuf[0] = addr+(Offset % 16);
+				InBuf[1] = 2;
+				InBuf[2] = pData[0];
+
+				eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2);
+		}
+
+		//Step 4. Write mapping table
+		addr = EFUSE_USAGE_MAP_START+BlkNum;
+
+		tmpaddr = addr;
+
+		if(addr % 2 != 0)
+			addr = addr -1;
+		InBuf[0] = addr;
+		InBuf[1] = 2;
+
+		//convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry
+		tmpOffset = Offset;
+		tmpOffset >>= 4;
+		tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^  (tmpOffset >> 2 & 0x01) ^  (tmpOffset >> 3 & 0x01))) << 6) & 0x40;
+		tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80;
+
+		// write the logical address
+		if(tmpaddr%2 != 0)
+			InBuf[2] = tmpOffset<<8;
+		else
+			InBuf[2] = tmpOffset;
+
+		eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0);
+
+		//Step 5. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted
+		bWriteSuccess = TRUE;
+		for(i =0; i<8; i++)
+		{
+			addr = BlkNum * 0x10 ;
+
+			InBuf[0] = addr+2*i;
+			InBuf[1] = 2;
+			InBuf[2] = 0x0;
+
+			eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+
+			if(buffer[i] != InBuf[2])
+			{
+				bWriteSuccess = FALSE;
+				break;
+			}
+		}
+
+		//Step 6. invlidate mapping entry and find a free mapping entry if not succeed
+		if (!bWriteSuccess)
+		{
+			DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess BlkNum = %d\n", BlkNum));
+
+			// the offset of current mapping entry
+			addr = EFUSE_USAGE_MAP_START+BlkNum;
+
+			//find a new mapping entry
+			BlkNum = 0xffff;
+			for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2)
+			{
+				eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
+				if( (LogicalAddress & 0xff) == 0)
+				{
+					BlkNum = i-EFUSE_USAGE_MAP_START;
+					break;
+				}
+				else if(( (LogicalAddress >> 8) & 0xff) == 0)
+				{
+					if (i != EFUSE_USAGE_MAP_END)
+					{
+						BlkNum = i+1-EFUSE_USAGE_MAP_START;
+					}
+					break;
+				}
+			}
+			DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess new BlkNum = %d\n", BlkNum));
+			if(BlkNum == 0xffff)
+			{
+				DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n"));
+				return FALSE;
+			}
+
+			//invalidate the original mapping entry if new entry is not found
+			tmpaddr = addr;
+
+			if(addr % 2 != 0)
+				addr = addr -1;
+			InBuf[0] = addr;
+			InBuf[1] = 2;
+
+			eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+
+			// write the logical address
+			if(tmpaddr%2 != 0)
+			{
+				// Invalidate the high byte
+				for (i=8; i<15; i++)
+				{
+					if( ( (InBuf[2] >> i) & 0x01) == 0)
+					{
+						InBuf[2] |= (0x1 <<i);
+						break;
+					}
+				}
+			}
+			else
+			{
+				// invalidate the low byte
+				for (i=0; i<8; i++)
+				{
+					if( ( (InBuf[2] >> i) & 0x01) == 0)
+					{
+						InBuf[2] |= (0x1 <<i);
+						break;
+					}
+				}
+			}
+			eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 0);
+		}
+	}
+	while(!bWriteSuccess);
+
+	return TRUE;
+}
+
+/*
+	========================================================================
+
+	Routine Description:
+
+	Arguments:
+
+	Return Value:
+
+	IRQL =
+
+	Note:
+
+	========================================================================
+*/
+VOID eFuseWritePhysical(
+	IN	PRTMP_ADAPTER	pAd,
+  	PUSHORT lpInBuffer,
+	ULONG nInBufferSize,
+  	PUCHAR lpOutBuffer,
+  	ULONG nOutBufferSize
+)
+{
+	USHORT* pInBuf = (USHORT*)lpInBuffer;
+	int 		i;
+	//USHORT* pOutBuf = (USHORT*)ioBuffer;
+
+	USHORT Offset = pInBuf[0];					//addr
+	USHORT Length = pInBuf[1];					//length
+	USHORT* pValueX = &pInBuf[2];				//value ...
+		// Little-endian		S	|	S	Big-endian
+		// addr	3	2	1	0	|	0	1	2	3
+		// Ori-V	D	C	B	A	|	A	B	C	D
+		//After swapping
+		//		D	C	B	A	|	D	C	B	A
+		//Both the little and big-endian use the same sequence to write  data.
+		//Therefore, we only need swap data when read the data.
+	for(i=0; i<Length; i+=2)
+	{
+		eFusePhysicalWriteRegisters(pAd, Offset+i, 2, &pValueX[i/2]);
+	}
+}
+
+
+/*
+	========================================================================
+
+	Routine Description:
+
+	Arguments:
+
+	Return Value:
+
+	IRQL =
+
+	Note:
+
+	========================================================================
+*/
+NTSTATUS eFuseWrite(
+   	IN	PRTMP_ADAPTER	pAd,
+	IN	USHORT			Offset,
+	IN	PUCHAR			pData,
+	IN	USHORT			length)
+{
+	int i;
+
+	USHORT* pValueX = (PUSHORT) pData;				//value ...
+		//The input value=3070 will be stored as following
+ 		// Little-endian		S	|	S	Big-endian
+		// addr			1	0	|	0	1
+		// Ori-V			30	70	|	30	70
+		//After swapping
+		//				30	70	|	70	30
+		//Casting
+		//				3070	|	7030 (x)
+		//The swapping should be removed for big-endian
+	for(i=0; i<length; i+=2)
+	{
+		eFuseWriteRegisters(pAd, Offset+i, 2, &pValueX[i/2]);
+	}
+
+	return TRUE;
+}
+
+/*
+	========================================================================
+
+	Routine Description:
+
+	Arguments:
+
+	Return Value:
+
+	IRQL =
+
+	Note:
+
+	========================================================================
+*/
+INT set_eFuseGetFreeBlockCount_Proc(
+   	IN	PRTMP_ADAPTER	pAd,
+	IN	PUCHAR			arg)
+{
+	USHORT i;
+	USHORT	LogicalAddress;
+	USHORT efusefreenum=0;
+	if(!pAd->bUseEfuse)
+		return FALSE;
+	for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i+=2)
+	{
+		eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
+		if( (LogicalAddress & 0xff) == 0)
+		{
+			efusefreenum= (UCHAR) (EFUSE_USAGE_MAP_END-i+1);
+			break;
+		}
+		else if(( (LogicalAddress >> 8) & 0xff) == 0)
+		{
+			efusefreenum = (UCHAR) (EFUSE_USAGE_MAP_END-i);
+			break;
+		}
+
+		if(i == EFUSE_USAGE_MAP_END)
+			efusefreenum = 0;
+	}
+	printk("efuseFreeNumber is %d\n",efusefreenum);
+	return TRUE;
+}
+INT set_eFusedump_Proc(
+	IN	PRTMP_ADAPTER	pAd,
+	IN	PUCHAR			arg)
+{
+USHORT InBuf[3];
+	INT i=0;
+	if(!pAd->bUseEfuse)
+		return FALSE;
+	for(i =0; i<EFUSE_USAGE_MAP_END/2; i++)
+	{
+		InBuf[0] = 2*i;
+		InBuf[1] = 2;
+		InBuf[2] = 0x0;
+
+		eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+		if(i%4==0)
+		printk("\nBlock %x:",i/8);
+		printk("%04x ",InBuf[2]);
+	}
+	return TRUE;
+}
+INT	set_eFuseLoadFromBin_Proc(
+	IN	PRTMP_ADAPTER	pAd,
+	IN	PUCHAR			arg)
+{
+	CHAR					*src;
+	struct file				*srcf;
+	INT 					retval, orgfsuid, orgfsgid;
+   	mm_segment_t			orgfs;
+	UCHAR					*buffer;
+	UCHAR					BinFileSize=0;
+	INT						i = 0,j=0,k=1;
+	USHORT					*PDATA;
+	USHORT					DATA;
+	BinFileSize=strlen("RT30xxEEPROM.bin");
+	src = kmalloc(128, MEM_ALLOC_FLAG);
+	NdisZeroMemory(src, 128);
+
+ 	if(strlen(arg)>0)
+	{
+
+		NdisMoveMemory(src, arg, strlen(arg));
+ 	}
+
+	else
+	{
+
+		NdisMoveMemory(src, "RT30xxEEPROM.bin", BinFileSize);
+	}
+
+	DBGPRINT(RT_DEBUG_TRACE, ("FileName=%s\n",src));
+	buffer = kmalloc(MAX_EEPROM_BIN_FILE_SIZE, MEM_ALLOC_FLAG);
+
+	if(buffer == NULL)
+	{
+		kfree(src);
+		 return FALSE;
+}
+	PDATA=kmalloc(sizeof(USHORT)*8,MEM_ALLOC_FLAG);
+
+	if(PDATA==NULL)
+	{
+		kfree(src);
+
+		kfree(buffer);
+		return FALSE;
+	}
+	/* Don't change to uid 0, let the file be opened as the "normal" user */
+#if 0
+	orgfsuid = current->fsuid;
+	orgfsgid = current->fsgid;
+	current->fsuid=current->fsgid = 0;
+#endif
+    	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));
+			return FALSE;
+		}
+		else
+		{
+			// The object must have a read method
+			if (srcf->f_op && srcf->f_op->read)
+			{
+				memset(buffer, 0x00, MAX_EEPROM_BIN_FILE_SIZE);
+				while(srcf->f_op->read(srcf, &buffer[i], 1, &srcf->f_pos)==1)
+				{
+					DBGPRINT(RT_DEBUG_TRACE, ("%02X ",buffer[i]));
+					if((i+1)%8==0)
+						DBGPRINT(RT_DEBUG_TRACE, ("\n"));
+              			i++;
+						if(i>=MAX_EEPROM_BIN_FILE_SIZE)
+							{
+								DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld reading %s, The file is too large[1024]\n", -PTR_ERR(srcf),src));
+								kfree(PDATA);
+								kfree(buffer);
+								kfree(src);
+								return FALSE;
+							}
+			       }
+			}
+			else
+			{
+						DBGPRINT(RT_DEBUG_ERROR, ("--> Error!! System doest not support read function\n"));
+						kfree(PDATA);
+						kfree(buffer);
+						kfree(src);
+						return FALSE;
+			}
+      		}
+
+
+	}
+	else
+		{
+					DBGPRINT(RT_DEBUG_ERROR, ("--> Error src  or srcf is null\n"));
+					kfree(PDATA);
+					kfree(buffer);
+					return FALSE;
+
+		}
+
+
+	retval=filp_close(srcf,NULL);
+
+	if (retval)
+	{
+		DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src));
+	}
+	set_fs(orgfs);
+#if 0
+	current->fsuid = orgfsuid;
+	current->fsgid = orgfsgid;
+#endif
+	for(j=0;j<i;j++)
+	{
+		DBGPRINT(RT_DEBUG_TRACE, ("%02X ",buffer[j]));
+		if((j+1)%2==0)
+			PDATA[j/2%8]=((buffer[j]<<8)&0xff00)|(buffer[j-1]&0xff);
+		if(j%16==0)
+		{
+			k=buffer[j];
+		}
+		else
+		{
+			k&=buffer[j];
+			if((j+1)%16==0)
+			{
+
+				DBGPRINT(RT_DEBUG_TRACE, (" result=%02X,blk=%02x\n",k,j/16));
+
+				if(k!=0xff)
+					eFuseWriteRegistersFromBin(pAd,(USHORT)j-15, 16, PDATA);
+				else
+					{
+						if(eFuseReadRegisters(pAd,j, 2,(PUSHORT)&DATA)!=0x3f)
+							eFuseWriteRegistersFromBin(pAd,(USHORT)j-15, 16, PDATA);
+					}
+				/*
+				for(l=0;l<8;l++)
+					printk("%04x ",PDATA[l]);
+				printk("\n");
+				*/
+				NdisZeroMemory(PDATA,16);
+
+
+			}
+		}
+
+
+	}
+
+
+	kfree(PDATA);
+	kfree(buffer);
+	kfree(src);
+	return TRUE;
+}
+NTSTATUS eFuseWriteRegistersFromBin(
+	IN	PRTMP_ADAPTER	pAd,
+	IN	USHORT Offset,
+	IN	USHORT Length,
+	IN	USHORT* pData)
+{
+	USHORT	i;
+	USHORT	eFuseData;
+	USHORT	LogicalAddress, BlkNum = 0xffff;
+	UCHAR	EFSROM_AOUT,Loop=0;
+	EFUSE_CTRL_STRUC		eFuseCtrlStruc;
+	USHORT	efuseDataOffset;
+	UINT32	data,tempbuffer;
+	USHORT addr,tmpaddr, InBuf[3], tmpOffset;
+	UINT32 buffer[4];
+	BOOLEAN		bWriteSuccess = TRUE;
+	BOOLEAN		bNotWrite=TRUE;
+	BOOLEAN		bAllocateNewBlk=TRUE;
+
+	DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin Offset=%x, pData=%04x:%04x:%04x:%04x\n", Offset, *pData,*(pData+1),*(pData+2),*(pData+3)));
+
+	do
+	{
+	//Step 0. find the entry in the mapping table
+	//The address of EEPROM is 2-bytes alignment.
+	//The last bit is used for alignment, so it must be 0.
+	Loop++;
+	tmpOffset = Offset & 0xfffe;
+	EFSROM_AOUT = eFuseReadRegisters(pAd, tmpOffset, 2, &eFuseData);
+
+	if( EFSROM_AOUT == 0x3f)
+	{	//find available logical address pointer
+		//the logical address does not exist, find an empty one
+		//from the first address of block 45=16*45=0x2d0 to the last address of block 47
+		//==>48*16-3(reserved)=2FC
+		bAllocateNewBlk=TRUE;
+		for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2)
+		{
+			//Retrive the logical block nubmer form each logical address pointer
+			//It will access two logical address pointer each time.
+			eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
+			if( (LogicalAddress & 0xff) == 0)
+			{//Not used logical address pointer
+				BlkNum = i-EFUSE_USAGE_MAP_START;
+				break;
+			}
+			else if(( (LogicalAddress >> 8) & 0xff) == 0)
+			{//Not used logical address pointer
+				if (i != EFUSE_USAGE_MAP_END)
+				{
+					BlkNum = i-EFUSE_USAGE_MAP_START+1;
+				}
+				break;
+			}
+		}
+	}
+	else
+	{
+		bAllocateNewBlk=FALSE;
+		BlkNum = EFSROM_AOUT;
+	}
+
+	DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum));
+
+	if(BlkNum == 0xffff)
+	{
+		DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n"));
+		return FALSE;
+	}
+	//Step 1.1.0
+	//If the block is not existing in mapping table, create one
+	//and write down the 16-bytes data to the new block
+	if(bAllocateNewBlk)
+	{
+		DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk\n"));
+		efuseDataOffset =  EFUSE_DATA3;
+		for(i=0; i< 4; i++)
+		{
+			DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk, Data%d=%04x%04x\n",3-i,pData[2*i+1],pData[2*i]));
+			tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i];
+
+
+			RTMP_IO_WRITE32(pAd, efuseDataOffset,tempbuffer);
+			efuseDataOffset -= 4;
+
+		}
+		/////////////////////////////////////////////////////////////////
+
+		//Step1.1.1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.
+		eFuseCtrlStruc.field.EFSROM_AIN = BlkNum* 0x10 ;
+
+		//Step1.1.2. Write EFSROM_MODE (0x580, bit7:bit6) to 3.
+		eFuseCtrlStruc.field.EFSROM_MODE = 3;
+
+		//Step1.1.3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure.
+		eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+		NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+
+		RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
+
+		//Step1.1.4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. It??????s done.
+		i = 0;
+		while(i < 100)
+		{
+			RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+
+			if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+				break;
+
+			RTMPusecDelay(2);
+			i++;
+		}
+
+	}
+	else
+	{	//Step1.2.
+		//If the same logical number is existing, check if the writting data and the data
+		//saving in this block are the same.
+		/////////////////////////////////////////////////////////////////
+		//read current values of 16-byte block
+		RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+
+		//Step1.2.0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.
+		eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
+
+		//Step1.2.1. Write EFSROM_MODE (0x580, bit7:bit6) to 1.
+		eFuseCtrlStruc.field.EFSROM_MODE = 0;
+
+		//Step1.2.2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.
+		eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+		NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+		RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
+
+		//Step1.2.3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.
+		i = 0;
+		while(i < 100)
+		{
+			RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+
+			if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+				break;
+			RTMPusecDelay(2);
+			i++;
+		}
+
+		//Step1.2.4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590)
+		efuseDataOffset =  EFUSE_DATA3;
+		for(i=0; i< 4; i++)
+		{
+			RTMP_IO_READ32(pAd, efuseDataOffset, (PUINT32) &buffer[i]);
+			efuseDataOffset -=  4;
+		}
+		//Step1.2.5. Check if the data of efuse and the writing data are the same.
+		for(i =0; i<4; i++)
+		{
+			tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i];
+			DBGPRINT(RT_DEBUG_TRACE, ("buffer[%d]=%x,pData[%d]=%x,pData[%d]=%x,tempbuffer=%x\n",i,buffer[i],2*i,pData[2*i],2*i+1,pData[2*i+1],tempbuffer));
+
+			if(((buffer[i]&0xffff0000)==(pData[2*i+1]<<16))&&((buffer[i]&0xffff)==pData[2*i]))
+				bNotWrite&=TRUE;
+			else
+			{
+				bNotWrite&=FALSE;
+				break;
+			}
+		}
+		if(!bNotWrite)
+		{
+		printk("The data is not the same\n");
+
+			for(i =0; i<8; i++)
+			{
+				addr = BlkNum * 0x10 ;
+
+				InBuf[0] = addr+2*i;
+				InBuf[1] = 2;
+				InBuf[2] = pData[i];
+
+				eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2);
+			}
+
+		}
+		else
+			return TRUE;
+	     }
+
+
+
+		//Step 2. Write mapping table
+		addr = EFUSE_USAGE_MAP_START+BlkNum;
+
+		tmpaddr = addr;
+
+		if(addr % 2 != 0)
+			addr = addr -1;
+		InBuf[0] = addr;
+		InBuf[1] = 2;
+
+		//convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry
+		tmpOffset = Offset;
+		tmpOffset >>= 4;
+		tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^  (tmpOffset >> 2 & 0x01) ^  (tmpOffset >> 3 & 0x01))) << 6) & 0x40;
+		tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80;
+
+		// write the logical address
+		if(tmpaddr%2 != 0)
+			InBuf[2] = tmpOffset<<8;
+		else
+			InBuf[2] = tmpOffset;
+
+		eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0);
+
+		//Step 3. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted
+		bWriteSuccess = TRUE;
+		for(i =0; i<8; i++)
+		{
+			addr = BlkNum * 0x10 ;
+
+			InBuf[0] = addr+2*i;
+			InBuf[1] = 2;
+			InBuf[2] = 0x0;
+
+			eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+			DBGPRINT(RT_DEBUG_TRACE, ("addr=%x, buffer[i]=%x,InBuf[2]=%x\n",InBuf[0],pData[i],InBuf[2]));
+			if(pData[i] != InBuf[2])
+			{
+				bWriteSuccess = FALSE;
+				break;
+			}
+		}
+
+		//Step 4. invlidate mapping entry and find a free mapping entry if not succeed
+
+		if (!bWriteSuccess&&Loop<2)
+		{
+			DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin::Not bWriteSuccess BlkNum = %d\n", BlkNum));
+
+			// the offset of current mapping entry
+			addr = EFUSE_USAGE_MAP_START+BlkNum;
+
+			//find a new mapping entry
+			BlkNum = 0xffff;
+			for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2)
+			{
+				eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
+				if( (LogicalAddress & 0xff) == 0)
+				{
+					BlkNum = i-EFUSE_USAGE_MAP_START;
+					break;
+				}
+				else if(( (LogicalAddress >> 8) & 0xff) == 0)
+				{
+					if (i != EFUSE_USAGE_MAP_END)
+					{
+						BlkNum = i+1-EFUSE_USAGE_MAP_START;
+					}
+					break;
+				}
+			}
+			DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin::Not bWriteSuccess new BlkNum = %d\n", BlkNum));
+			if(BlkNum == 0xffff)
+			{
+				DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin: out of free E-fuse space!!!\n"));
+				return FALSE;
+			}
+
+			//invalidate the original mapping entry if new entry is not found
+			tmpaddr = addr;
+
+			if(addr % 2 != 0)
+				addr = addr -1;
+			InBuf[0] = addr;
+			InBuf[1] = 2;
+
+			eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+
+			// write the logical address
+			if(tmpaddr%2 != 0)
+			{
+				// Invalidate the high byte
+				for (i=8; i<15; i++)
+				{
+					if( ( (InBuf[2] >> i) & 0x01) == 0)
+					{
+						InBuf[2] |= (0x1 <<i);
+						break;
+					}
+				}
+			}
+			else
+			{
+				// invalidate the low byte
+				for (i=0; i<8; i++)
+				{
+					if( ( (InBuf[2] >> i) & 0x01) == 0)
+					{
+						InBuf[2] |= (0x1 <<i);
+						break;
+					}
+				}
+			}
+			eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 0);
+		}
+
+	}
+	while(!bWriteSuccess&&Loop<2);
+
+	return TRUE;
 }
 
+#endif // RT30xx //
+//2008/09/11:KH add to support efuse-->
diff --git a/drivers/staging/rt2860/common/mlme.c b/drivers/staging/rt2860/common/mlme.c
index 5146868..e9e69c5 100644
--- a/drivers/staging/rt2860/common/mlme.c
+++ b/drivers/staging/rt2860/common/mlme.c
@@ -338,6 +338,9 @@ UCHAR  WpaIe	 = IE_WPA;
 UCHAR  Wpa2Ie	 = IE_WPA2;
 UCHAR  IbssIe	 = IE_IBSS_PARM;
 UCHAR  Ccx2Ie	 = IE_CCX_V2;
+#ifdef RT2870
+UCHAR  WapiIe	 = IE_WAPI;
+#endif
 
 extern UCHAR	WPA_OUI[];
 
@@ -446,7 +449,13 @@ FREQUENCY_ITEM FreqItems3020[] =
 	{13,   247,	 2,  2},
 	{14,   248,	 2,  4},
 };
+#ifndef RT30xx
 #define	NUM_OF_3020_CHNL	(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
+#endif
+#ifdef RT30xx
+//2008/07/10:KH Modified to share this variable
+UCHAR	NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
+#endif
 
 /*
 	==========================================================================
@@ -504,6 +513,7 @@ NDIS_STATUS MlmeInit(
 		// software-based RX Antenna diversity
 		RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
 
+#ifdef RT2860
 		{
 	        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
 	        {
@@ -512,6 +522,7 @@ NDIS_STATUS MlmeInit(
 	    		RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
 	        }
 		}
+#endif
 	} while (FALSE);
 
 	DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
@@ -566,6 +577,16 @@ VOID MlmeHandler(
 		//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)
@@ -636,6 +657,9 @@ VOID MlmeHalt(
 	IN PRTMP_ADAPTER pAd)
 {
 	BOOLEAN 	  Cancelled;
+#ifdef RT3070
+	UINT32		TxPinCfg = 0x00050F0F;
+#endif // RT3070 //
 
 	DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
 
@@ -653,11 +677,13 @@ VOID MlmeHalt(
 		RTMPCancelTimer(&pAd->MlmeAux.AuthTimer,		&Cancelled);
 		RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer,		&Cancelled);
 		RTMPCancelTimer(&pAd->MlmeAux.ScanTimer,		&Cancelled);
+#ifdef RT2860
 	    if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
 	    {
 	   	    RTMPCancelTimer(&pAd->Mlme.PsPollTimer,		&Cancelled);
 		    RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer,		&Cancelled);
 		}
+#endif
 	}
 
 	RTMPCancelTimer(&pAd->Mlme.PeriodicTimer,		&Cancelled);
@@ -670,6 +696,27 @@ VOID MlmeHalt(
 		// 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 //
+#ifdef RT3070
+		//
+		// Turn off LNA_PE
+		//
+		if (IS_RT3070(pAd) || IS_RT3071(pAd))
+		{
+			TxPinCfg &= 0xFFFFF0F0;
+			RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
+		}
+#endif // RT3070 //
 	}
 
 	RTMPusecDelay(5000);    //  5 msec to gurantee Ant Diversity timer canceled
@@ -740,6 +787,7 @@ VOID MlmePeriodicExec(
 	ULONG			TxTotalCnt;
 	PRTMP_ADAPTER	pAd = (RTMP_ADAPTER *)FunctionContext;
 
+#ifdef RT2860
 	//Baron 2008/07/10
 	//printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
 	//If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
@@ -792,6 +840,7 @@ VOID MlmePeriodicExec(
 			}
 		}
 	}
+#endif /* RT2860 */
 
 	// Do nothing if the driver is starting halt state.
 	// This might happen when timer already been fired before cancel timer with mlmehalt
@@ -801,6 +850,7 @@ VOID MlmePeriodicExec(
 								fRTMP_ADAPTER_RESET_IN_PROGRESS))))
 		return;
 
+#ifdef RT2860
 	{
 		if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
 		{
@@ -838,7 +888,7 @@ VOID MlmePeriodicExec(
 			AsicResetFromDMABusy(pAd);
 		}
 	}
-
+#endif /* RT2860 */
 	RT28XX_MLME_PRE_SANITY_CHECK(pAd);
 
 	{
@@ -871,6 +921,10 @@ VOID MlmePeriodicExec(
 //	RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
 	pAd->Mlme.PeriodicRound ++;
 
+#ifdef RT3070
+	// execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
+	NICUpdateFifoStaCounters(pAd);
+#endif // RT3070 //
 	// execute every 500ms
 	if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
 	{
@@ -919,6 +973,10 @@ VOID MlmePeriodicExec(
 		// the dynamic tuning mechanism below are based on most up-to-date information
 		NICUpdateRawCounters(pAd);
 
+#ifdef RT2870
+		RT2870_WatchDog(pAd);
+#endif // RT2870 //
+
    		// Need statistics after read counter. So put after NICUpdateRawCounters
 		ORIBATimerTimeout(pAd);
 
@@ -929,6 +987,7 @@ VOID MlmePeriodicExec(
 							 pAd->RalinkCounters.OneSecTxRetryOkCount +
 							 pAd->RalinkCounters.OneSecTxFailCount;
 
+			// dynamic adjust antenna evaluation period according to the traffic
 			if (TxTotalCnt > 50)
 			{
 				if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
@@ -950,7 +1009,9 @@ VOID MlmePeriodicExec(
 		MlmeResetRalinkCounters(pAd);
 
 		{
+#ifdef RT2860
 			if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
+#endif
 			{
 				// 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.
@@ -976,14 +1037,19 @@ VOID MlmePeriodicExec(
 		RT28XX_MLME_HANDLER(pAd);
 	}
 
-
 	pAd->bUpdateBcnCntDone = FALSE;
 }
 
 VOID STAMlmePeriodicExec(
 	PRTMP_ADAPTER pAd)
 {
+#ifdef RT2860
 	ULONG			    TxTotalCnt;
+#endif
+#ifdef RT2870
+	ULONG	TxTotalCnt;
+	int 	i;
+#endif
 
     if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
     {
@@ -992,6 +1058,7 @@ VOID STAMlmePeriodicExec(
     		pAd->StaCfg.bBlockAssoc = FALSE;
     }
 
+#ifdef RT2860
 	//Baron 2008/07/10
 	//printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
 	//If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
@@ -1004,6 +1071,7 @@ VOID STAMlmePeriodicExec(
 	{
 		pAd->StaCfg.WpaSupplicantUP = 1;
 	}
+#endif
 
     if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
 	{
@@ -1014,6 +1082,7 @@ VOID STAMlmePeriodicExec(
 		pAd->PreMediaState = pAd->IndicateMediaState;
 	}
 
+#ifdef RT2860
 	if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
         (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
 		(pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
@@ -1023,6 +1092,7 @@ VOID STAMlmePeriodicExec(
 	{
 		RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
 	}
+#endif
 
 
 
@@ -1119,6 +1189,7 @@ VOID STAMlmePeriodicExec(
 	}
 	else if (ADHOC_ON(pAd))
 	{
+#ifdef RT2860
 		// 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
 		// the "TX BEACON competition" for the entire past 1 sec.
 		// So that even when ASIC's BEACONgen engine been blocked
@@ -1159,6 +1230,7 @@ VOID STAMlmePeriodicExec(
 				pAd->StaCfg.Adhoc20NJoined = FALSE;
 			}
 		}
+#endif /* RT2860 */
 
 		//radar detect
 		if ((pAd->CommonCfg.Channel > 14)
@@ -1183,6 +1255,19 @@ VOID STAMlmePeriodicExec(
 			MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
 			pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
 		}
+
+#ifdef RT2870
+		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);
+		}
+#endif
 	}
 	else // no INFRA nor ADHOC connection
 	{
@@ -1350,10 +1435,16 @@ VOID MlmeSelectTxRateTable(
 		if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
 		{
 			if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
+#ifdef RT2860
 				!pAd->StaCfg.AdhocBOnlyJoined &&
 				!pAd->StaCfg.AdhocBGJoined &&
 				(pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
 				((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
+#endif
+#ifdef RT2870
+				(pEntry->HTCapability.MCSSet[0] == 0xff) &&
+				((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
+#endif
 			{// 11N 1S Adhoc
 				*ppTable = RateSwitchTable11N1S;
 				*pTableSize = RateSwitchTable11N1S[0];
@@ -1361,10 +1452,16 @@ VOID MlmeSelectTxRateTable(
 
 			}
 			else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
+#ifdef RT2860
 					!pAd->StaCfg.AdhocBOnlyJoined &&
 					!pAd->StaCfg.AdhocBGJoined &&
 					(pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
 					(pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
+#endif
+#ifdef RT2870
+					(pEntry->HTCapability.MCSSet[0] == 0xff) &&
+					(pEntry->HTCapability.MCSSet[1] == 0xff) &&
+#endif
 					(pAd->Antenna.field.TxPath == 2))
 			{// 11N 2S Adhoc
 				if (pAd->LatchRfRegs.Channel <= 14)
@@ -1382,6 +1479,7 @@ VOID MlmeSelectTxRateTable(
 
 			}
 			else
+#ifdef RT2860
 				if (pAd->CommonCfg.PhyMode == PHY_11B)
 			{
 				*ppTable = RateSwitchTable11B;
@@ -1390,6 +1488,12 @@ VOID MlmeSelectTxRateTable(
 
 			}
 	        else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
+#endif
+#ifdef RT2870
+				if ((pEntry->RateLen == 4)
+					&& (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
+					)
+#endif
 			{
 				// USe B Table when Only b-only Station in my IBSS .
 				*ppTable = RateSwitchTable11B;
@@ -1473,7 +1577,10 @@ VOID MlmeSelectTxRateTable(
 
 		//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)
+#ifndef RT30xx
+//Iverson mark for Adhoc b mode,sta will use rate 54  Mbps when connect with sta b/g/n mode
 			&& (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
+#endif
 			)
 		{// B only AP
 			*ppTable = RateSwitchTable11B;
@@ -1934,7 +2041,15 @@ VOID MlmeDynamicTxRateSwitching(
 
 		if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
 		{
+#ifdef RT2860
 			Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
+#endif
+#ifdef RT2870
+			Rssi = RTMPMaxRssi(pAd,
+							   pAd->StaCfg.RssiSample.AvgRssi0,
+							   pAd->StaCfg.RssiSample.AvgRssi1,
+							   pAd->StaCfg.RssiSample.AvgRssi2);
+#endif
 
 			// Update statistic counter
 			RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
@@ -1964,7 +2079,21 @@ VOID MlmeDynamicTxRateSwitching(
 		}
 		else
 		{
+#ifdef RT2860
 			Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
+#endif
+#ifdef RT2870
+			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);
+#endif
 
 			TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
 				 pEntry->OneSecTxRetryOkCount +
@@ -2388,7 +2517,12 @@ VOID StaQuickResponeForRateUpExec(
 	UCHAR					UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
 	ULONG					TxTotalCnt;
 	ULONG					TxErrorRatio = 0;
+#ifdef RT2860
 	BOOLEAN					bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
+#endif
+#ifdef RT2870
+	BOOLEAN					bTxRateChanged; //, bUpgradeQuality = FALSE;
+#endif
 	PRTMP_TX_RATE_SWITCH	pCurrTxRate, pNextTxRate = NULL;
 	PUCHAR					pTable;
 	UCHAR					TableSize = 0;
@@ -2413,11 +2547,25 @@ VOID StaQuickResponeForRateUpExec(
 		if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
 			continue;
 
+#ifdef RT2860
 		//Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
 	    if (pAd->Antenna.field.TxPath > 1)
 			Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
 		else
 			Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
+#endif
+#ifdef RT2870
+		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);
+#endif
 
 		CurrRateIdx = pAd->CommonCfg.TxRateIndex;
 
@@ -2557,6 +2705,9 @@ VOID StaQuickResponeForRateUpExec(
 			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);
+#ifdef RT2870
+			bTxRateChanged = TRUE;
+#endif
 		}
 		// if rate-down happen, only clear DownRate's bad history
 		else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
@@ -2566,6 +2717,9 @@ VOID StaQuickResponeForRateUpExec(
 			pAd->DrsCounters.TxRateUpPenalty = 0;           // no penalty
 			pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
 			pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
+#ifdef RT2870
+			bTxRateChanged = TRUE;
+#endif
 		}
 		else
 		{
@@ -2621,7 +2775,13 @@ VOID MlmeCheckPsmChange(
 	if (INFRA_ON(pAd) &&
 		(PowerMode != Ndis802_11PowerModeCAM) &&
 		(pAd->StaCfg.Psm == PWR_ACTIVE) &&
+#ifdef RT2860
 		RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
+#endif
+#if !defined(RT2860) && !defined(RT30xx)
+		(pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
+#endif
+#ifndef RT30xx
 	{
 		NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
 		pAd->RalinkCounters.RxCountSinceLastNULL = 0;
@@ -2635,6 +2795,42 @@ VOID MlmeCheckPsmChange(
 			RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
 		}
 	}
+#endif
+#ifdef RT30xx
+//		(! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+		(pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
+		(pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
+		(pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
+	{
+		// add by johnli, use Rx OK data count per second to calculate throughput
+		// If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
+		// Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
+		if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
+/* Iverson mark
+				(pAd->StaCfg.HTPhyMode.field.MODE <= MODE_OFDM) &&
+*/
+				(pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
+			((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
+/* Iverson mark
+			(pAd->StaCfg.HTPhyMode.field.MODE > MODE_OFDM) &&
+*/
+			(pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
+		{
+				// Get this time
+			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);
+			}
+		}
+	}
+#endif
 }
 
 // IRQL = PASSIVE_LEVEL
@@ -2649,7 +2845,9 @@ VOID MlmeSetPsmBit(
 	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);
+#ifndef RT30xx
 	DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
+#endif
 }
 
 // IRQL = DISPATCH_LEVEL
@@ -3679,9 +3877,18 @@ ULONG BssTableSetEntry(
 	}
 	else
 	{
+#ifdef RT30xx
+		/* avoid  Hidden SSID form beacon to overwirite correct SSID from probe response */
+		if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
+			(NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
+		{
+#endif
 		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);
+#ifdef RT30xx
+		}
+#endif
 	}
 
 	return Idx;
@@ -3742,9 +3949,14 @@ VOID BssTableSsidSort(
 							continue;
 
 					// check group cipher
+#ifndef RT30xx
 					if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
 						(pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
 						(pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
+#endif
+#ifdef RT30xx
+					if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
+#endif
 						continue;
 
 					// check pairwise cipher, skip if none matched
@@ -3763,9 +3975,14 @@ VOID BssTableSsidSort(
 							continue;
 
 					// check group cipher
+#ifndef RT30xx
 					if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
 						(pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
 						(pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
+#endif
+#ifdef RT30xx
+					if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
+#endif
 						continue;
 
 					// check pairwise cipher, skip if none matched
@@ -4043,10 +4260,16 @@ VOID BssCipherParse(
 				switch (*pTmp)
 				{
 					case 1:
+#ifndef RT30xx
 						pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
 						break;
 					case 5:
 						pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
+#endif
+#ifdef RT30xx
+					case 5:	// Although WEP is not allowed in WPA related auth mode, we parse it anyway
+						pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
+#endif
 						break;
 					case 2:
 						pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
@@ -4133,7 +4356,6 @@ VOID BssCipherParse(
 					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;
 				}
@@ -4163,10 +4385,16 @@ VOID BssCipherParse(
 				switch (pCipher->Type)
 				{
 					case 1:
+#ifndef RT30xx
 						pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
 						break;
 					case 5:
 						pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
+#endif
+#ifdef RT30xx
+					case 5:	// Although WEP is not allowed in WPA related auth mode, we parse it anyway
+						pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
+#endif
 						break;
 					case 2:
 						pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
@@ -4260,7 +4488,6 @@ VOID BssCipherParse(
 					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;
 				}
@@ -4619,11 +4846,14 @@ BOOLEAN MlmeDequeue(
 VOID	MlmeRestartStateMachine(
 	IN	PRTMP_ADAPTER	pAd)
 {
+#ifdef RT2860
 	MLME_QUEUE_ELEM		*Elem = NULL;
+#endif
 	BOOLEAN				Cancelled;
 
 	DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
 
+#ifdef RT2860
 	NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
 	if(pAd->Mlme.bRunning)
 	{
@@ -4651,6 +4881,7 @@ VOID	MlmeRestartStateMachine(
 			DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
 		}
 	}
+#endif /* RT2860 */
 
 	{
 		// Cancel all timer events
@@ -4680,10 +4911,12 @@ VOID	MlmeRestartStateMachine(
 		pAd->Mlme.ActMachine.CurrState    = ACT_IDLE;
 	}
 
+#ifdef RT2860
 	// Remove running state
 	NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
 	pAd->Mlme.bRunning = FALSE;
 	NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+#endif
 }
 
 /*! \brief	test if the MLME Queue is empty
@@ -5402,6 +5635,276 @@ VOID 	AsicUpdateProtect(
 	}
 }
 
+#ifdef RT30xx
+/*
+	========================================================================
+
+	Routine Description: Write RT30xx 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
+	{
+		RTMP_IO_READ32(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;
+
+	RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
+
+	return STATUS_SUCCESS;
+}
+
+
+/*
+	========================================================================
+
+	Routine Description: Read RT30xx 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=0;
+
+	for (i=0; i<MAX_BUSY_COUNT; i++)
+	{
+		RTMP_IO_READ32(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;
+		RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
+		for (k=0; k<MAX_BUSY_COUNT; k++)
+		{
+			RTMP_IO_READ32(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, i[%d], k[%d]\n", RegID, rfcsr.word,i,k));
+		return STATUS_UNSUCCESSFUL;
+	}
+
+	return STATUS_SUCCESS;
+}
+#endif // RT30xx //
+
+#ifdef RT30xx
+// add by johnli, RF power sequence setup
+/*
+	==========================================================================
+	Description:
+
+	Load RF normal operation-mode setup
+
+	==========================================================================
+ */
+VOID RT30xxLoadRFNormalModeSetup(
+	IN PRTMP_ADAPTER 	pAd)
+{
+	UCHAR RFValue;
+
+	// RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1
+	RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
+	RFValue = (RFValue & (~0x0C)) | 0x31;
+	RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
+
+	// TX_LO2_en, RF R15 register Bit 3 to 0
+	RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
+	RFValue &= (~0x08);
+	RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
+
+	// TX_LO1_en, RF R17 register Bit 3 to 0
+	RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
+	RFValue &= (~0x08);
+	// to fix rx long range issue
+	if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
+	{
+		RFValue |= 0x20;
+	}
+	RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
+
+	// RX_LO1_en, RF R20 register Bit 3 to 0
+	RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
+	RFValue &= (~0x08);
+	RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
+
+	// RX_LO2_en, RF R21 register Bit 3 to 0
+	RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
+	RFValue &= (~0x08);
+	RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
+
+	// LDORF_VC, RF R27 register Bit 2 to 0
+	RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
+	if ((pAd->MACVersion & 0xffff) < 0x0211)
+		RFValue = (RFValue & (~0x77)) | 0x3;
+	else
+		RFValue = (RFValue & (~0x77));
+	RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
+	/* end johnli */
+}
+
+/*
+	==========================================================================
+	Description:
+
+	Load RF sleep-mode setup
+
+	==========================================================================
+ */
+VOID RT30xxLoadRFSleepModeSetup(
+	IN PRTMP_ADAPTER 	pAd)
+{
+	UCHAR RFValue;
+	UINT32 MACValue;
+
+	// RF_BLOCK_en. RF R1 register Bit 0 to 0
+	RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
+	RFValue &= (~0x01);
+	RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
+
+	// VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
+	RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
+	RFValue &= (~0x30);
+	RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
+
+	// Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
+	RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
+	RFValue &= (~0x0E);
+	RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
+
+	// RX_CTB_en, RF R21 register Bit 7 to 0
+	RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
+	RFValue &= (~0x80);
+	RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
+
+	// LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
+	RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
+	RFValue |= 0x77;
+	RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
+
+	RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
+	MACValue |= 0x1D000000;
+	RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
+}
+
+/*
+	==========================================================================
+	Description:
+
+	Reverse RF sleep-mode setup
+
+	==========================================================================
+ */
+VOID RT30xxReverseRFSleepModeSetup(
+	IN PRTMP_ADAPTER 	pAd)
+{
+	UCHAR RFValue;
+	UINT32 MACValue;
+
+	// RF_BLOCK_en, RF R1 register Bit 0 to 1
+	RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
+	RFValue |= 0x01;
+	RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
+
+	// VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
+	RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
+	RFValue |= 0x30;
+	RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
+
+	// Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
+	RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
+	RFValue |= 0x0E;
+	RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
+
+	// RX_CTB_en, RF R21 register Bit 7 to 1
+	RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
+	RFValue |= 0x80;
+	RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
+
+	// LDORF_VC, RF R27 register Bit 2 to 0
+	RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
+	if ((pAd->MACVersion & 0xffff) < 0x0211)
+		RFValue = (RFValue & (~0x77)) | 0x3;
+	else
+		RFValue = (RFValue & (~0x77));
+	RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
+
+	// RT3071 version E has fixed this issue
+	if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
+	{
+		// patch tx EVM issue temporarily
+		RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
+		MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
+		RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
+	}
+	else
+	{
+		RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
+		MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
+		RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
+	}
+}
+// end johnli
+#endif // RT30xx //
+
 /*
 	==========================================================================
 	Description:
@@ -5423,6 +5926,21 @@ VOID AsicSwitchChannel(
 	RTMP_RF_REGS *RFRegTable;
 
 	// Search Tx power value
+#ifdef RT30xx
+	// We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
+	// in ChannelList, so use TxPower array instead.
+	//
+	for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
+	{
+		if (Channel == pAd->TxPower[index].Channel)
+	{
+			TxPwer = pAd->TxPower[index].Power;
+			TxPwer2 = pAd->TxPower[index].Power2;
+			break;
+		}
+	}
+#endif
+#ifndef RT30xx
 	for (index = 0; index < pAd->ChannelListNum; index++)
 	{
 		if (Channel == pAd->ChannelList[index].Channel)
@@ -5432,12 +5950,152 @@ VOID AsicSwitchChannel(
 			break;
 		}
 	}
+#endif
 
 	if (index == MAX_NUM_OF_CHANNELS)
 	{
+#ifndef RT30xx
 		DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
+#endif
+#ifdef RT30xx
+		DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
+#endif
 	}
 
+#ifdef RT2870
+	// The RF programming sequence is difference between 3xxx and 2xxx
+#ifdef RT30xx
+	if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
+		(pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
+#endif
+#ifndef RT30xx
+	if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
+#endif
+	{
+		/* 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);
+
+#ifndef RT30xx
+				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);
+#endif
+#ifdef RT30xx
+				RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
+				RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
+				RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
+
+				// Set Tx0 Power
+				RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
+				RFValue = (RFValue & 0xE0) | TxPwer;
+				RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
+
+				// Set Tx1 Power
+				RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
+				RFValue = (RFValue & 0xE0) | TxPwer2;
+				RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
+
+				// Tx/Rx Stream setting
+				RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
+				//if (IS_RT3090(pAd))
+				//	RFValue |= 0x01; // Enable RF block.
+				RFValue &= 0x03;	//clear bit[7~2]
+				if (pAd->Antenna.field.TxPath == 1)
+					RFValue |= 0xA0;
+				else if (pAd->Antenna.field.TxPath == 2)
+					RFValue |= 0x80;
+				if (pAd->Antenna.field.RxPath == 1)
+					RFValue |= 0x50;
+				else if (pAd->Antenna.field.RxPath == 2)
+					RFValue |= 0x40;
+				RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
+
+				// Set RF offset
+				RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
+				RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
+				RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
+#endif
+
+				// Set BW
+				if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
+				{
+					RFValue = pAd->Mlme.CaliBW40RfR24;
+					//DISABLE_11N_CHECK(pAd);
+				}
+				else
+				{
+					RFValue = pAd->Mlme.CaliBW20RfR24;
+				}
+#ifndef RT30xx
+				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;
+#endif
+#ifdef RT30xx
+				RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
+				RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
+
+				// Enable RF tuning
+				RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
+				RFValue = RFValue | 0x1;
+				RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
+
+				// latch channel for future usage.
+				pAd->LatchRfRegs.Channel = Channel;
+
+				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));
+#endif
+
+				break;
+			}
+		}
+
+#ifndef RT30xx
+		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));
+#endif
+	}
+	else
+#endif // RT2870 //
 	{
 		RFRegTable = RF2850RegTable;
 
@@ -5691,6 +6349,53 @@ VOID	AsicAntennaSelect(
 	IN	PRTMP_ADAPTER	pAd,
 	IN	UCHAR			Channel)
 {
+#ifdef RT30xx
+			if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
+			{
+				// patch for AsicSetRxAnt failed
+				pAd->RxAnt.EvaluatePeriod = 0;
+
+				// check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
+				// valid indication of the distance between this AP and its clients.
+				if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+				{
+					SHORT	realavgrssi1;
+
+					// if no traffic then reset average rssi to trigger evaluation
+					if (pAd->StaCfg.NumOfAvgRssiSample < 5)
+					{
+						pAd->RxAnt.Pair1LastAvgRssi = (-99);
+						pAd->RxAnt.Pair2LastAvgRssi = (-99);
+						DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
+					}
+
+					pAd->StaCfg.NumOfAvgRssiSample = 0;
+					realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
+
+					DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
+
+					// if the difference between two rssi is larger or less than 5, then evaluate the other antenna
+					if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
+					{
+						pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
+						AsicEvaluateRxAnt(pAd);
+					}
+				}
+				else
+				{
+					// if not connected, always switch antenna to try to connect
+					UCHAR	temp;
+
+					temp = pAd->RxAnt.Pair1PrimaryRxAnt;
+					pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
+					pAd->RxAnt.Pair1SecondaryRxAnt = temp;
+
+					DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
+
+					AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
+				}
+			}
+#endif /* RT30xx */
 }
 
 /*
@@ -5760,11 +6465,13 @@ VOID AsicAdjustTxPower(
 	ULONG		TxPwr[5];
 	CHAR		Value;
 
+#ifdef RT2860
 	if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
 		|| (pAd->bPCIclkOff == TRUE)
 		|| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
 		|| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
 		return;
+#endif
 
 	if (pAd->CommonCfg.BBPCurrentBW == BW_40)
 	{
@@ -6020,10 +6727,20 @@ VOID AsicForceSleep(
  */
 VOID AsicForceWakeup(
 	IN PRTMP_ADAPTER pAd,
+#ifdef RT2860
 	IN UCHAR    	 Level)
+#endif
+#ifdef RT2870
+	IN BOOLEAN    bFromTx)
+#endif
 {
     DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
+#ifdef RT2860
     RT28XX_STA_FORCE_WAKEUP(pAd, Level);
+#endif
+#ifdef RT2870
+    RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
+#endif
 }
 
 /*
@@ -6234,6 +6951,7 @@ VOID AsicEnableIbssSync(
 	csr9.field.bTsfTicking = 0;
 	RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
 
+#ifdef RT2860
 	// move BEACON TXD and frame content to on-chip memory
 	ptr = (PUCHAR)&pAd->BeaconTxWI;
 	for (i=0; i<TXWI_SIZE; i+=4)  // 16-byte TXWI field
@@ -6251,6 +6969,24 @@ VOID AsicEnableIbssSync(
 		RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
 		ptr +=4;
 	}
+#endif
+#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
+	{
+		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)
+	{
+		RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
+		ptr +=2;
+	}
+#endif // RT2870 //
 
 	// start sending BEACON
 	csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
@@ -6406,13 +7142,21 @@ VOID AsicSetEdcaParm(
 				Ac2Cfg.field.Aifsn -= 1;
 
 			// Tuning for TGn Wi-Fi 5.2.32
-			// STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
+			// STA TestBed changes in this item: connexant 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;
 			}
+
+#ifdef RT30xx
+			if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
+			{
+				// Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
+				Ac2Cfg.field.Aifsn = 5;
+			}
+#endif // RT30xx //
 		}
 
 		Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
@@ -6479,16 +7223,24 @@ VOID AsicSetEdcaParm(
 				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
+			// STA TestBed changes in this item: connexant 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;
 			}
+#ifdef RT2870
+			if (INFRA_ON(pAd))
+				CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
+#endif
 		}
 
 		AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
+#ifdef RT30xx
+		if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
+			AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
+#endif // RT30xx //
 
 		RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
 
@@ -6551,6 +7303,7 @@ VOID 	AsicSetSlotTime(
 	SlotTime = (bUseShortSlotTime)? 9 : 20;
 
 	{
+#ifndef RT30xx
 		// 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)))
 			|| ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
@@ -6560,6 +7313,10 @@ VOID 	AsicSetSlotTime(
 			// And we will not set to short slot when bEnableTxBurst is TRUE.
 		}
 		else if (pAd->CommonCfg.bEnableTxBurst)
+#endif
+#ifdef RT30xx
+		if (pAd->CommonCfg.bEnableTxBurst)
+#endif
 			SlotTime = 9;
 	}
 
@@ -6600,7 +7357,9 @@ VOID AsicAddSharedKeyEntry(
 {
 	ULONG offset; //, csr0;
 	SHAREDKEY_MODE_STRUC csr1;
+#ifdef RT2860
 	INT   i;
+#endif
 
 	DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
 //============================================================================================
@@ -6622,28 +7381,43 @@ VOID AsicAddSharedKeyEntry(
 	//
 	// fill key material - key + TX MIC + RX MIC
 	//
+
 	offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
+#ifdef RT2860
 	for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
 	{
 		RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
 	}
-
+#endif
+#ifdef RT2870
+	RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
+#endif
 	offset += MAX_LEN_OF_SHARE_KEY;
 	if (pTxMic)
 	{
+#ifdef RT2860
 		for (i=0; i<8; i++)
 		{
 			RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
 		}
+#endif
+#ifdef RT2870
+		RTUSBMultiWrite(pAd, offset, pTxMic, 8);
+#endif
 	}
 
 	offset += 8;
 	if (pRxMic)
 	{
+#ifdef RT2860
 		for (i=0; i<8; i++)
 		{
 			RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
 		}
+#endif
+#ifdef RT2870
+		RTUSBMultiWrite(pAd, offset, pRxMic, 8);
+#endif
 	}
 
 
@@ -6819,7 +7593,9 @@ VOID AsicAddKeyEntry(
 	PUCHAR		pTxtsc = pCipherKey->TxTsc;
 	UCHAR		CipherAlg = pCipherKey->CipherAlg;
 	SHAREDKEY_MODE_STRUC csr1;
+#ifdef RT2860
 	UCHAR		i;
+#endif
 
 	DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
 	//
@@ -6834,10 +7610,15 @@ VOID AsicAddKeyEntry(
 	// 2.) Set Key to Asic
 	//
 	//for (i = 0; i < KeyLen; i++)
+#ifdef RT2860
 	for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
 	{
 		RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
 	}
+#endif
+#ifdef RT2870
+	RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
+#endif
 	offset += MAX_LEN_OF_PEER_KEY;
 
 	//
@@ -6845,19 +7626,29 @@ VOID AsicAddKeyEntry(
 	//
 	if (pTxMic)
 	{
+#ifdef RT2860
 		for (i = 0; i < 8; i++)
 		{
 			RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
 		}
+#endif
+#ifdef RT2870
+		RTUSBMultiWrite(pAd, offset, pTxMic, 8);
+#endif
 	}
 	offset += LEN_TKIP_TXMICK;
 
 	if (pRxMic)
 	{
+#ifdef RT2860
 		for (i = 0; i < 8; i++)
 		{
 			RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
 		}
+#endif
+#ifdef RT2870
+		RTUSBMultiWrite(pAd, offset, pRxMic, 8);
+#endif
 	}
 
 
@@ -6867,6 +7658,7 @@ VOID AsicAddKeyEntry(
 	//
 	if (bTxKey)
 	{
+#ifdef RT2860
 		offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
 		//
 		// Write IV
@@ -6890,6 +7682,26 @@ VOID AsicAddKeyEntry(
 			RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
 		}
 
+#endif
+#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);
 	}
 
@@ -6954,10 +7766,15 @@ VOID AsicAddPairwiseKeyEntry(
 
 	// EKEY
 	offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
+#ifdef RT2860
 	for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
 	{
 		RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
 	}
+#endif
+#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;
@@ -6969,18 +7786,28 @@ VOID AsicAddPairwiseKeyEntry(
 	//  MIC KEY
 	if (pTxMic)
 	{
+#ifdef RT2860
 		for (i=0; i<8; i++)
 		{
 			RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
 		}
+#endif
+#ifdef RT2870
+		RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
+#endif // RT2870 //
 	}
 	offset += 8;
 	if (pRxMic)
 	{
+#ifdef RT2860
 		for (i=0; i<8; i++)
 		{
 			RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
 		}
+#endif
+#ifdef RT2870
+		RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
+#endif // RT2870 //
 	}
 
 	DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
@@ -7042,6 +7869,7 @@ BOOLEAN AsicSendCommandToMcu(
 	if (i >= 100)
 	{
 		{
+#ifdef RT2860
 			UINT32 Data;
 
 			// Reset DMA
@@ -7063,9 +7891,13 @@ BOOLEAN AsicSendCommandToMcu(
 			RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
 			Data &= 0xfffffffd;
 			RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
+#endif /* RT2860 */
 		DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
 		}
 		//return FALSE;
+#ifdef RT2870
+		return FALSE;
+#endif
 	}
 
 	H2MMailbox.field.Owner	  = 1;	   // pass ownership to MCU
@@ -7085,6 +7917,7 @@ BOOLEAN AsicSendCommandToMcu(
 	return TRUE;
 }
 
+#ifdef RT2860
 BOOLEAN AsicCheckCommanOk(
 	IN PRTMP_ADAPTER pAd,
 	IN UCHAR		 Command)
@@ -7149,6 +7982,7 @@ BOOLEAN AsicCheckCommanOk(
 
 	return FALSE;
 }
+#endif /* RT8260 */
 
 /*
 	========================================================================
@@ -7497,6 +8331,58 @@ CHAR RTMPMaxRssi(
 	return larger;
 }
 
+#ifdef RT30xx
+// Antenna divesity use GPIO3 and EESK pin for control
+// Antenna and EEPROM access are both using EESK pin,
+// Therefor we should avoid accessing EESK at the same time
+// Then restore antenna after EEPROM access
+VOID AsicSetRxAnt(
+	IN PRTMP_ADAPTER	pAd,
+	IN UCHAR			Ant)
+{
+#ifdef RT30xx
+	UINT32	Value;
+	UINT32	x;
+
+	if ((pAd->EepromAccess)										||
+		(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;
+	}
+
+	// the antenna selection is through firmware and MAC register(GPIO3)
+	if (Ant == 0)
+	{
+		// Main antenna
+		RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+		x |= (EESK);
+		RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+		RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
+		Value &= ~(0x0808);
+		RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
+		DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
+	}
+	else
+	{
+		// Aux antenna
+		RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+		x &= ~(EESK);
+		RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+		RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
+		Value &= ~(0x0808);
+		Value |= 0x08;
+		RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
+		DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
+	}
+#endif // RT30xx //
+}
+#endif /* RT30xx */
+
 /*
     ========================================================================
     Routine Description:
@@ -7515,6 +8401,7 @@ VOID AsicEvaluateRxAnt(
 {
 	UCHAR	BBPR3 = 0;
 
+#ifndef RT30xx
 	{
 		if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS	|
 								fRTMP_ADAPTER_HALT_IN_PROGRESS	|
@@ -7543,7 +8430,92 @@ VOID AsicEvaluateRxAnt(
 	}
 	RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
 
+#ifdef RT2860
     	pAd->StaCfg.BBPR3 = BBPR3;
+#endif
+#ifdef RT2870
+	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;
+		}
+	}
+#endif
+#endif /* RT30xx */
+#ifdef RT30xx
+	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) ||
+							OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
+#ifdef RT30xx
+							|| (pAd->EepromAccess)
+#endif // RT30xx //
+							)
+		return;
+
+
+	{
+		//if (pAd->StaCfg.Psm == PWR_SAVE)
+		//	return;
+	}
+
+	// two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
+	// one is antenna diversity:there is only one antenna can rx and tx
+	// the other is failed antenna remove:two physical antenna can rx and tx
+	if (pAd->NicConfig2.field.AntDiversity)
+	{
+		DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
+			pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
+
+		AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
+
+		pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
+		pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
+		pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
+
+		// a one-shot timer to end the evalution
+		// dynamic adjust antenna evaluation period according to the traffic
+		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+			RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
+		else
+			RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
+	}
+	else
+	{
+		if (pAd->StaCfg.Psm == PWR_SAVE)
+			return;
+
+		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);
+	}
+#endif /* RT30xx */
 
 	if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
 		)
@@ -7552,6 +8524,7 @@ VOID AsicEvaluateRxAnt(
 								pAd->RalinkCounters.OneSecTxRetryOkCount +
 								pAd->RalinkCounters.OneSecTxFailCount;
 
+			// dynamic adjust antenna evaluation period according to the traffic
 		if (TxTotalCnt > 50)
 		{
 			RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
@@ -7588,6 +8561,7 @@ VOID AsicRxAntEvalTimeout(
 	UCHAR			BBPR3 = 0;
 	CHAR			larger = -127, rssi0, rssi1, rssi2;
 
+#ifndef RT30xx
 	{
 		if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)	||
 			RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)		||
@@ -7645,8 +8619,111 @@ VOID AsicRxAntEvalTimeout(
 			BBPR3 |= (0x0);
 		}
 		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
+#ifdef RT2860
 		pAd->StaCfg.BBPR3 = BBPR3;
+#endif
 	}
+#endif /* RT30xx */
+#ifdef RT30xx
+	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS	|
+							fRTMP_ADAPTER_HALT_IN_PROGRESS	|
+							fRTMP_ADAPTER_RADIO_OFF			|
+							fRTMP_ADAPTER_NIC_NOT_EXIST) ||
+							OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
+#ifdef RT30xx
+							|| (pAd->EepromAccess)
+#endif // RT30xx //
+							)
+		return;
+
+	{
+		//if (pAd->StaCfg.Psm == PWR_SAVE)
+		//	return;
+
+		if (pAd->NicConfig2.field.AntDiversity)
+		{
+			if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
+			{
+				UCHAR			temp;
+
+				//
+				// select PrimaryRxAntPair
+				//    Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
+				//    Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
+				//
+				temp = pAd->RxAnt.Pair1PrimaryRxAnt;
+				pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
+				pAd->RxAnt.Pair1SecondaryRxAnt = temp;
+
+				pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
+				pAd->RxAnt.EvaluateStableCnt = 0;
+			}
+			else
+			{
+				// if the evaluated antenna is not better than original, switch back to original antenna
+				AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
+				pAd->RxAnt.EvaluateStableCnt ++;
+			}
+
+			pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
+
+			DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
+					pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
+		}
+		else
+		{
+			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 /* RT30xx */
 }
 
 
@@ -7845,7 +8922,12 @@ VOID AsicStaBbpTuning(
 		&& (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
 			)
 		&& !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+#ifdef RT2860
 		&& (pAd->bPCIclkOff == FALSE))
+#endif
+#ifdef RT2870
+		)
+#endif
 	{
 		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
 		R66 = OrigR66Value;
@@ -7857,6 +8939,45 @@ VOID AsicStaBbpTuning(
 
 		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
+#ifndef RT30xx
+			if (IS_RT3070(pAd))
+#endif
+#ifdef RT30xx
+			if (IS_RT30xx(pAd))
+#endif
+			{
+				if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
+				{
+					R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
+					if (OrigR66Value != R66)
+					{
+#ifndef RT30xx
+						RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
+#endif
+#ifdef RT30xx
+						RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+#endif
+					}
+				}
+				else
+				{
+					R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
+					if (OrigR66Value != R66)
+					{
+#ifndef RT30xx
+						RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
+#endif
+#ifdef RT30xx
+						RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+#endif
+					}
+				}
+			}
+			else
+#endif // RT2870 //
 			{
 				if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
 				{
@@ -7922,6 +9043,7 @@ VOID AsicStaBbpTuning(
 	}
 }
 
+#ifdef RT2860
 VOID AsicResetFromDMABusy(
 	IN PRTMP_ADAPTER pAd)
 {
@@ -8021,6 +9143,7 @@ VOID AsicResetPBF(
 		DBGPRINT(RT_DEBUG_TRACE, ("<---  Asic HardReset PBF !!!! \n"));
 	}
 }
+#endif /* RT2860 */
 
 VOID RTMPSetAGCInitValue(
 	IN PRTMP_ADAPTER	pAd,
@@ -8059,6 +9182,15 @@ VOID AsicTurnOffRFClk(
 	UCHAR			index;
 	RTMP_RF_REGS	*RFRegTable;
 
+#ifdef RT30xx
+	// The RF programming sequence is difference between 3xxx and 2xxx
+	if (IS_RT3090(pAd))
+	{
+		RT30xxLoadRFSleepModeSetup(pAd);  // add by johnli,  RF power sequence setup, load RF sleep-mode setup
+	}
+	else
+	{
+#endif // RT30xx //
 	RFRegTable = RF2850RegTable;
 
 	switch (pAd->RfIcType)
@@ -8100,6 +9232,10 @@ VOID AsicTurnOffRFClk(
 		default:
 			break;
 	}
+#ifdef RT30xx
+	}
+#endif // RT30xx //
+
 }
 
 
@@ -8113,6 +9249,14 @@ VOID AsicTurnOnRFClk(
 	UCHAR			index;
 	RTMP_RF_REGS	*RFRegTable;
 
+#ifdef RT30xx
+	// The RF programming sequence is difference between 3xxx and 2xxx
+	if (IS_RT3090(pAd))
+	{
+	}
+	else
+	{
+#endif // RT30xx //
 	RFRegTable = RF2850RegTable;
 
 	switch (pAd->RfIcType)
@@ -8159,9 +9303,14 @@ VOID AsicTurnOnRFClk(
 			break;
 	}
 
+#ifndef RT30xx
 	DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
 		Channel,
 		pAd->RfIcType,
 		R2));
+#endif
+#ifdef RT30xx
+	}
+#endif // RT30xx //
 }
 
diff --git a/drivers/staging/rt2860/common/rtmp_init.c b/drivers/staging/rt2860/common/rtmp_init.c
index d79877e..c2facac 100644
--- a/drivers/staging/rt2860/common/rtmp_init.c
+++ b/drivers/staging/rt2860/common/rtmp_init.c
@@ -38,8 +38,18 @@
     Jan Lee  2006-09-15    RT2860. Change for 802.11n , EEPROM, Led, BA, HT.
 */
 #include "../rt_config.h"
-#include 	"firmware.h"
+#ifndef RT30xx
+#ifdef RT2860
+#include "firmware.h"
 #include <linux/bitrev.h>
+#endif
+#ifdef RT2870
+#include "../../rt2870/common/firmware.h"
+#endif
+#endif
+#ifdef RT30xx
+#include "../../rt3070/firmware.h"
+#endif
 
 UCHAR    BIT8[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
 ULONG    BIT32[] = {0x00000001, 0x00000002, 0x00000004, 0x00000008,
@@ -90,6 +100,22 @@ const unsigned short ccitt_16Table[] = {
 #define ByteCRC16(v, crc) \
 	(unsigned short)((crc << 8) ^  ccitt_16Table[((crc >> 8) ^ (v)) & 255])
 
+#ifdef RT2870
+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;
+}
+#endif
+
 //
 // BBP register initialization set
 //
@@ -114,6 +140,38 @@ REG_PAIR   BBPRegTable[] = {
 //
 // 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},
+#ifndef RT30xx
+        {RF_R10,          0x71},
+#endif
+#ifdef RT30xx
+        {RF_R10,          0x41},
+#endif
+        {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},
+#ifndef RT30xx
+        {RF_R27,          0x03},
+#endif
+        {RF_R29,          0x1F},
+};
+#define	NUM_RF_REG_PARMS	(sizeof(RT30xx_RFRegTable) / sizeof(REG_PAIR))
+#endif // RT2870 //
 
 //
 // ASIC register initialization sets
@@ -146,10 +204,18 @@ RTMP_REG_PAIR	MACRegTable[] =	{
 	{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.
+//PS packets use Tx1Q (for HCCA) when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
+#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},
+#ifdef RT2860
 	{MM40_PROT_CFG,			0x03F54084},
+#endif
 	{TXOP_CTRL_CFG,			0x0000583f, /*0x0000243f*/ /*0x000024bf*/},	//Extension channel backoff.
 	{TX_RTS_CFG,			0x00092b20},
 	{EXP_ACK_TIME,			0x002400ca},	// default value
@@ -172,6 +238,13 @@ RTMP_REG_PAIR	STAMACRegTable[] =	{
 #define	NUM_MAC_REG_PARMS		(sizeof(MACRegTable) / sizeof(RTMP_REG_PAIR))
 #define	NUM_STA_MAC_REG_PARMS	(sizeof(STAMACRegTable) / sizeof(RTMP_REG_PAIR))
 
+#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
@@ -181,7 +254,9 @@ RTMP_REG_PAIR	STAMACRegTable[] =	{
 #define FIRMWAREIMAGEV1_LENGTH	0x1000
 #define FIRMWAREIMAGEV2_LENGTH	0x1000
 
+#ifdef RT2860
 #define FIRMWARE_MINOR_VERSION	2
+#endif
 
 
 /*
@@ -239,7 +314,9 @@ NDIS_STATUS	RTMPAllocAdapterBlock(
 
 		// Init spin locks
 		NdisAllocateSpinLock(&pAd->MgmtRingLock);
+#ifdef RT2860
 		NdisAllocateSpinLock(&pAd->RxRingLock);
+#endif
 
 		for (index =0 ; index < NUM_OF_TX_RING; index++)
 		{
@@ -1005,6 +1082,425 @@ NDIS_STATUS	NICReadRegParameters(
 }
 
 
+#ifdef RT2870
+/*
+	========================================================================
+
+	Routine Description:
+		For RF filter calibration purpose
+
+	Arguments:
+		pAd                          Pointer to our adapter
+
+	Return Value:
+		None
+
+	IRQL = PASSIVE_LEVEL
+
+	========================================================================
+*/
+#ifndef RT30xx
+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));
+}
+#endif /* RT30xx */
+#ifdef RT30xx
+VOID RTMPFilterCalibration(
+	IN PRTMP_ADAPTER pAd)
+{
+	UCHAR	R55x = 0, value, FilterTarget = 0x1E, BBPValue=0;
+	UINT	loop = 0, count = 0, loopcnt = 0, ReTry = 0;
+	UCHAR	RF_R24_Value = 0;
+
+	// Give bbp filter initial value
+	pAd->Mlme.CaliBW20RfR24 = 0x1F;
+	pAd->Mlme.CaliBW40RfR24 = 0x2F; //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);
+			if (IS_RT3090(pAd))
+				FilterTarget = 0x15;
+			else
+				FilterTarget = 0x19;
+
+			// when calibrate BW40, BBP mask must set to BW40.
+			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);
+
+			// set to BW40
+			RT30xxReadRFRegister(pAd, RF_R31, &value);
+			value |= 0x20;
+			RT30xxWriteRFRegister(pAd, RF_R31, value);
+		}
+		else			//BandWidth = 20 MHz
+		{
+			// Write 0x07 to RF_R24 to program filter
+			RF_R24_Value = 0x07;
+			RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value);
+			if (IS_RT3090(pAd))
+				FilterTarget = 0x13;
+			else
+				FilterTarget = 0x16;
+
+			// set to BW20
+			RT30xxReadRFRegister(pAd, RF_R31, &value);
+			value &= (~0x20);
+			RT30xxWriteRFRegister(pAd, RF_R31, value);
+		}
+
+		// 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
+		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0);
+
+		do
+		{
+			// Write 0x90 to BBP_R25 to transmit test tone
+			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90);
+
+			RTMPusecDelay(1000);
+			// Read BBP_R55[6:0] for received power, set R55x = BBP_R55[6:0]
+			RTMP_BBP_IO_READ8_BY_REG_ID(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
+		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x06);
+
+		while(TRUE)
+		{
+			// Write 0x90 to BBP_R25 to transmit test tone
+			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90);
+
+			//We need to wait for calibration
+			RTMPusecDelay(1000);
+			RTMP_BBP_IO_READ8_BY_REG_ID(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, ("RTMPFilterCalibration - 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
+	//
+	RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0);
+
+	RT30xxReadRFRegister(pAd, RF_R22, &value);
+	value &= ~(0x01);
+	RT30xxWriteRFRegister(pAd, RF_R22, value);
+
+	// set BBP back to BW20
+	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, ("RTMPFilterCalibration - CaliBW20RfR24=0x%x, CaliBW40RfR24=0x%x\n", pAd->Mlme.CaliBW20RfR24, pAd->Mlme.CaliBW40RfR24));
+}
+#endif /* RT30xx */
+
+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
+#ifndef RT30xx
+        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
+#ifdef RT30xx
+	if (IS_RT3070(pAd) || IS_RT3071(pAd))
+	{
+		// Init RF calibration
+		// Driver should toggle RF R30 bit7 before init RF registers
+		UINT32 RfReg = 0;
+		UINT32 data;
+
+		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);
+		}
+
+		// add by johnli
+		if (IS_RT3070(pAd))
+		{
+			//  Update MAC 0x05D4 from 01xxxxxx to 0Dxxxxxx (voltage 1.2V to 1.35V) for RT3070 to improve yield rate
+			RTUSBReadMACRegister(pAd, LDO_CFG0, &data);
+			data = ((data & 0xF0FFFFFF) | 0x0D000000);
+			RTUSBWriteMACRegister(pAd, LDO_CFG0, data);
+		}
+		else if (IS_RT3071(pAd))
+		{
+			// Driver should set RF R6 bit6 on before init RF registers
+			RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RfReg);
+			RfReg |= 0x40;
+			RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RfReg);
+
+			// init R31
+			RT30xxWriteRFRegister(pAd, RF_R31, 0x14);
+
+			// RT3071 version E has fixed this issue
+			if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
+			{
+				// patch tx EVM issue temporarily
+				RTUSBReadMACRegister(pAd, LDO_CFG0, &data);
+				data = ((data & 0xE0FFFFFF) | 0x0D000000);
+				RTUSBWriteMACRegister(pAd, LDO_CFG0, data);
+			}
+			else
+			{
+				RTMP_IO_READ32(pAd, LDO_CFG0, &data);
+				data = ((data & 0xE0FFFFFF) | 0x01000000);
+				RTMP_IO_WRITE32(pAd, LDO_CFG0, data);
+			}
+
+			// patch LNA_PE_G1 failed issue
+			RTUSBReadMACRegister(pAd, GPIO_SWITCH, &data);
+			data &= ~(0x20);
+			RTUSBWriteMACRegister(pAd, GPIO_SWITCH, data);
+		}
+
+		//For RF filter Calibration
+		RTMPFilterCalibration(pAd);
+
+		// Initialize RF R27 register, set RF R27 must be behind RTMPFilterCalibration()
+		if ((pAd->MACVersion & 0xffff) < 0x0211)
+			RT30xxWriteRFRegister(pAd, RF_R27, 0x3);
+
+		// set led open drain enable
+		RTUSBReadMACRegister(pAd, OPT_14, &data);
+		data |= 0x01;
+		RTUSBWriteMACRegister(pAd, OPT_14, data);
+
+		if (IS_RT3071(pAd))
+		{
+			// add by johnli, RF power sequence setup, load RF normal operation-mode setup
+			RT30xxLoadRFNormalModeSetup(pAd);
+		}
+	}
+#endif
+}
+#endif // RT2870 //
 
 
 /*
@@ -1179,11 +1675,25 @@ VOID	NICReadEEPROMParameters(
 	Antenna.word = pAd->EEPROMDefaultValue[0];
 	if (Antenna.word == 0xFFFF)
 	{
+#ifdef RT30xx
+		if(IS_RT3090(pAd))
+		{
+			Antenna.word = 0;
+			Antenna.field.RfIcType = RFIC_3020;
+			Antenna.field.TxPath = 1;
+			Antenna.field.RxPath = 1;
+		}
+		else
+		{
+#endif // RT30xx //
 		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));
+#ifdef RT30xx
+		}
+#endif // RT30xx //
 	}
 
 	// Choose the desired Tx&Rx stream.
@@ -1212,7 +1722,9 @@ VOID	NICReadEEPROMParameters(
 	NicConfig2.word = pAd->EEPROMDefaultValue[1];
 
 	{
+#ifndef RT30xx
 		NicConfig2.word = 0;
+#endif
 		if ((NicConfig2.word & 0x00ff) == 0xff)
 		{
 			NicConfig2.word &= 0xff00;
@@ -1405,6 +1917,14 @@ VOID	NICReadEEPROMParameters(
 
 	RTMPReadTxPwrPerRate(pAd);
 
+#ifdef RT30xx
+	if (IS_RT30xx(pAd))
+	{
+		eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value);
+		pAd->EFuseTag = (value & 0xff);
+	}
+#endif // RT30xx //
+
 	DBGPRINT(RT_DEBUG_TRACE, ("<-- NICReadEEPROMParameters\n"));
 }
 
@@ -1449,16 +1969,49 @@ VOID	NICInitAsicFromEEPROM(
 		}
 	}
 
+#ifndef RT30xx
 	Antenna.word = pAd->Antenna.word;
+#endif
+#ifdef RT30xx
+	Antenna.word = pAd->EEPROMDefaultValue[0];
+	if (Antenna.word == 0xFFFF)
+	{
+		DBGPRINT(RT_DEBUG_ERROR, ("E2PROM error, hard code as 0x%04x\n", Antenna.word));
+		BUG_ON(Antenna.word == 0xFFFF);
+	}
+#endif
 	pAd->Mlme.RealRxPath = (UCHAR) Antenna.field.RxPath;
 	pAd->RfIcType = (UCHAR) Antenna.field.RfIcType;
 
+#ifdef RT30xx
+	DBGPRINT(RT_DEBUG_WARN, ("pAd->RfIcType = %d, RealRxPath=%d, TxPath = %d\n", pAd->RfIcType, pAd->Mlme.RealRxPath,Antenna.field.TxPath));
+
+	// Save the antenna for future use
+	pAd->Antenna.word = Antenna.word;
+#endif
 	NicConfig2.word = pAd->EEPROMDefaultValue[1];
 
+#ifdef RT30xx
+	{
+		if ((NicConfig2.word & 0x00ff) == 0xff)
+		{
+			NicConfig2.word &= 0xff00;
+		}
 
+		if ((NicConfig2.word >> 8) == 0xff)
+		{
+			NicConfig2.word &= 0x00ff;
+		}
+	}
+#endif
 	// Save the antenna for future use
 	pAd->NicConfig2.word = NicConfig2.word;
 
+#ifdef RT30xx
+	// set default antenna as main
+	if (pAd->RfIcType == RFIC_3020)
+		AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
+#endif
 	//
 	// Send LED Setting to MCU.
 	//
@@ -1467,7 +2020,13 @@ VOID	NICInitAsicFromEEPROM(
 		pAd->LedCntl.word = 0x01;
 		pAd->Led1 = 0x5555;
 		pAd->Led2 = 0x2221;
+#ifdef RT2860
 		pAd->Led3 = 0xA9F8;
+#endif
+
+#ifdef RT2870
+		pAd->Led3 = 0x5627;
+#endif // RT2870 //
 	}
 
 	AsicSendCommandToMcu(pAd, 0x52, 0xff, (UCHAR)pAd->Led1, (UCHAR)(pAd->Led1 >> 8));
@@ -1501,10 +2060,12 @@ VOID	NICInitAsicFromEEPROM(
 		else
 		{
 			RTMPSetLED(pAd, LED_RADIO_ON);
+#ifdef RT2860
 			AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
 			AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00);
 			// 2-1. wait command ok.
 			AsicCheckCommanOk(pAd, PowerWakeCID);
+#endif
 		}
 	}
 
@@ -1579,8 +2140,10 @@ NDIS_STATUS	NICInitializeAdapter(
 {
 	NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
 	WPDMA_GLO_CFG_STRUC	GloCfg;
+#ifdef RT2860
 	UINT32			Value;
 	DELAY_INT_CFG_STRUC	IntCfg;
+#endif
 	ULONG	i =0, j=0;
 	AC_TXOP_CSR0_STRUC	csr0;
 
@@ -1619,9 +2182,11 @@ retry:
 
 	// asic simulation sequence put this ahead before loading firmware.
 	// pbf hardware reset
+#ifdef RT2860
 	RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0x1003f);	// 0x10000 for reset rx, 0x3f resets all 6 tx rings.
 	RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe1f);
 	RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe00);
+#endif
 
 	// Initialze ASIC for TX & Rx operation
 	if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS)
@@ -1635,6 +2200,7 @@ retry:
 	}
 
 
+#ifdef RT2860
 	// Write AC_BK base address register
 	Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BK].Cell[0].AllocPa);
 	RTMP_IO_WRITE32(pAd, TX_BASE_PTR1, Value);
@@ -1707,6 +2273,7 @@ retry:
 	// Write RX_RING_CSR register
 	Value = RX_RING_SIZE;
 	RTMP_IO_WRITE32(pAd, RX_MAX_CNT, Value);
+#endif /* RT2860 */
 
 
 	// WMM parameter
@@ -1725,6 +2292,7 @@ retry:
 	RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr0.word);
 
 
+#ifdef RT2860
 	// 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits:
 	i = 0;
 	do
@@ -1743,6 +2311,7 @@ retry:
 
 	IntCfg.word = 0;
 	RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word);
+#endif
 
 
 	// reset action
@@ -1778,33 +2347,134 @@ NDIS_STATUS	NICInitializeAsic(
 	ULONG			Index = 0;
 	UCHAR			R0 = 0xff;
 	UINT32			MacCsr12 = 0, Counter = 0;
+#ifdef RT2870
+	UINT32			MacCsr0 = 0;
+	NTSTATUS		Status;
+	UCHAR			Value = 0xff;
+#endif // RT2870 //
+#ifdef RT30xx
+	UINT32			eFuseCtrl;
+#endif // RT30xx //
 	USHORT			KeyIdx;
 	INT				i,apidx;
 
 	DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n"));
 
+#ifdef RT2860
 	if (bHardReset == TRUE)
 	{
 		RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3);
 	}
 	else
 		RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
+#endif
+#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);
+#endif
 
 	RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
+
 	// Initialize MAC register to default value
+#ifdef RT2860
 	for (Index = 0; Index < NUM_MAC_REG_PARMS; Index++)
 	{
 		RTMP_IO_WRITE32(pAd, MACRegTable[Index].Register, MACRegTable[Index].Value);
 	}
+#endif
+#ifdef RT2870
+	for(Index=0; Index<NUM_MAC_REG_PARMS; Index++)
+	{
+#ifdef RT3070
+		if ((MACRegTable[Index].Register == TX_SW_CFG0) && (IS_RT3070(pAd) || IS_RT3071(pAd)))
+		{
+			MACRegTable[Index].Value = 0x00000400;
+		}
+#endif // RT3070 //
+		RTMP_IO_WRITE32(pAd, (USHORT)MACRegTable[Index].Register, MACRegTable[Index].Value);
+	}
+
+#ifndef RT30xx
+	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);
+	}
+#endif
+#endif // RT2870 //
 
 
 	{
 		for (Index = 0; Index < NUM_STA_MAC_REG_PARMS; Index++)
 		{
+#ifdef RT2860
 			RTMP_IO_WRITE32(pAd, STAMACRegTable[Index].Register, STAMACRegTable[Index].Value);
+#endif
+#ifdef RT2870
+			RTMP_IO_WRITE32(pAd, (USHORT)STAMACRegTable[Index].Register, STAMACRegTable[Index].Value);
+#endif
 		}
 	}
 
+#ifdef RT30xx
+	// Initialize RT3070 serial MAc registers which is different from RT2870 serial
+	if (IS_RT3090(pAd))
+	{
+		RTMP_IO_WRITE32(pAd, TX_SW_CFG1, 0);
+
+		// RT3071 version E has fixed this issue
+		if ((pAd->MACVersion & 0xffff) < 0x0211)
+		{
+			if (pAd->NicConfig2.field.DACTestBit == 1)
+			{
+				RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x1F);	// To fix throughput drop drastically
+			}
+			else
+			{
+				RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0F);	// To fix throughput drop drastically
+			}
+		}
+		else
+		{
+			RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0);
+		}
+	}
+	else if (IS_RT3070(pAd))
+	{
+		RTMP_IO_WRITE32(pAd, TX_SW_CFG1, 0);
+		RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x1F);	// To fix throughput drop drastically
+	}
+#endif // RT30xx //
+
 	//
 	// Before program BBP, we need to wait BBP/RF get wake up.
 	//
@@ -1844,11 +2514,69 @@ NDIS_STATUS	NICInitializeAsic(
 		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, BBPRegTable[Index].Value);
 	}
 
+#ifndef RT30xx
 	// 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 //
+#endif
+#ifdef RT30xx
+	// for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT.
+	// RT3090 should not program BBP R84 to 0x19, otherwise TX will block.
+	if (((pAd->MACVersion&0xffff) != 0x0101) && (!IS_RT30xx(pAd)))
+		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19);
+
+// add by johnli, RF power sequence setup
+	if (IS_RT30xx(pAd))
+	{	//update for RT3070/71/72/90/91/92.
+		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R79, 0x13);
+		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R80, 0x05);
+		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R81, 0x33);
+	}
+
+	if (IS_RT3090(pAd))
+	{
+		UCHAR		bbpreg=0;
+
+		// enable DC filter
+		if ((pAd->MACVersion & 0xffff) >= 0x0211)
+		{
+			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R103, 0xc0);
+		}
 
+		// improve power consumption
+		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R138, &bbpreg);
+		if (pAd->Antenna.field.TxPath == 1)
+		{
+			// turn off tx DAC_1
+			bbpreg = (bbpreg | 0x20);
+		}
+
+		if (pAd->Antenna.field.RxPath == 1)
+		{
+			// turn off tx ADC_1
+			bbpreg &= (~0x2);
+		}
+		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R138, bbpreg);
+
+		// improve power consumption in RT3071 Ver.E
+		if ((pAd->MACVersion & 0xffff) >= 0x0211)
+		{
+			RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R31, &bbpreg);
+			bbpreg &= (~0x3);
+			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R31, bbpreg);
+		}
+	}
+#endif
 	if (pAd->MACVersion == 0x28600100)
 	{
 		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
@@ -1865,6 +2593,18 @@ NDIS_STATUS	NICInitializeAsic(
 		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
 	{
@@ -1912,6 +2652,35 @@ NDIS_STATUS	NICInitializeAsic(
 				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 RT30xx
+	pAd->bUseEfuse=FALSE;
+	RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrl);
+	pAd->bUseEfuse = ( (eFuseCtrl & 0x80000000) == 0x80000000) ? 1 : 0;
+	if(pAd->bUseEfuse)
+	{
+			DBGPRINT(RT_DEBUG_TRACE, ("NVM is Efuse\n"));
+	}
+	else
+	{
+			DBGPRINT(RT_DEBUG_TRACE, ("NVM is EEPROM\n"));
+
+	}
+#endif // RT30xx //
 
 	{
 		// for rt2860E and after, init TXOP_CTRL_CFG with 0x583f. This is for extension channel overlapping IOT.
@@ -1924,6 +2693,7 @@ NDIS_STATUS	NICInitializeAsic(
 }
 
 
+#ifdef RT2860
 VOID NICRestoreBBPValue(
 	IN PRTMP_ADAPTER pAd)
 {
@@ -2047,6 +2817,7 @@ VOID NICRestoreBBPValue(
 
 	DBGPRINT(RT_DEBUG_TRACE, ("<---  NICRestoreBBPValue !!!!!!!!!!!!!!!!!!!!!!!  \n"));
 }
+#endif /* RT2860 */
 
 /*
 	========================================================================
@@ -2299,6 +3070,22 @@ VOID NICUpdateRawCounters(
 	// Update RX Overflow counter
 	pAd->Counters8023.RxNoBuffer += (RxStaCnt2.field.RxFifoOverflowCount);
 
+#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 (!pAd->bUpdateBcnCntDone)
 	{
 	// Update BEACON sent count
@@ -2531,9 +3318,40 @@ NDIS_STATUS NICLoadFirmware(
 	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 //
+
 	RT28XX_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength);
 
 	/* check if MCU is ready */
@@ -2799,6 +3617,31 @@ VOID	UserCfgInit(
 	//
 	//  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++)
 	{
@@ -2809,14 +3652,19 @@ VOID	UserCfgInit(
 		}
 	}
 
+#ifdef RT30xx
+	pAd->EepromAccess = FALSE;
+#endif
 	pAd->Antenna.word = 0;
 	pAd->CommonCfg.BBPCurrentBW = BW_20;
 
 	pAd->LedCntl.word = 0;
+#ifdef RT2860
 	pAd->LedIndicatorStregth = 0;
 	pAd->RLnkCtrlOffset = 0;
 	pAd->HostLnkCtrlOffset = 0;
 	pAd->CheckDmaBusyCount = 0;
+#endif
 
 	pAd->bAutoTxAgcA = FALSE;			// Default is OFF
 	pAd->bAutoTxAgcG = FALSE;			// Default is OFF
@@ -3020,9 +3868,11 @@ VOID	UserCfgInit(
 	NdisAllocateSpinLock(&pAd->MacTabLock);
 
 	pAd->CommonCfg.bWiFiTest = FALSE;
+#ifdef RT2860
 	pAd->bPCIclkOff = FALSE;
 
 	RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
+#endif
 	DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n"));
 }
 
@@ -3124,6 +3974,9 @@ VOID	RTMPInitTimer(
 	pTimer->State      = FALSE;
 	pTimer->cookie = (ULONG) pData;
 
+#ifdef RT2870
+	pTimer->pAd = pAd;
+#endif // RT2870 //
 
 	RTMP_OS_Init_Timer(pAd,	&pTimer->TimerObj,	pTimerFunc, (PVOID) pTimer);
 }
@@ -3250,6 +4103,12 @@ VOID	RTMPCancelTimer(
 		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
 	{
diff --git a/drivers/staging/rt2860/common/spectrum.c b/drivers/staging/rt2860/common/spectrum.c
index c658bf3..101c292 100644
--- a/drivers/staging/rt2860/common/spectrum.c
+++ b/drivers/staging/rt2860/common/spectrum.c
@@ -1570,7 +1570,12 @@ static VOID PeerMeasureReportAction(
 
 	if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)
 	{
+#ifndef RT30xx
 		DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%zu).\n", __func__, sizeof(MEASURE_RPI_REPORT)));
+#endif
+#ifdef RT30xx
+		DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __func__, sizeof(MEASURE_RPI_REPORT)));
+#endif
 		return;
 	}
 
-- 
1.6.3.2



[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux