summaryrefslogtreecommitdiff
path: root/cleopatre/devkit/rt5572drv/MODULE/common/cmm_data.c
diff options
context:
space:
mode:
authorFisher Cheng2012-11-30 17:41:08 +0800
committerJulien Lacour2013-10-01 11:30:32 +0200
commit1acf0f895c26837099eeaff6455152dd94fa6d53 (patch)
treef841b2c132fff301ef00d74f1e3dd8ae21341db0 /cleopatre/devkit/rt5572drv/MODULE/common/cmm_data.c
parentca15306cb8a92c9f2abfc816ef5b69545c838d9f (diff)
cleo/devkit: add Ralink RT5572 driver source code, refs #4213
Diffstat (limited to 'cleopatre/devkit/rt5572drv/MODULE/common/cmm_data.c')
-rw-r--r--cleopatre/devkit/rt5572drv/MODULE/common/cmm_data.c3765
1 files changed, 3765 insertions, 0 deletions
diff --git a/cleopatre/devkit/rt5572drv/MODULE/common/cmm_data.c b/cleopatre/devkit/rt5572drv/MODULE/common/cmm_data.c
new file mode 100644
index 0000000000..fa10d63266
--- /dev/null
+++ b/cleopatre/devkit/rt5572drv/MODULE/common/cmm_data.c
@@ -0,0 +1,3765 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ****************************************************************************
+
+ Module Name:
+ cmm_data.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+ */
+
+
+#include "rt_config.h"
+
+
+UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
+UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
+UCHAR EAPOL[] = {0x88, 0x8e};
+UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */
+
+UCHAR IPX[] = {0x81, 0x37};
+UCHAR APPLE_TALK[] = {0x80, 0xf3};
+
+UCHAR OfdmRateToRxwiMCS[12] = {
+ 0, 0, 0, 0,
+ 0, 1, 2, 3, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */
+ 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */
+};
+UCHAR RxwiMCSToOfdmRate[12] = {
+ RATE_6, RATE_9, RATE_12, RATE_18,
+ RATE_24, RATE_36, RATE_48, RATE_54, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */
+ 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */
+};
+
+UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ API for MLME to transmit management frame to AP (BSS Mode)
+ or station (IBSS Mode)
+
+ Arguments:
+ pAd Pointer to our adapter
+ pData Pointer to the outgoing 802.11 frame
+ Length Size of outgoing management frame
+
+ Return Value:
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_PENDING
+ NDIS_STATUS_SUCCESS
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS MiniportMMRequest(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PUCHAR pData,
+ IN UINT Length)
+{
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ ULONG FreeNum;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+ UCHAR rtmpHwHdr[TXINFO_SIZE + pAd->chipCap.TXWISize]; /*RTMP_HW_HDR_LEN];*/
+ BOOLEAN bUseDataQ = FALSE, FlgDataQForce = FALSE, FlgIsLocked = FALSE;
+ int retryCnt = 0;
+
+ ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
+
+ if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG)
+ {
+ bUseDataQ = TRUE;
+ QueIdx &= (~MGMT_USE_QUEUE_FLAG);
+ }
+
+
+ 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.*/
+ {
+ FreeNum = GET_MGMTRING_FREENO(pAd);
+ }
+
+ if ((FreeNum > 0))
+ {
+ /* We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870*/
+ NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWISize));
+ Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWISize), 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;*/
+#ifdef CONFIG_AP_SUPPORT
+#ifdef UAPSD_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UAPSD_MR_QOS_NULL_HANDLE(pAd, pData, pPacket);
+ }
+#endif /* UAPSD_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ Status = MlmeHardTransmit(pAd, QueIdx, pPacket, FlgDataQForce, FlgIsLocked);
+ if (Status == NDIS_STATUS_SUCCESS)
+ retryCnt = 0;
+ else
+ RELEASE_NDIS_PACKET(pAd, pPacket, Status);
+ }
+ else
+ {
+ pAd->RalinkCounters.MgmtRingFullCount++;
+ DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
+ QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
+ }
+ } while (retryCnt > 0);
+
+
+
+ return Status;
+}
+
+
+#ifdef CONFIG_AP_SUPPORT
+/*
+ ========================================================================
+
+ Routine Description:
+ Copy frame from waiting queue into relative ring buffer and set
+ appropriate ASIC register to kick hardware transmit function
+
+ Arguments:
+ pAd Pointer to our adapter
+ pBuffer Pointer to memory of outgoing frame
+ Length Size of outgoing management frame
+ FlgIsDeltsFrame 1: the frame is a DELTS frame
+
+ Return Value:
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_PENDING
+ NDIS_STATUS_SUCCESS
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+void AP_QueuePsActionPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pMacEntry,
+ IN PNDIS_PACKET pPacket,
+ IN BOOLEAN FlgIsDeltsFrame,
+ IN BOOLEAN FlgIsLocked,
+ IN UCHAR MgmtQid)
+{
+
+#ifdef UAPSD_SUPPORT
+#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY
+ PNDIS_PACKET DuplicatePkt = NULL;
+#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */
+#endif /* UAPSD_SUPPORT */
+
+ /* Note: for original mode of 4 AC are UAPSD, if station want to change
+ the mode of a AC to legacy PS, we dont know where to put the
+ response;
+ 1. send the response;
+ 2. but the station is in ps mode, so queue the response;
+ 3. we should queue the reponse to UAPSD queue because the station
+ is not yet change its mode to legacy ps AC;
+ 4. so AP should change its mode to legacy ps AC only when the station
+ sends a trigger frame and we send out the reponse;
+ 5. the mechanism is too complicate; */
+
+#ifdef UAPSD_SUPPORT
+ /*
+ If the frame is action frame and the VO is UAPSD, we can not send the
+ frame to VO queue, we need to send to legacy PS queue; or the frame
+ maybe not got from QSTA.
+ */
+/* if ((pMacEntry->bAPSDDeliverEnabledPerAC[MgmtQid]) &&*/
+/* (FlgIsDeltsFrame == 0))*/
+ if (pMacEntry->bAPSDDeliverEnabledPerAC[MgmtQid])
+ {
+ /* queue the management frame to VO queue if VO is deliver-enabled */
+ DBGPRINT(RT_DEBUG_TRACE, ("ps> mgmt to UAPSD queue %d ... (IsDelts: %d)\n",
+ MgmtQid, FlgIsDeltsFrame));
+
+#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY
+ if (!pMacEntry->bAPSDAllAC)
+ {
+ /* duplicate one packet to legacy PS queue */
+ RTMP_SET_PACKET_UAPSD(pPacket, 0, MgmtQid);
+ DuplicatePkt = RTMP_DUPLICATE_PACKET(pAd, pPacket, pMacEntry->apidx);
+ }
+ else
+#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */
+ {
+ RTMP_SET_PACKET_UAPSD(pPacket, 1, MgmtQid);
+ }
+
+ UAPSD_PacketEnqueue(pAd, pMacEntry, pPacket, MgmtQid);
+
+ if (pMacEntry->bAPSDAllAC)
+ {
+ /* mark corresponding TIM bit in outgoing BEACON frame*/
+ WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->apidx, pMacEntry->Aid);
+ }
+ else
+ {
+#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY
+ /* duplicate one packet to legacy PS queue */
+
+ /*
+ Sometimes AP will send DELTS frame to STA but STA will not
+ send any trigger frame to get the DELTS frame.
+ We must force to send it so put another one in legacy PS
+ queue.
+ */
+ if (DuplicatePkt != NULL)
+ {
+ pPacket = DuplicatePkt;
+ goto Label_Legacy_PS;
+ }
+#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */
+ }
+ }
+ else
+#endif /* UAPSD_SUPPORT */
+ {
+/* DuplicatePkt = DuplicatePacket(get_netdev_from_bssid(pAd, pMacEntry->apidx), pPacket, pMacEntry->apidx);*/
+
+#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY
+Label_Legacy_PS:
+#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */
+ if (pMacEntry->PsQueue.Number >= MAX_PACKETS_IN_PS_QUEUE)
+ {
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_RESOURCES);
+ return;
+ }
+ else
+ {
+ ULONG IrqFlags=0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ps> mgmt to legacy ps queue... (%d)\n", FlgIsDeltsFrame));
+
+ if (FlgIsLocked == FALSE)
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+ InsertTailQueue(&pMacEntry->PsQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
+ if (FlgIsLocked == FALSE)
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+ }
+
+ /* mark corresponding TIM bit in outgoing BEACON frame*/
+ WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->apidx, pMacEntry->Aid);
+ }
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Copy frame from waiting queue into relative ring buffer and set
+ appropriate ASIC register to kick hardware transmit function
+
+ Arguments:
+ pAd Pointer to our adapter
+ pBuffer Pointer to memory of outgoing frame
+ Length Size of outgoing management frame
+
+ Return Value:
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_PENDING
+ NDIS_STATUS_SUCCESS
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS MlmeHardTransmit(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket,
+ IN BOOLEAN FlgDataQForce,
+ IN BOOLEAN FlgIsLocked)
+{
+#ifdef CONFIG_AP_SUPPORT
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ PHEADER_802_11 pHeader_802_11;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+#endif /* CONFIG_AP_SUPPORT */
+ PACKET_INFO PacketInfo;
+ PUCHAR pSrcBufVA;
+ UINT SrcBufLen;
+
+ if ((pAd->Dot11_H.RDMode != RD_NORMAL_MODE)
+#ifdef CARRIER_DETECTION_SUPPORT
+#ifdef CONFIG_AP_SUPPORT
+ ||(isCarrierDetectExist(pAd) == TRUE)
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* CARRIER_DETECTION_SUPPORT */
+ )
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+ if (pSrcBufVA == NULL)
+ return NDIS_STATUS_FAILURE;
+
+#ifdef CONFIG_AP_SUPPORT
+ pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWISize);
+
+ /*
+ Section 11.2.1.1 STA Power Management modes of IEEE802.11-2007:
+ The Power Managment bit shall not be set in any management frame,
+ except an Action frame.
+
+ So in the 'baseline' test plan
+ (Wi-Fi 802.11 WPA2, WPA, WEP Interoperability Test Plan),
+ Section 2.2.6, the following Requirement:
+ APs shall ignore the power save bit in any received Authenticate and
+ (Re) Associate, and shall assume that the station is awake for the
+ response.
+ */
+
+ /*
+ IEEE802.11, 11.2.1.4 AP operation during the contention period f)
+ A single buffered MSDU or management frame for a STA in the PS mode shall
+ be forwarded to the STA after a PS-Poll has been received from that STA.
+ The More Data field shall be set to indicate the presence of further
+ buffered MSDUs or "management frames" for the polling STA.
+ */
+
+ /*
+ IEEE802.11e, 11.2.1.4 Power management with APSD,
+ An unscheduled SP ends after the QAP has attempted to transmit at least
+ one MSDU or MMPDU associated with a delivery-enabled AC and destined for
+ the non-AP QSTA, but no more than the number indicated in the Max SP
+ Length field if the field has a nonzero value.
+ */
+
+ if ((pHeader_802_11->FC.Type == BTYPE_DATA) ||
+ (pHeader_802_11->FC.Type == BTYPE_MGMT))
+ {
+ if (pHeader_802_11->FC.SubType != SUBTYPE_QOS_NULL)
+ pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
+ }
+
+
+
+ if ((pEntry != NULL) &&
+ (pEntry->PsMode == PWR_SAVE) &&
+ (((pHeader_802_11->FC.Type == BTYPE_DATA) &&
+ (pHeader_802_11->FC.SubType != SUBTYPE_NULL_FUNC) &&
+ (pHeader_802_11->FC.SubType != SUBTYPE_QOS_NULL)) ||
+ ((pHeader_802_11->FC.Type == BTYPE_MGMT) &&
+ (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) ||
+ ((pHeader_802_11->FC.Type == BTYPE_MGMT) &&
+ (pHeader_802_11->FC.SubType == SUBTYPE_ACTION_NO_ACK))))
+ {
+ /* the peer is in PS mode, we need to queue the management frame */
+ UINT8 FlgIsDeltsFrame = 0, MgmtQid = QID_AC_VO;
+
+ /*
+ 1. Data & Not QoS Null, or
+ 2. Management & Action, or
+ 3. Management & Action No ACK;
+ */
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("The station is in ps mode, queue the management frame!\n"));
+ RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
+ RTMP_SET_PACKET_MGMT_PKT(pPacket, 1); /* is management frame */
+ RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(pPacket, 0); /* default to management queue */
+
+ if ((pAd->MACVersion == 0x28600100) || (FlgDataQForce == TRUE))
+ RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(pPacket, 1); /* force to data queue */
+
+ if ((pHeader_802_11->FC.Type == BTYPE_MGMT) &&
+ (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
+ {
+ FRAME_ADDBA_REQ *pFrameBa = (FRAME_ADDBA_REQ *)pHeader_802_11;
+ if (pFrameBa->Category == CATEGORY_BA)
+ MgmtQid = QueIdx;
+ }
+
+
+ AP_QueuePsActionPacket(pAd, pEntry, pPacket, FlgIsDeltsFrame,
+ FlgIsLocked, MgmtQid);
+ return NDIS_STATUS_SUCCESS;
+ }
+ else
+#endif /* CONFIG_AP_SUPPORT */
+ {
+ return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
+ }
+}
+
+
+NDIS_STATUS MlmeHardTransmitMgmtRing(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket)
+{
+ PACKET_INFO PacketInfo;
+ PUCHAR pSrcBufVA;
+ UINT SrcBufLen;
+ PHEADER_802_11 pHeader_802_11;
+ BOOLEAN bAckRequired, bInsertTimestamp;
+ UCHAR MlmeRate;
+ PTXWI_STRUC pFirstTxWI;
+ MAC_TABLE_ENTRY *pMacEntry = NULL;
+ UCHAR PID;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+
+ /* Make sure MGMT ring resource won't be used by other threads*/
+ RTMP_SEM_LOCK(&pAd->MgmtRingLock);
+ if (pSrcBufVA == NULL)
+ {
+ /* The buffer shouldn't be NULL*/
+ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+ return NDIS_STATUS_FAILURE;
+ }
+
+
+ pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
+ pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWISize);
+
+ if (pHeader_802_11->Addr1[0] & 0x01)
+ {
+ MlmeRate = pAd->CommonCfg.BasicMlmeRate;
+ }
+ else
+ {
+ MlmeRate = pAd->CommonCfg.MlmeRate;
+ }
+
+ /* Verify Mlme rate for a / g bands.*/
+ if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band*/
+ MlmeRate = RATE_6;
+
+ if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
+ (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
+ {
+ pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
+ }
+
+
+ /* Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)*/
+ /* Snice it's been set to 0 while on MgtMacHeaderInit*/
+ /* By the way this will cause frame to be send on PWR_SAVE failed.*/
+
+ pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; /* (pAd->StaCfg.Psm == PWR_SAVE);*/
+
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+ pHeader_802_11->FC.MoreData = RTMP_GET_PACKET_MOREDATA(pPacket);
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ bInsertTimestamp = FALSE;
+ if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL*/
+ {
+ bAckRequired = FALSE;
+ }
+ else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame)*/
+ {
+ if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST*/
+ {
+ bAckRequired = FALSE;
+ pHeader_802_11->Duration = 0;
+ }
+ else
+ {
+ bAckRequired = TRUE;
+ pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
+ if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) && (pHeader_802_11->FC.Type == BTYPE_MGMT))
+ {
+ bInsertTimestamp = TRUE;
+ bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Response*/
+ }
+ else if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) && (pHeader_802_11->FC.Type == BTYPE_MGMT))
+ {
+ bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Request*/
+ }
+ }
+ }
+
+ pHeader_802_11->Sequence = pAd->Sequence++;
+ if (pAd->Sequence >0xfff)
+ pAd->Sequence = 0;
+
+ /* Before radar detection done, mgmt frame can not be sent but probe req*/
+ /* Because we need to use probe req to trigger driver to send probe req in passive scan*/
+ if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
+ && (pAd->CommonCfg.bIEEE80211H == 1)
+ && (pAd->Dot11_H.RDMode != RD_NORMAL_MODE))
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
+/* if (!IrqState)*/
+ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+ return (NDIS_STATUS_FAILURE);
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
+#endif
+
+
+ /* fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET*/
+ /* should always has only one physical buffer, and the whole frame size equals*/
+ /* to the first scatter buffer size*/
+
+
+ /*
+ Initialize TX Descriptor
+ For inter-frame gap, the number is for this frame and next frame
+ For MLME rate, we will fix as 2Mb to match other vendor's implement
+ */
+ /*pAd->CommonCfg.MlmeTransmit.field.MODE = 1;*/
+
+ /*
+ management frame doesn't need encryption.
+ so use RESERVED_WCID no matter u are sending to specific wcid or not
+ */
+ PID = PID_MGMT;
+
+
+ if (pMacEntry == NULL)
+ {
+ RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
+ 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWISize), PID, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
+ }
+ else
+ {
+ /* dont use low rate to send QoS Null data frame */
+ RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
+ bInsertTimestamp, FALSE, bAckRequired, FALSE,
+ 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWISize),
+ pMacEntry->MaxHTPhyMode.field.MCS, 0,
+ (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
+ IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange(pAd, (PUCHAR)pFirstTxWI, TYPE_TXWI);
+#endif
+
+ /* Now do hardware-depened kick out.*/
+ HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
+
+ /* Make sure to release MGMT ring resource*/
+/* if (!IrqState)*/
+ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/********************************************************************************
+
+ New DeQueue Procedures.
+
+ ********************************************************************************/
+
+#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
+ do{ \
+ if (bIntContext == FALSE) \
+ RTMP_IRQ_LOCK((lock), IrqFlags); \
+ }while(0)
+
+#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
+ do{ \
+ if (bIntContext == FALSE) \
+ RTMP_IRQ_UNLOCK((lock), IrqFlags); \
+ }while(0)
+
+
+
+
+/*
+ ========================================================================
+ Tx Path design algorithm:
+ Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
+ Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
+ Classification Rule=>
+ Multicast: (*addr1 & 0x01) == 0x01
+ Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
+ 11N Rate : If peer support HT
+ (1).AMPDU -- If TXBA is negotiated.
+ (2).AMSDU -- If AMSDU is capable for both peer and ourself.
+ *). AMSDU can embedded in a AMPDU, but now we didn't support it.
+ (3).Normal -- Other packets which send as 11n rate.
+
+ B/G Rate : If peer is b/g only.
+ (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
+ (2).Normal -- Other packets which send as b/g rate.
+ Fragment:
+ The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
+
+ Classified Packet Handle Rule=>
+ Multicast:
+ No ACK, pTxBlk->bAckRequired = FALSE;
+ No WMM, pTxBlk->bWMM = FALSE;
+ No piggyback, pTxBlk->bPiggyBack = FALSE;
+ Force LowRate, pTxBlk->bForceLowRate = TRUE;
+ Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
+ the same policy to handle it.
+ Force LowRate, pTxBlk->bForceLowRate = TRUE;
+
+ 11N Rate :
+ No piggyback, pTxBlk->bPiggyBack = FALSE;
+
+ (1).AMSDU
+ pTxBlk->bWMM = TRUE;
+ (2).AMPDU
+ pTxBlk->bWMM = TRUE;
+ (3).Normal
+
+ B/G Rate :
+ (1).ARALINK
+
+ (2).Normal
+ ========================================================================
+*/
+static UCHAR TxPktClassification(
+ IN RTMP_ADAPTER *pAd,
+ IN PNDIS_PACKET pPacket)
+{
+ UCHAR TxFrameType = TX_UNKOWN_FRAME;
+ UCHAR Wcid;
+ MAC_TABLE_ENTRY *pMacEntry = NULL;
+#ifdef DOT11_N_SUPPORT
+ BOOLEAN bHTRate = FALSE;
+#endif /* DOT11_N_SUPPORT */
+
+ Wcid = RTMP_GET_PACKET_WCID(pPacket);
+ if (Wcid == MCAST_WCID)
+ { /* Handle for RA is Broadcast/Multicast Address.*/
+ return TX_MCAST_FRAME;
+ }
+
+ /* Handle for unicast packets*/
+ pMacEntry = &pAd->MacTab.Content[Wcid];
+ if (RTMP_GET_PACKET_LOWRATE(pPacket))
+ { /* It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame*/
+ TxFrameType = TX_LEGACY_FRAME;
+ }
+#ifdef DOT11_N_SUPPORT
+ else if (IS_HT_RATE(pMacEntry))
+ { /* it's a 11n capable packet*/
+
+ /* Depends on HTPhyMode to check if the peer support the HTRate transmission.*/
+ /* Currently didn't support A-MSDU embedded in A-MPDU*/
+ bHTRate = TRUE;
+ if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
+ TxFrameType = TX_LEGACY_FRAME;
+#ifdef UAPSD_SUPPORT
+ else if (RTMP_GET_PACKET_EOSP(pPacket))
+ TxFrameType = TX_LEGACY_FRAME;
+#endif /* UAPSD_SUPPORT */
+ else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
+ return TX_AMPDU_FRAME;
+ else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
+ return TX_AMSDU_FRAME;
+ else
+ TxFrameType = TX_LEGACY_FRAME;
+ }
+#endif /* DOT11_N_SUPPORT */
+ else
+ { /* it's a legacy b/g packet.*/
+ if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
+ (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
+ (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
+ { /* if peer support Ralink Aggregation, we use it.*/
+ TxFrameType = TX_RALINK_FRAME;
+ }
+ else
+ {
+ TxFrameType = TX_LEGACY_FRAME;
+ }
+ }
+
+ /* Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.*/
+ if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1)
+ && (TxFrameType == TX_LEGACY_FRAME)
+#ifdef DOT11_N_SUPPORT
+ && ((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) == 0)
+#endif /* DOT11_N_SUPPORT */
+ )
+ TxFrameType = TX_FRAG_FRAME;
+
+ return TxFrameType;
+}
+
+
+BOOLEAN RTMP_FillTxBlkInfo(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk)
+{
+ PACKET_INFO PacketInfo;
+ PNDIS_PACKET pPacket;
+ PMAC_TABLE_ENTRY pMacEntry = NULL;
+
+ pPacket = pTxBlk->pPacket;
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
+
+ pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
+ pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
+ pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
+ pTxBlk->FrameGap = IFS_HTTXOP; /* ASIC determine Frame Gap*/
+#ifdef CONFIG_AP_SUPPORT
+ pTxBlk->pMbss = NULL;
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
+ else
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
+
+ /* Default to clear this flag*/
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
+
+#ifdef WAPI_SUPPORT
+ /* Check if this is an WPI data frame*/
+ if ((RTMPIsWapiCipher(pAd, pTxBlk->apidx) == TRUE) &&
+ (RTMP_GET_PACKET_WAI(pTxBlk->pPacket) == FALSE))
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bWPIDataFrame);
+ else
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWPIDataFrame);
+#endif /* WAPI_SUPPORT */
+
+ if (pTxBlk->Wcid == MCAST_WCID)
+ {
+ pTxBlk->pMacEntry = NULL;
+ {
+#ifdef MCAST_RATE_SPECIFIC
+ PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
+ if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
+ pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
+ else
+#endif /* MCAST_RATE_SPECIFIC */
+ pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
+ }
+
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); /* AckRequired = FALSE, when broadcast packet in Adhoc mode.*/
+ /*TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);*/
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
+ if (RTMP_GET_PACKET_MOREDATA(pPacket))
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
+ }
+ }
+ else
+ {
+ pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
+ pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
+
+ pMacEntry = pTxBlk->pMacEntry;
+#ifdef CONFIG_AP_SUPPORT
+ pTxBlk->pMbss = pMacEntry->pMbss;
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.*/
+ if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
+ else
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
+
+
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef WDS_SUPPORT
+ if(IS_ENTRY_WDS(pMacEntry))
+ {
+ /*if (pAd->WdsTab.WdsEntry[pMacEntry->MatchWDSTabIdx].bAutoTxRateSwitch)*/
+ /* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);*/
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bWDSEntry);
+ }
+ else
+#endif /* WDS_SUPPORT */
+#ifdef APCLI_SUPPORT
+ if(IS_ENTRY_APCLI(pMacEntry))
+ {
+ PNDIS_PACKET apCliPkt = NULL;
+
+ /* For each tx packet, update our MAT convert engine databases.*/
+ apCliPkt = (PNDIS_PACKET)MATEngineTxHandle(pAd, pPacket, pMacEntry->MatchAPCLITabIdx, pTxBlk->OpMode);
+ if(apCliPkt)
+ {
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ pPacket = apCliPkt;
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
+ pTxBlk->pPacket = apCliPkt;
+ }
+ pTxBlk->pApCliEntry = &pAd->ApCfg.ApCliTab[pMacEntry->MatchAPCLITabIdx];
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bApCliPacket);
+
+ /*if (pTxBlk->pApCliEntry->bAutoTxRateSwitch)*/
+ /* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);*/
+
+ }
+ else
+#endif /* APCLI_SUPPORT */
+#ifdef CLIENT_WDS
+ if (IS_ENTRY_CLIWDS(pMacEntry))
+ {
+ PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
+ PUCHAR pSA = GET_OS_PKT_DATAPTR(pPacket) + MAC_ADDR_LEN;
+ if (((pMacEntry->apidx < MAX_MBSSID_NUM(pAd))
+ && !MAC_ADDR_EQUAL(pSA, pAd->ApCfg.MBSSID[pMacEntry->apidx].Bssid))
+ || !MAC_ADDR_EQUAL(pDA, pMacEntry->Addr)
+ )
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bClientWDSFrame);
+ }
+ }
+ else
+#endif /* CLIENT_WDS */
+ if (IS_ENTRY_CLIENT(pMacEntry))
+ {
+ /*if (IS_ENTRY_CLIENT(pMacEntry) && pAd->ApCfg.MBSSID[pMacEntry->apidx].bAutoTxRateSwitch)*/
+ /* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);*/
+ }
+ else
+ return FALSE;
+
+ /* If both of peer and us support WMM, enable it.*/
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+
+ if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
+ {
+ if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
+ ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
+ { /* Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.*/
+ pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
+
+#ifdef WAPI_SUPPORT
+ /* According to WAPIA certification description, WAI packets can not
+ include QoS header */
+ if (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))
+ {
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
+ }
+#endif /* WAPI_SUPPORT */
+#ifdef DOT11_N_SUPPORT
+ /* Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???*/
+ if (IS_HT_STA(pTxBlk->pMacEntry) &&
+ (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
+ ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
+ {
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
+ }
+#endif /* DOT11_N_SUPPORT */
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
+ (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
+ { /* Currently piggy-back only support when peer is operate in b/g mode.*/
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
+ }
+#endif /* DOT11_N_SUPPORT */
+
+ if (RTMP_GET_PACKET_MOREDATA(pPacket))
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
+ }
+#ifdef UAPSD_SUPPORT
+ if (RTMP_GET_PACKET_EOSP(pPacket))
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
+ }
+#endif /* UAPSD_SUPPORT */
+ }
+ else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
+ }
+
+ pMacEntry->DebugTxCount++;
+ }
+
+ pAd->LastTxRate = (USHORT)pTxBlk->pTransmit->word;
+
+ return TRUE;
+}
+
+
+BOOLEAN CanDoAggregateTransmit(
+ IN RTMP_ADAPTER *pAd,
+ IN NDIS_PACKET *pPacket,
+ IN TX_BLK *pTxBlk)
+{
+ int minLen = LENGTH_802_3;
+
+ /*DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType));*/
+
+ if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
+ return FALSE;
+
+ if (RTMP_GET_PACKET_DHCP(pPacket) ||
+ RTMP_GET_PACKET_EAPOL(pPacket) ||
+ RTMP_GET_PACKET_WAI(pPacket))
+ return FALSE;
+
+ /* Make sure the first packet has non-zero-length data payload */
+ if (RTMP_GET_PACKET_VLAN(pPacket))
+ minLen += LENGTH_802_1Q; /* VLAN tag */
+ else if (RTMP_GET_PACKET_LLCSNAP(pPacket))
+ minLen += 8; /* SNAP hdr Len*/
+ if (minLen >= GET_OS_PKT_LEN(pPacket))
+ return FALSE;
+
+ if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
+ ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
+ { /* For AMSDU, allow the packets with total length < max-amsdu size*/
+ return FALSE;
+ }
+
+ if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
+ (pTxBlk->TxPacketList.Number == 2))
+ { /* For RALINK-Aggregation, allow two frames in one batch.*/
+ return FALSE;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ if ((MAC_ADDR_EQUAL(GET_OS_PKT_DATAPTR(pTxBlk->pPacket), GET_OS_PKT_DATAPTR(pPacket))) && (pAd->OpMode == OPMODE_AP)) /* unicast to same STA*/
+ return TRUE;
+ else
+#endif /* CONFIG_AP_SUPPORT */
+ return FALSE;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ To do the enqueue operation and extract the first item of waiting
+ list. If a number of available shared memory segments could meet
+ the request of extracted item, the extracted item will be fragmented
+ into shared memory segments.
+
+ Arguments:
+ pAd Pointer to our adapter
+ pQueue Pointer to Waiting Queue
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPDeQueuePacket(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bIntContext,
+ IN UCHAR QIdx, /* BulkOutPipeId */
+ IN UCHAR Max_Tx_Packets)
+{
+ PQUEUE_ENTRY pEntry = NULL;
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ UCHAR Count=0;
+ PQUEUE_HEADER pQueue;
+ ULONG FreeNumber[NUM_OF_TX_RING];
+ UCHAR QueIdx, sQIdx, eQIdx;
+ unsigned long IrqFlags = 0;
+ BOOLEAN hasTxDesc = FALSE;
+ TX_BLK TxBlk;
+ TX_BLK *pTxBlk;
+
+#ifdef DBG_DIAGNOSE
+ BOOLEAN firstRound;
+ RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
+#endif
+
+
+ if (QIdx == NUM_OF_TX_RING)
+ {
+ sQIdx = 0;
+ eQIdx = 3; /* 4 ACs, start from 0.*/
+ }
+ else
+ {
+ sQIdx = eQIdx = QIdx;
+ }
+
+ for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
+ {
+ Count=0;
+
+ RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags);
+
+#ifdef DBG_DIAGNOSE
+ firstRound = ((QueIdx == 0) ? TRUE : FALSE);
+#endif /* DBG_DIAGNOSE */
+
+ while (1)
+ {
+ if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
+ fRTMP_ADAPTER_RADIO_OFF |
+ fRTMP_ADAPTER_RESET_IN_PROGRESS |
+ fRTMP_ADAPTER_HALT_IN_PROGRESS |
+ fRTMP_ADAPTER_NIC_NOT_EXIST)))
+ )
+ {
+ RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
+ return;
+ }
+
+ if (Count >= Max_Tx_Packets)
+ break;
+
+ DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ if (&pAd->TxSwQueue[QueIdx] == NULL)
+ {
+#ifdef DBG_DIAGNOSE
+ if (firstRound == TRUE)
+ pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
+#endif /* DBG_DIAGNOSE */
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ break;
+ }
+
+
+ /* probe the Queue Head*/
+ pQueue = &pAd->TxSwQueue[QueIdx];
+ if ((pEntry = pQueue->Head) == NULL)
+ {
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ break;
+ }
+
+ pTxBlk = &TxBlk;
+ NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
+ /*InitializeQueueHeader(&pTxBlk->TxPacketList); Didn't need it because we already memzero it.*/
+ pTxBlk->QueIdx = QueIdx;
+
+#ifdef VENDOR_FEATURE1_SUPPORT
+ pTxBlk->HeaderBuf = (UCHAR *)pTxBlk->HeaderBuffer;
+#endif /* VENDOR_FEATURE1_SUPPORT */
+
+ pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+
+#ifdef CONFIG_AP_SUPPORT
+ if (RTMP_GET_PACKET_MGMT_PKT(pPacket) == 1)
+ {
+ /* this is a management frame */
+ NDIS_STATUS status;
+
+ pEntry = RemoveHeadQueue(pQueue);
+
+ status = MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("Transmit queued management frame error!\n"));
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ }
+
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ Count++;
+ continue;
+ }
+ else
+ {
+ /*when WDS Jam happen, drop following 1min to HW TxRing Pkts*/
+ MAC_TABLE_ENTRY *pMacEntry = NULL;
+ UCHAR RAWcid;
+ RAWcid = RTMP_GET_PACKET_WCID(pPacket);
+ pMacEntry = &pAd->MacTab.Content[RAWcid];
+
+#ifdef WDS_SUPPORT
+ /*
+ It WDS life checking.
+ WDS need to check the peer is come back or not
+ by sending few (2 ~3) WDS Packet out to peer.
+ It must be checked first.
+ */
+ if(IS_ENTRY_WDS(pMacEntry))
+ {
+ ULONG Now32;
+ NdisGetSystemUpTime(&Now32);
+ if(pMacEntry->LockEntryTx && RTMP_TIME_BEFORE(Now32, pMacEntry->TimeStamp_toTxRing + WDS_ENTRY_RETRY_INTERVAL))
+ {
+ pEntry = RemoveHeadQueue(pQueue);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ continue;
+ }
+ else
+ NdisGetSystemUpTime(&pMacEntry->TimeStamp_toTxRing);
+ }
+ else
+#endif /* WDS_SUPPORT */
+ if (!IS_ENTRY_NONE(pMacEntry)
+ && (pMacEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck))
+ {
+ /*
+ Sample Lin, 20100412
+
+ For non-WDS interface, we need to send packet to detect
+ the link periodically; Or when
+ pMacEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck,
+ no any chance to clear pMacEntry->ContinueTxFailCnt.
+
+ EX: When pMacEntry->ContinueTxFailCnt >=
+ pAd->ApCfg.EntryLifeCheck, the condition will not be
+ removed and we will drop all packets for the pEntry.
+ But maybe the signal becomes better.
+ So we try to send a packet periodically and we will
+ get the tx status in tx done interrupt.
+ If the tx status is success, pMacEntry->ContinueTxFailCnt
+ will be cleared to 0.
+ */
+#define ENTRY_RETRY_INTERVAL (100 * OS_HZ / 1000)
+ ULONG Now32;
+ NdisGetSystemUpTime(&Now32);
+ if(RTMP_TIME_BEFORE(Now32, pMacEntry->TimeStamp_toTxRing + ENTRY_RETRY_INTERVAL))
+ {
+ pEntry = RemoveHeadQueue(pQueue);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ continue;
+ }
+ else
+ NdisGetSystemUpTime(&pMacEntry->TimeStamp_toTxRing);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Early check to make sure we have enoguh Tx Resource.*/
+ hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
+ if (!hasTxDesc)
+ {
+ pAd->PrivateInfo.TxRingFullCnt++;
+
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+
+ break;
+ }
+
+ pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
+ pEntry = RemoveHeadQueue(pQueue);
+ pTxBlk->TotalFrameNum++;
+ pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary*/
+ pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
+ pTxBlk->pPacket = pPacket;
+ InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
+
+ if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
+ {
+ // Enhance SW Aggregation Mechanism
+ if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
+ {
+ InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ break;
+ }
+ }
+
+
+ if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
+ {
+ // Enhance SW Aggregation Mechanism
+ if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
+ {
+ InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ break;
+ }
+
+ do{
+ if((pEntry = pQueue->Head) == NULL)
+ break;
+
+ /* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.*/
+ pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+ FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
+ hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
+ if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
+ break;
+
+ /*Remove the packet from the TxSwQueue and insert into pTxBlk*/
+ pEntry = RemoveHeadQueue(pQueue);
+ ASSERT(pEntry);
+ pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+
+
+ pTxBlk->TotalFrameNum++;
+ pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary*/
+ pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
+ InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
+ }while(1);
+
+ if (pTxBlk->TxPacketList.Number == 1)
+ pTxBlk->TxFrameType = TX_LEGACY_FRAME;
+ }
+
+#ifdef RTMP_MAC_USB
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+#endif /* RTMP_MAC_USB */
+
+ Count += pTxBlk->TxPacketList.Number;
+
+ /* Do HardTransmit now.*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ Status = APHardTransmit(pAd, pTxBlk, QueIdx);
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ }
+
+ RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
+
+#ifdef RTMP_MAC_USB
+ if (!hasTxDesc)
+ RTUSBKickBulkOut(pAd);
+#endif /* RTMP_MAC_USB */
+
+#ifdef BLOCK_NET_IF
+ if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE)
+ && (pAd->TxSwQueue[QueIdx].Number < 1))
+ {
+ releaseNetIf(&pAd->blockQueueTab[QueIdx]);
+ }
+#endif /* BLOCK_NET_IF */
+
+ }
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculates the duration which is required to transmit out frames
+ with given size and specified rate.
+
+ Arguments:
+ pAd Pointer to our adapter
+ Rate Transmit rate
+ Size Frame size in units of byte
+
+ Return Value:
+ Duration number in units of usec
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+USHORT RTMPCalcDuration(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Rate,
+ IN ULONG Size)
+{
+ ULONG Duration = 0;
+
+ if (Rate < RATE_FIRST_OFDM_RATE) /* CCK*/
+ {
+ if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
+ Duration = 96; /* 72+24 preamble+plcp*/
+ else
+ Duration = 192; /* 144+48 preamble+plcp*/
+
+ Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
+ if ((Size << 4) % RateIdTo500Kbps[Rate])
+ Duration ++;
+ }
+ else if (Rate <= RATE_LAST_OFDM_RATE)/* OFDM rates*/
+ {
+ Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension*/
+ Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
+ if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
+ Duration += 4;
+ }
+ else /*mimo rate*/
+ {
+ Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension*/
+ }
+
+ return (USHORT)Duration;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculates the duration which is required to transmit out frames
+ with given size and specified rate.
+
+ Arguments:
+ pTxWI Pointer to head of each MPDU to HW.
+ Ack Setting for Ack requirement bit
+ Fragment Setting for Fragment bit
+ RetryMode Setting for retry mode
+ Ifs Setting for IFS gap
+ Rate Setting for transmit rate
+ Service Setting for service
+ Length Frame length
+ TxPreamble Short or Long preamble when using CCK rates
+ QueIdx - 0-3, according to 802.11e/d4.4 June/2003
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ See also : BASmartHardTransmit() !!!
+
+ ========================================================================
+*/
+VOID RTMPWriteTxWI(
+ IN PRTMP_ADAPTER pAd,
+ IN PTXWI_STRUC pOutTxWI,
+ IN BOOLEAN FRAG,
+ IN BOOLEAN CFACK,
+ IN BOOLEAN InsTimestamp,
+ IN BOOLEAN AMPDU,
+ IN BOOLEAN Ack,
+ IN BOOLEAN NSeq, /* HW new a sequence.*/
+ IN UCHAR BASize,
+ IN UCHAR WCID,
+ IN ULONG Length,
+ IN UCHAR PID,
+ IN UCHAR TID,
+ IN UCHAR TxRate,
+ IN UCHAR Txopmode,
+ IN BOOLEAN CfAck,
+ IN HTTRANSMIT_SETTING *pTransmit)
+{
+ PMAC_TABLE_ENTRY pMac = NULL;
+ TXWI_STRUC TxWI;
+ PTXWI_STRUC pTxWI;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+ if (WCID < MAX_LEN_OF_MAC_TABLE)
+ pMac = &pAd->MacTab.Content[WCID];
+
+
+ /*
+ Always use Long preamble before verifiation short preamble functionality works well.
+ Todo: remove the following line if short preamble functionality works
+ */
+
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+ NdisZeroMemory(&TxWI, TXWISize);
+ pTxWI = &TxWI;
+
+ pTxWI->FRAG= FRAG;
+
+ pTxWI->CFACK = CFACK;
+ pTxWI->TS= InsTimestamp;
+ pTxWI->AMPDU = AMPDU;
+ pTxWI->ACK = Ack;
+ pTxWI->txop= Txopmode;
+
+ pTxWI->NSEQ = NSeq;
+ /* John tune the performace with Intel Client in 20 MHz performance*/
+#ifdef DOT11_N_SUPPORT
+ BASize = pAd->CommonCfg.TxBASize;
+ if (pAd->MACVersion == 0x28720200)
+ {
+ if( BASize >13 )
+ BASize =13;
+ }
+ else
+ {
+ if( BASize >7 )
+ BASize =7;
+ }
+
+ pTxWI->BAWinSize = BASize;
+ pTxWI->ShortGI = pTransmit->field.ShortGI;
+ pTxWI->STBC = pTransmit->field.STBC;
+
+#ifdef TXBF_SUPPORT
+ if (pMac && pAd->chipCap.FlgHwTxBfCap)
+ {
+ if (pMac->TxSndgType == SNDG_TYPE_NDP || pMac->TxSndgType == SNDG_TYPE_SOUNDING || pTxWI->eTxBF)
+ pTxWI->STBC = 0;
+ }
+#endif /* TXBF_SUPPORT */
+#endif /* DOT11_N_SUPPORT */
+
+ pTxWI->WirelessCliID = WCID;
+ pTxWI->MPDUtotalByteCount = Length;
+ pTxWI->PacketId = PID;
+
+ /* If CCK or OFDM, BW must be 20*/
+ pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+ if (pTxWI->BW)
+ pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
+#endif /* DOT11N_DRAFT3 */
+#endif /* DOT11_N_SUPPORT */
+
+ pTxWI->MCS = pTransmit->field.MCS;
+ pTxWI->PHYMODE = pTransmit->field.MODE;
+ pTxWI->CFACK = CfAck;
+
+#ifdef DOT11_N_SUPPORT
+ if (pMac)
+ {
+ if (pAd->CommonCfg.bMIMOPSEnable)
+ {
+ if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
+ {
+ /* Dynamic MIMO Power Save Mode*/
+ pTxWI->MIMOps = 1;
+ }
+ else if (pMac->MmpsMode == MMPS_STATIC)
+ {
+ /* Static MIMO Power Save Mode*/
+ if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
+ {
+ pTxWI->MCS = 7;
+ pTxWI->MIMOps = 0;
+ }
+ }
+ }
+ /*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;*/
+ {
+ pTxWI->MpduDensity = pMac->MpduDensity;
+ }
+ }
+#endif /* DOT11_N_SUPPORT */
+
+
+ pTxWI->PacketId = pTxWI->MCS;
+ NdisMoveMemory(pOutTxWI, &TxWI, TXWISize);
+}
+
+
+VOID RTMPWriteTxWI_Data(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PTXWI_STRUC pTxWI,
+ IN TX_BLK *pTxBlk)
+{
+ HTTRANSMIT_SETTING *pTransmit;
+ PMAC_TABLE_ENTRY pMacEntry;
+#ifdef DOT11_N_SUPPORT
+ UCHAR BASize;
+#endif /* DOT11_N_SUPPORT */
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+ ASSERT(pTxWI);
+
+ pTransmit = pTxBlk->pTransmit;
+ pMacEntry = pTxBlk->pMacEntry;
+
+
+
+ /*
+ Always use Long preamble before verifiation short preamble functionality works well.
+ Todo: remove the following line if short preamble functionality works
+ */
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+ NdisZeroMemory(pTxWI, TXWISize);
+
+ pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
+ pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
+ pTxWI->txop = pTxBlk->FrameGap;
+
+ pTxWI->WirelessCliID = pTxBlk->Wcid;
+
+ pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
+ pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
+
+ /* If CCK or OFDM, BW must be 20*/
+ pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+ if (pTxWI->BW)
+ pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
+#endif /* DOT11N_DRAFT3 */
+ pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
+
+#ifdef TXBF_SUPPORT
+ if(pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE)
+ pTxWI->AMPDU = FALSE;
+#endif /* TXBF_SUPPORT */
+
+ BASize = pAd->CommonCfg.TxBASize;
+
+ if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
+ {
+ /*
+ * Under HT20, 2x2 chipset, OPEN, and with some atero chipsets
+ * reduce BASize to 7 to add one bulk A-MPDU during one TXOP
+ * to improve throughput
+ */
+ if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pAd->Antenna.field.TxPath == 2)
+ && (pMacEntry->bIAmBadAtheros) && (pMacEntry->WepStatus == Ndis802_11EncryptionDisabled))
+ {
+ BASize = 7;
+ }
+ else
+ {
+ UCHAR RABAOriIdx = 0; /*The RA's BA Originator table index.*/
+ RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
+ BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
+ }
+ }
+
+#ifdef TXBF_SUPPORT
+ if (pTxBlk->TxSndgPkt == SNDG_TYPE_SOUNDING)
+ {
+ pTxWI->Sounding = 1;
+/* DBGPRINT(RT_DEBUG_OFF, ("\n @@@@@ 1. pTxBlk->TxSndgPkt = %d @@@@@ .\n", pTxBlk->TxSndgPkt));*/
+ DBGPRINT(RT_DEBUG_TRACE, ("ETxBF in RTMPWriteTxWI_Data(): sending normal sounding, eTxBF=%d\n", pTxWI->eTxBF));
+ pTxWI->iTxBF = 0;
+ }
+ else if (pTxBlk->TxSndgPkt == SNDG_TYPE_NDP)
+ {
+ if (pTxBlk->TxNDPSndgMcs>=16)
+ pTxWI->NDPSndRate = 2;
+ else if (pTxBlk->TxNDPSndgMcs>=8)
+ pTxWI->NDPSndRate = 1;
+ else
+ pTxWI->NDPSndRate = 0;
+
+ pTxWI->NDPSndBW = pTransmit->field.BW;
+
+ pTxWI->iTxBF = 0;
+ }
+ else
+ {
+#ifdef MFB_SUPPORT
+ if (pMacEntry && (pMacEntry->mrqCnt >0) && (pMacEntry->toTxMrq == TRUE))
+ {
+ pTxWI->eTxBF = ~(pTransmit->field.eTxBF);
+ }
+ else
+#endif /* MFB_SUPPORT */
+ pTxWI->eTxBF = pTransmit->field.eTxBF;
+ pTxWI->iTxBF = pTransmit->field.iTxBF;
+ }
+#endif /* TXBF_SUPPORT */
+
+ pTxWI->BAWinSize = BASize;
+ pTxWI->ShortGI = pTransmit->field.ShortGI;
+ pTxWI->STBC = pTransmit->field.STBC;
+#ifdef TXBF_SUPPORT
+ if (pTxBlk->TxSndgPkt == SNDG_TYPE_NDP || pTxBlk->TxSndgPkt == SNDG_TYPE_SOUNDING || pTxWI->eTxBF)
+ pTxWI->STBC = 0;
+#endif /* TXBF_SUPPORT */
+
+#endif /* DOT11_N_SUPPORT */
+
+ pTxWI->MCS = pTransmit->field.MCS;
+ pTxWI->PHYMODE = pTransmit->field.MODE;
+
+
+#ifdef DOT11_N_SUPPORT
+ if (pMacEntry)
+ {
+ if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
+ {
+ /* Dynamic MIMO Power Save Mode*/
+ pTxWI->MIMOps = 1;
+ }
+ else if (pMacEntry->MmpsMode == MMPS_STATIC)
+ {
+ /* Static MIMO Power Save Mode*/
+ if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
+ {
+ pTxWI->MCS = 7;
+ pTxWI->MIMOps = 0;
+ }
+ }
+
+ if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pMacEntry->bIAmBadAtheros))
+ pTxWI->MpduDensity = 7;
+ else
+ pTxWI->MpduDensity = pMacEntry->MpduDensity;
+ }
+#endif /* DOT11_N_SUPPORT */
+
+#ifdef TXBF_SUPPORT
+ if (pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE)
+ {
+ pTxWI->MCS = 0;
+ pTxWI->AMPDU = FALSE;
+ }
+#endif /* TXBF_SUPPORT */
+
+#ifdef DBG_DIAGNOSE
+ if (pTxBlk->QueIdx== 0)
+ {
+ pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
+ pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
+ }
+#endif /* DBG_DIAGNOSE */
+
+ /* for rate adapation*/
+ pTxWI->PacketId = pTxWI->MCS;
+
+#ifdef INF_AMAZON_SE
+/*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */
+ if( RTMP_GET_PACKET_NOBULKOUT(pTxBlk->pPacket))
+ {
+ if(pTxWI->PHYMODE == MODE_CCK)
+ {
+ pTxWI->PacketId = 6;
+ }
+ }
+#endif /* INF_AMAZON_SE */
+
+}
+
+
+VOID RTMPWriteTxWI_Cache(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PTXWI_STRUC pTxWI,
+ IN TX_BLK *pTxBlk)
+{
+ PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit;
+ PMAC_TABLE_ENTRY pMacEntry;
+#ifdef DOT11_N_SUPPORT
+#endif /* DOT11_N_SUPPORT */
+
+
+ /* update TXWI */
+ pMacEntry = pTxBlk->pMacEntry;
+ pTransmit = pTxBlk->pTransmit;
+
+ /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/
+ /*if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry))*/
+ /*if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch))*/
+ if (pMacEntry->bAutoTxRateSwitch)
+ {
+ pTxWI->txop = IFS_HTTXOP;
+
+ /* If CCK or OFDM, BW must be 20*/
+ pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
+ pTxWI->ShortGI = pTransmit->field.ShortGI;
+ pTxWI->STBC = pTransmit->field.STBC;
+
+#ifdef TXBF_SUPPORT
+ if (pTxBlk->TxSndgPkt == SNDG_TYPE_NDP || pTxBlk->TxSndgPkt == SNDG_TYPE_SOUNDING || pTxWI->eTxBF)
+ pTxWI->STBC = 0;
+#endif /* TXBF_SUPPORT */
+
+ pTxWI->MCS = pTransmit->field.MCS;
+ pTxWI->PHYMODE = pTransmit->field.MODE;
+
+ /* set PID for TxRateSwitching*/
+ pTxWI->PacketId = pTransmit->field.MCS;
+
+ }
+
+#ifdef DOT11_N_SUPPORT
+ pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
+#ifdef TXBF_SUPPORT
+ if(pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE)
+ pTxWI->AMPDU = FALSE;
+#endif /* TXBF_SUPPORT */
+
+ pTxWI->MIMOps = 0;
+
+#ifdef DOT11N_DRAFT3
+ if (pTxWI->BW)
+ pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
+#endif /* DOT11N_DRAFT3 */
+
+ if (pAd->CommonCfg.bMIMOPSEnable)
+ {
+ /* MIMO Power Save Mode*/
+ if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
+ {
+ /* Dynamic MIMO Power Save Mode*/
+ pTxWI->MIMOps = 1;
+ }
+ else if (pMacEntry->MmpsMode == MMPS_STATIC)
+ {
+ /* Static MIMO Power Save Mode*/
+ if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
+ {
+ pTxWI->MCS = 7;
+ pTxWI->MIMOps = 0;
+ }
+ }
+ }
+
+ if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
+ {
+ /*
+ * Under HT20, 2x2 chipset, OPEN, and with some atero chipsets
+ * reduce BASize to 7 to add one bulk A-MPDU during one TXOP
+ * to improve throughput
+ */
+ if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pAd->Antenna.field.TxPath == 2)
+ && (pMacEntry->bIAmBadAtheros) && (pMacEntry->WepStatus == Ndis802_11EncryptionDisabled))
+ {
+ pTxWI->BAWinSize = 7;
+ }
+ }
+
+ if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pMacEntry->bIAmBadAtheros))
+ pTxWI->MpduDensity = 7;
+
+#endif /* DOT11_N_SUPPORT */
+
+#ifdef DBG_DIAGNOSE
+ if (pTxBlk->QueIdx== 0)
+ {
+ pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
+ pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
+ }
+#endif /* DBG_DIAGNOSE */
+
+#ifdef TXBF_SUPPORT
+ if (pTxBlk->TxSndgPkt == SNDG_TYPE_SOUNDING)
+ {
+ pTxWI->Sounding = 1;
+ pTxWI->eTxBF = 0;
+ pTxWI->iTxBF = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("ETxBF in RTMPWriteTxWI_Cache(): sending normal sounding, eTxBF=%d\n", pTxWI->eTxBF));
+ }
+ else if (pTxBlk->TxSndgPkt == SNDG_TYPE_NDP)
+ {
+ if (pTxBlk->TxNDPSndgMcs>=16)
+ pTxWI->NDPSndRate = 2;
+ else if (pTxBlk->TxNDPSndgMcs>=8)
+ pTxWI->NDPSndRate = 1;
+ else
+ pTxWI->NDPSndRate = 0;
+ pTxWI->Sounding = 0;
+ pTxWI->eTxBF = 0;
+ pTxWI->iTxBF = 0;
+
+ pTxWI->NDPSndBW = pTransmit->field.BW;
+
+/*
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("%s():ETxBF, sending ndp sounding(BW=%d, Rate=%d, eTxBF=%d)\n",
+ __FUNCTION__, pTxWI->NDPSndBW, pTxWI->NDPSndRate, pTxWI->eTxBF));
+*/
+ }
+ else
+ {
+ pTxWI->Sounding = 0;
+#ifdef MFB_SUPPORT
+ if (pMacEntry && pMacEntry->mrqCnt >0 && pMacEntry->toTxMrq == 1)
+ {
+ pTxWI->eTxBF = ~(pTransmit->field.eTxBF);
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("ETxBF in AP_AMPDU_Frame_Tx(): invert eTxBF\n"));
+ }
+ else
+#endif /* MFB_SUPPORT */
+ pTxWI->eTxBF = pTransmit->field.eTxBF;
+
+ pTxWI->iTxBF = pTransmit->field.iTxBF;
+
+ if (pTxWI->eTxBF || pTxWI->iTxBF)
+ pTxWI->STBC = 0;
+ }
+
+ if (pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE)
+ {
+ pTxWI->MCS = 0;
+ pTxWI->AMPDU = FALSE;
+ }
+#endif /* TXBF_SUPPORT */
+
+ pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
+
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Suspend MSDU transmission
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPSuspendMsduTransmission(
+ IN PRTMP_ADAPTER pAd)
+{
+ DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier */
+ /* no carrier detection when scanning */
+ if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+ {
+ CarrierDetectionStop(pAd);
+ }
+#endif
+#endif /* CONFIG_AP_SUPPORT */
+
+ /*
+ Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
+ use Lowbound as R66 value on ScanNextChannel(...)
+ */
+ AsicBBPReadWithRxChain(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue, RX_CHAIN_0);
+
+ /* set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)*/
+ /*AsicBBPWriteWithRxChain(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)), RX_CHAIN_ALL);*/
+ RTMPSetAGCInitValue(pAd, BW_20);
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+ /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); abort all TX rings*/
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Resume MSDU transmission
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPResumeMsduTransmission(
+ IN PRTMP_ADAPTER pAd)
+{
+/* UCHAR IrqState;*/
+
+ DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef CARRIER_DETECTION_SUPPORT
+ /* no carrier detection when scanning*/
+ if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+ CarrierDetectionStart(pAd);
+#endif /* CARRIER_DETECTION_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ /*
+ 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"));
+ }
+ AsicBBPWriteWithRxChain(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue, RX_CHAIN_ALL);
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+/* sample, for IRQ LOCK to SEM LOCK */
+/*
+ IrqState = pAd->irq_disabled;
+ if (IrqState)
+ RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+ else
+*/
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+}
+
+
+#ifdef DOT11_N_SUPPORT
+UINT deaggregate_AMSDU_announce(
+ IN PRTMP_ADAPTER pAd,
+ PNDIS_PACKET pPacket,
+ IN PUCHAR pData,
+ IN ULONG DataSize,
+ IN UCHAR OpMode)
+{
+ USHORT PayloadSize;
+ USHORT SubFrameSize;
+ PHEADER_802_3 pAMSDUsubheader;
+ UINT nMSDU;
+ UCHAR Header802_3[14];
+
+ PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
+ PNDIS_PACKET pClonePacket;
+
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR FromWhichBSSID = RTMP_GET_PACKET_IF(pPacket);
+ UCHAR VLAN_Size;
+ USHORT VLAN_VID = 0, VLAN_Priority = 0;
+
+
+ if ((FromWhichBSSID < pAd->ApCfg.BssidNum)
+ )
+ VLAN_Size = (pAd->ApCfg.MBSSID[FromWhichBSSID].VLAN_VID != 0) ? LENGTH_802_1Q : 0;
+#ifdef WDS_VLAN_SUPPORT
+ else if ((FromWhichBSSID >= MIN_NET_DEVICE_FOR_WDS) &&
+ (FromWhichBSSID < (MIN_NET_DEVICE_FOR_WDS + MAX_WDS_ENTRY)))
+ {
+ VLAN_Size = (pAd->WdsTab.\
+ WdsEntry[FromWhichBSSID - MIN_NET_DEVICE_FOR_WDS].\
+ VLAN_VID != 0) ? LENGTH_802_1Q : 0;
+ }
+#endif /* WDS_VLAN_SUPPORT */
+ else /* only MBssid support VLAN.*/
+ VLAN_Size = 0;
+#endif /* CONFIG_AP_SUPPORT */
+
+ nMSDU = 0;
+
+ while (DataSize > LENGTH_802_3)
+ {
+
+ nMSDU++;
+
+ /*hex_dump("subheader", pData, 64);*/
+ pAMSDUsubheader = (PHEADER_802_3)pData;
+ /*pData += LENGTH_802_3;*/
+ PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
+ SubFrameSize = PayloadSize + LENGTH_802_3;
+
+
+ if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
+ {
+ break;
+ }
+
+ /*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize));*/
+
+ pPayload = pData + LENGTH_802_3;
+ pDA = pData;
+ pSA = pData + MAC_ADDR_LEN;
+
+ /* convert to 802.3 header*/
+ CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UCHAR WhichBSSID = FromWhichBSSID;
+ if (pRemovedLLCSNAP)
+ {
+ pPayload -= (LENGTH_802_3 + VLAN_Size);
+ PayloadSize += (LENGTH_802_3 + VLAN_Size);
+ /*NdisMoveMemory(pPayload, &Header802_3, LENGTH_802_3);*/
+ }
+ else
+ {
+ pPayload -= VLAN_Size;
+ PayloadSize += VLAN_Size;
+ }
+
+ MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, WhichBSSID);
+
+#ifdef WDS_VLAN_SUPPORT
+ if (VLAN_VID == 0) /* maybe WDS packet */
+ WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#endif /* WDS_VLAN_SUPPORT */
+
+ RT_VLAN_8023_HEADER_COPY(pAd, VLAN_VID, VLAN_Priority,
+ Header802_3, LENGTH_802_3, pPayload,
+ FromWhichBSSID, TPID);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
+ if (pClonePacket)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+
+ /* A-MSDU has padding to multiple of 4 including subframe header.*/
+ /* align SubFrameSize up to multiple of 4*/
+ SubFrameSize = (SubFrameSize+3)&(~0x3);
+
+
+ if (SubFrameSize > 1528 || SubFrameSize < 32)
+ {
+ break;
+ }
+
+ if (DataSize > SubFrameSize)
+ {
+ pData += SubFrameSize;
+ DataSize -= SubFrameSize;
+ }
+ else
+ {
+ /* end of A-MSDU*/
+ DataSize = 0;
+ }
+ }
+
+ /* finally release original rx packet*/
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+
+ return nMSDU;
+}
+
+
+UINT BA_Reorder_AMSDU_Annnounce(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN UCHAR OpMode)
+{
+ PUCHAR pData;
+ USHORT DataSize;
+ UINT nMSDU = 0;
+
+ pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
+ DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
+
+ nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize, OpMode);
+
+ return nMSDU;
+}
+
+VOID Indicate_AMSDU_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ UINT nMSDU;
+
+ RTMP_UPDATE_OS_PACKET_INFO(pAd, pRxBlk, FromWhichBSSID);
+ RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
+ nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize, pRxBlk->OpMode);
+}
+#endif /* DOT11_N_SUPPORT */
+
+/*
+ ==========================================================================
+ Description:
+ Look up the MAC address in the MAC table. Return NULL if not found.
+ Return:
+ pEntry - pointer to the MAC entry; NULL is not found
+ ==========================================================================
+*/
+MAC_TABLE_ENTRY *MacTableLookup(
+ IN PRTMP_ADAPTER pAd,
+ PUCHAR pAddr)
+{
+ ULONG HashIdx;
+ MAC_TABLE_ENTRY *pEntry = NULL;
+
+ HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+ pEntry = pAd->MacTab.Hash[HashIdx];
+
+ while (pEntry && !IS_ENTRY_NONE(pEntry))
+ {
+ if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
+ {
+ break;
+ }
+ else
+ pEntry = pEntry->pNext;
+ }
+
+ return pEntry;
+}
+
+MAC_TABLE_ENTRY *MacTableInsertEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UCHAR apidx,
+ IN UCHAR OpMode,
+ IN BOOLEAN CleanAll)
+{
+ UCHAR HashIdx;
+ int i, FirstWcid;
+ MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
+/* USHORT offset;*/
+/* ULONG addr;*/
+ BOOLEAN Cancelled;
+
+ /* if FULL, return*/
+ if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
+ return NULL;
+
+ FirstWcid = 1;
+
+ /* allocate one MAC entry*/
+ NdisAcquireSpinLock(&pAd->MacTabLock);
+ for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) /* skip entry#0 so that "entry index == AID" for fast lookup*/
+ {
+ /* pick up the first available vacancy*/
+ if (IS_ENTRY_NONE(&pAd->MacTab.Content[i]))
+ {
+ pEntry = &pAd->MacTab.Content[i];
+
+ /* ENTRY PREEMPTION: initialize the entry */
+ RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
+ RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
+
+ NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
+
+ if (CleanAll == TRUE)
+ {
+ pEntry->MaxSupportedRate = RATE_11;
+ pEntry->CurrTxRate = RATE_11;
+ NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
+ pEntry->PairwiseKey.KeyLen = 0;
+ pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
+ }
+
+ do
+ {
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ if (apidx >= MIN_NET_DEVICE_FOR_APCLI)
+ {
+ SET_ENTRY_APCLI(pEntry);
+ pEntry->isCached = FALSE;
+ break;
+ }
+#endif /* APCLI_SUPPORT */
+#ifdef WDS_SUPPORT
+ if (apidx >= MIN_NET_DEVICE_FOR_WDS)
+ {
+ SET_ENTRY_WDS(pEntry);
+ pEntry->isCached = FALSE;
+ break;
+ }
+#endif /* WDS_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ { /* be a regular-entry*/
+ if ((apidx < pAd->ApCfg.BssidNum) &&
+ (apidx < MAX_MBSSID_NUM(pAd)) &&
+ ((apidx < HW_BEACON_MAX_NUM)) &&
+ (pAd->ApCfg.MBSSID[apidx].MaxStaNum != 0) &&
+ (pAd->ApCfg.MBSSID[apidx].StaCount >= pAd->ApCfg.MBSSID[apidx].MaxStaNum))
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s: The connection table is full in ra%d.\n", __FUNCTION__, apidx));
+ NdisReleaseSpinLock(&pAd->MacTabLock);
+ return NULL;
+ }
+
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ SET_ENTRY_CLIENT(pEntry);
+
+ } while (FALSE);
+
+ pEntry->bIAmBadAtheros = FALSE;
+
+ RTMPInitTimer(pAd, &pEntry->EnqueueStartForPSKTimer, GET_TIMER_FUNCTION(EnqueueStartForPSKExec), pEntry, FALSE);
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (IS_ENTRY_CLIENT(pEntry)) /* Only Clent entry need the retry timer.*/
+ {
+ RTMPInitTimer(pAd, &pEntry->RetryTimer, GET_TIMER_FUNCTION(WPARetryExec), pEntry, FALSE);
+
+ /* RTMP_OS_Init_Timer(pAd, &pEntry->RetryTimer, GET_TIMER_FUNCTION(WPARetryExec), pAd);*/
+ }
+#ifdef APCLI_SUPPORT
+ else if (IS_ENTRY_APCLI(pEntry))
+ {
+ RTMPInitTimer(pAd, &pEntry->RetryTimer, GET_TIMER_FUNCTION(WPARetryExec), pEntry, FALSE);
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef TXBF_SUPPORT
+ if (pAd->chipCap.FlgHwTxBfCap)
+ RTMPInitTimer(pAd, &pEntry->eTxBfProbeTimer, GET_TIMER_FUNCTION(eTxBfProbeTimerExec), pEntry, FALSE);
+#endif /* TXBF_SUPPORT */
+
+ pEntry->pAd = pAd;
+ pEntry->CMTimerRunning = FALSE;
+ pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+ pEntry->RSNIE_Len = 0;
+ NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
+ pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
+
+ if (IS_ENTRY_MESH(pEntry))
+ pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
+ else if (IS_ENTRY_APCLI(pEntry))
+ pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
+ else if (IS_ENTRY_WDS(pEntry))
+ pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
+ else
+ pEntry->apidx = apidx;
+
+#ifdef CONFIG_AP_SUPPORT
+ if ((apidx < pAd->ApCfg.BssidNum) &&
+ (apidx < MAX_MBSSID_NUM(pAd)) &&
+ (apidx < HW_BEACON_MAX_NUM))
+ pEntry->pMbss = &pAd->ApCfg.MBSSID[pEntry->apidx];
+ else
+ pEntry->pMbss = NULL;
+#endif /* CONFIG_AP_SUPPORT */
+
+ do
+ {
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(pEntry))
+ {
+ pEntry->AuthMode = pAd->ApCfg.ApCliTab[pEntry->apidx].AuthMode;
+ pEntry->WepStatus = pAd->ApCfg.ApCliTab[pEntry->apidx].WepStatus;
+
+ if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
+ {
+ pEntry->WpaState = AS_NOTUSE;
+ pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
+ }
+ else
+ {
+ pEntry->WpaState = AS_PTKSTART;
+ pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
+ }
+ pEntry->MatchAPCLITabIdx = pEntry->apidx;
+ break;
+ }
+#endif /* APCLI_SUPPORT */
+#ifdef WDS_SUPPORT
+ if (IS_ENTRY_WDS(pEntry))
+ {
+ pEntry->AuthMode = Ndis802_11AuthModeOpen;
+ pEntry->WepStatus = Ndis802_11EncryptionDisabled;
+
+ pEntry->MatchWDSTabIdx = pEntry->apidx;
+ break;
+ }
+#endif /* WDS_SUPPORT */
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ MBSS_MR_APIDX_SANITY_CHECK(pAd, apidx);
+ pEntry->AuthMode = pAd->ApCfg.MBSSID[apidx].AuthMode;
+ pEntry->WepStatus = pAd->ApCfg.MBSSID[apidx].WepStatus;
+ pEntry->GroupKeyWepStatus = pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus;
+
+ if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
+ pEntry->WpaState = AS_NOTUSE;
+ else
+ pEntry->WpaState = AS_INITIALIZE;
+
+ pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
+ pEntry->StaIdleTimeout = pAd->ApCfg.StaIdleTimeout;
+ pAd->ApCfg.MBSSID[apidx].StaCount++;
+ pAd->ApCfg.EntryClientCount++;
+ break;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ } while (FALSE);
+
+ pEntry->GTKState = REKEY_NEGOTIATING;
+ pEntry->PairwiseKey.KeyLen = 0;
+ pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
+ pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+
+ pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
+ COPY_MAC_ADDR(pEntry->Addr, pAddr);
+ COPY_MAC_ADDR(pEntry->HdrAddr1, pAddr);
+
+ do
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(pEntry))
+ {
+ COPY_MAC_ADDR(pEntry->HdrAddr2, pAd->ApCfg.ApCliTab[pEntry->apidx].CurrentAddress);
+ COPY_MAC_ADDR(pEntry->HdrAddr3, pAddr);
+ break;
+ }
+#endif // APCLI_SUPPORT //
+#ifdef WDS_SUPPORT
+ if (IS_ENTRY_WDS(pEntry))
+ {
+ COPY_MAC_ADDR(pEntry->HdrAddr2, pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid);
+ COPY_MAC_ADDR(pEntry->HdrAddr3, pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid);
+ break;
+ }
+#endif // WDS_SUPPORT //
+#ifdef CONFIG_AP_SUPPORT
+ if (OpMode == OPMODE_AP)
+ {
+ COPY_MAC_ADDR(pEntry->HdrAddr2, pAd->ApCfg.MBSSID[apidx].Bssid);
+ COPY_MAC_ADDR(pEntry->HdrAddr3, pAd->ApCfg.MBSSID[apidx].Bssid);
+ break;
+ }
+#endif // CONFIG_AP_SUPPORT //
+ } while (FALSE);
+
+ pEntry->Sst = SST_NOT_AUTH;
+ pEntry->AuthState = AS_NOT_AUTH;
+ pEntry->Aid = (USHORT)i; /*0;*/
+ pEntry->CapabilityInfo = 0;
+ pEntry->PsMode = PWR_ACTIVE;
+ pEntry->PsQIdleCount = 0;
+ pEntry->NoDataIdleCount = 0;
+ pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT;
+ pEntry->ContinueTxFailCnt = 0;
+#ifdef WDS_SUPPORT
+ pEntry->LockEntryTx = FALSE;
+#endif /* WDS_SUPPORT */
+ pEntry->TimeStamp_toTxRing = 0;
+ InitializeQueueHeader(&pEntry->PsQueue);
+
+#ifdef STREAM_MODE_SUPPORT
+ /* Enable Stream mode for first three entries in MAC table */
+
+#endif /* STREAM_MODE_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef UAPSD_SUPPORT
+ if (IS_ENTRY_CLIENT(pEntry)) /* Ralink WDS doesn't support any power saving.*/
+ {
+ /* init U-APSD enhancement related parameters */
+ UAPSD_MR_ENTRY_INIT(pEntry);
+ }
+#endif /* UAPSD_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ pAd->MacTab.Size ++;
+
+ /* Set the security mode of this entry as OPEN-NONE in ASIC */
+ RTMP_REMOVE_PAIRWISE_KEY_ENTRY(pAd, (UCHAR)i);
+
+ /* Add this entry into ASIC RX WCID search table */
+ RTMP_STA_ENTRY_ADD(pAd, pEntry);
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef WSC_AP_SUPPORT
+ pEntry->bWscCapable = FALSE;
+ pEntry->Receive_EapolStart_EapRspId = 0;
+#endif /* WSC_AP_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef TXBF_SUPPORT
+ if (pAd->chipCap.FlgHwTxBfCap)
+ NdisAllocateSpinLock(pAd, &pEntry->TxSndgLock);
+#endif /* TXBF_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
+ break;
+ }
+ }
+
+ /* add this MAC entry into HASH table */
+ if (pEntry)
+ {
+
+ HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+ if (pAd->MacTab.Hash[HashIdx] == NULL)
+ {
+ pAd->MacTab.Hash[HashIdx] = pEntry;
+ }
+ else
+ {
+ pCurrEntry = pAd->MacTab.Hash[HashIdx];
+ while (pCurrEntry->pNext != NULL)
+ pCurrEntry = pCurrEntry->pNext;
+ pCurrEntry->pNext = pEntry;
+ }
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+
+#ifdef WSC_AP_SUPPORT
+ if (IS_ENTRY_CLIENT(pEntry) &&
+ (pEntry->apidx < pAd->ApCfg.BssidNum) &&
+ MAC_ADDR_EQUAL(pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr))
+ {
+ NdisZeroMemory(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, MAC_ADDR_LEN);
+ }
+#endif /* WSC_AP_SUPPORT */
+
+
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ }
+
+ NdisReleaseSpinLock(&pAd->MacTabLock);
+ return pEntry;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Delete a specified client from MAC table
+ ==========================================================================
+ */
+BOOLEAN MacTableDeleteEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT wcid,
+ IN PUCHAR pAddr)
+{
+ USHORT HashIdx;
+ MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
+ BOOLEAN Cancelled;
+ /*USHORT offset; unused variable*/
+ /*UCHAR j; unused variable*/
+
+ if (wcid >= MAX_LEN_OF_MAC_TABLE)
+ return FALSE;
+
+ NdisAcquireSpinLock(&pAd->MacTabLock);
+
+ HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+ /*pEntry = pAd->MacTab.Hash[HashIdx];*/
+ pEntry = &pAd->MacTab.Content[wcid];
+
+ if (pEntry && !IS_ENTRY_NONE(pEntry))
+ {
+ /* ENTRY PREEMPTION: Cancel all timers */
+ RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
+ RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
+
+ if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
+ {
+
+#ifdef DOT11_N_SUPPORT
+ /* free resources of BA*/
+ BASessionTearDownALL(pAd, pEntry->Aid);
+#endif /* DOT11_N_SUPPORT */
+
+ /* Delete this entry from ASIC on-chip WCID Table*/
+ RTMP_STA_ENTRY_MAC_RESET(pAd, wcid);
+
+#ifdef TXBF_SUPPORT
+ if (pAd->chipCap.FlgHwTxBfCap)
+ RTMPReleaseTimer(&pEntry->eTxBfProbeTimer, &Cancelled);
+#endif /* TXBF_SUPPORT */
+
+#ifdef STREAM_MODE_SUPPORT
+ /* Clear Stream Mode register for this client */
+ if (pEntry->StreamModeMACReg != 0)
+ RTMP_IO_WRITE32(pAd, pEntry->StreamModeMACReg+4, 0);
+#endif // STREAM_MODE_SUPPORT //
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+ if (IS_ENTRY_CLIENT(pEntry)
+ )
+ {
+#ifdef DOT1X_SUPPORT
+ INT PmkCacheIdx = -1;
+#endif /* DOT1X_SUPPORT */
+
+ RTMPReleaseTimer(&pEntry->RetryTimer, &Cancelled);
+
+#ifdef DOT1X_SUPPORT
+ /* Notify 802.1x daemon to clear this sta info*/
+ if (pEntry->AuthMode == Ndis802_11AuthModeWPA ||
+ pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
+ pAd->ApCfg.MBSSID[pEntry->apidx].IEEE8021X)
+ DOT1X_InternalCmdAction(pAd, pEntry, DOT1X_DISCONNECT_ENTRY);
+
+ /* Delete the PMK cache for this entry if it exists.*/
+ if ((PmkCacheIdx = RTMPSearchPMKIDCache(pAd, pEntry->apidx, pEntry->Addr)) != -1)
+ {
+ RTMPDeletePMKIDCache(pAd, pEntry->apidx, PmkCacheIdx);
+ }
+#endif /* DOT1X_SUPPORT */
+
+#ifdef WAPI_SUPPORT
+ RTMPCancelWapiRekeyTimerAction(pAd, pEntry);
+#endif /* WAPI_SUPPORT */
+
+#ifdef IGMP_SNOOP_SUPPORT
+ IgmpGroupDelMembers(pAd, (PUCHAR)pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].MSSIDDev);
+#endif /* IGMP_SNOOP_SUPPORT */
+ pAd->ApCfg.MBSSID[pEntry->apidx].StaCount--;
+ pAd->ApCfg.EntryClientCount--;
+
+#ifdef HOSTAPD_SUPPORT
+ if(pEntry && pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == TRUE )
+ {
+ RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, -1, pEntry->Addr,
+ NULL, 0,pEntry->apidx);
+ }
+#endif
+ }
+#ifdef APCLI_SUPPORT
+ else if (IS_ENTRY_APCLI(pEntry))
+ {
+ RTMPReleaseTimer(&pEntry->RetryTimer, &Cancelled);
+ }
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ pPrevEntry = NULL;
+ pProbeEntry = pAd->MacTab.Hash[HashIdx];
+ ASSERT(pProbeEntry);
+ if (pProbeEntry != NULL)
+ {
+ /* update Hash list*/
+ do
+ {
+ if (pProbeEntry == pEntry)
+ {
+ if (pPrevEntry == NULL)
+ {
+ pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
+ }
+ else
+ {
+ pPrevEntry->pNext = pEntry->pNext;
+ }
+ break;
+ }
+
+ pPrevEntry = pProbeEntry;
+ pProbeEntry = pProbeEntry->pNext;
+ } while (pProbeEntry);
+ }
+
+ /* not found !!!*/
+ ASSERT(pProbeEntry != NULL);
+
+#ifdef CONFIG_AP_SUPPORT
+ APCleanupPsQueue(pAd, &pEntry->PsQueue); /* return all NDIS packet in PSQ*/
+#endif /* CONFIG_AP_SUPPORT */
+ /*RTMP_REMOVE_PAIRWISE_KEY_ENTRY(pAd, wcid);*/
+
+#ifdef UAPSD_SUPPORT
+#ifdef CONFIG_AP_SUPPORT
+ UAPSD_MR_ENTRY_RESET(pAd, pEntry);
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* UAPSD_SUPPORT */
+
+ if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
+ {
+ RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
+ pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+ }
+ RTMPReleaseTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef WSC_AP_SUPPORT
+ if (IS_ENTRY_CLIENT(pEntry))
+ {
+ PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[pEntry->apidx].WscControl;
+ if (MAC_ADDR_EQUAL(pEntry->Addr, pWscControl->EntryAddr))
+ {
+ /*
+ Some WPS Client will send dis-assoc close to WSC_DONE.
+ If AP misses WSC_DONE, WPS Client still sends dis-assoc to AP.
+ Do not cancel timer if WscState is WSC_STATE_WAIT_DONE.
+ */
+ if ((pWscControl->EapolTimerRunning == TRUE) &&
+ (pWscControl->WscState != WSC_STATE_WAIT_DONE))
+ {
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+ pWscControl->EapolTimerRunning = FALSE;
+ pWscControl->EapMsgRunning = FALSE;
+ NdisZeroMemory(&(pWscControl->EntryAddr[0]), MAC_ADDR_LEN);
+ }
+ }
+ pEntry->Receive_EapolStart_EapRspId = 0;
+ pEntry->bWscCapable = FALSE;
+ }
+#endif /* WSC_AP_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+// NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
+ NdisZeroMemory(pEntry->Addr, MAC_ADDR_LEN);
+ /* invalidate the entry */
+ SET_ENTRY_NONE(pEntry);
+ pAd->MacTab.Size --;
+#ifdef TXBF_SUPPORT
+ if (pAd->chipCap.FlgHwTxBfCap)
+ NdisFreeSpinLock(&pEntry->TxSndgLock);
+#endif /* TXBF_SUPPORT */
+ DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("\n%s: Impossible Wcid = %d !!!!!\n", __FUNCTION__, wcid));
+ }
+ }
+
+ NdisReleaseSpinLock(&pAd->MacTabLock);
+
+ /*Reset operating mode when no Sta.*/
+ if (pAd->MacTab.Size == 0)
+ {
+#ifdef DOT11_N_SUPPORT
+ pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
+#endif /* DOT11_N_SUPPORT */
+ RTMP_UPDATE_PROTECT(pAd, 0, ALLN_SETPROTECT, TRUE, 0);
+ }
+#ifdef CONFIG_AP_SUPPORT
+ /*APUpdateCapabilityAndErpIe(pAd);*/
+ RTMP_AP_UPDATE_CAPABILITY_AND_ERPIE(pAd); /* edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet*/
+#endif /* CONFIG_AP_SUPPORT */
+
+ return TRUE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ This routine reset the entire MAC table. All packets pending in
+ the power-saving queues are freed here.
+ ==========================================================================
+ */
+VOID MacTableReset(
+ IN PRTMP_ADAPTER pAd)
+{
+ int i;
+ BOOLEAN Cancelled;
+#ifdef CONFIG_AP_SUPPORT
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ HEADER_802_11 DeAuthHdr;
+ USHORT Reason;
+ UCHAR apidx = MAIN_MBSSID;
+#endif /* CONFIG_AP_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
+ /*NdisAcquireSpinLock(&pAd->MacTabLock);*/
+
+
+ for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i]))
+ {
+ /* Delete a entry via WCID */
+
+ /*MacTableDeleteEntry(pAd, i, pAd->MacTab.Content[i].Addr);*/
+ RTMPReleaseTimer(&pAd->MacTab.Content[i].EnqueueStartForPSKTimer, &Cancelled);
+ pAd->MacTab.Content[i].EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* Before reset MacTable, send disassociation packet to client.*/
+ if (pAd->MacTab.Content[i].Sst == SST_ASSOC)
+ {
+ /* send out a De-authentication request frame*/
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, (" MlmeAllocateMemory fail ..\n"));
+ /*NdisReleaseSpinLock(&pAd->MacTabLock);*/
+ return;
+ }
+
+ Reason = REASON_NO_LONGER_VALID;
+ DBGPRINT(RT_DEBUG_WARN, ("Send DEAUTH - Reason = %d frame tO %02x:%02x:%02x:%02x:%02x:%02x \n",Reason, PRINT_MAC(pAd->MacTab.Content[i].Addr)));
+ MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pAd->MacTab.Content[i].Addr,
+ pAd->ApCfg.MBSSID[pAd->MacTab.Content[i].apidx].Bssid);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &DeAuthHdr,
+ 2, &Reason,
+ END_OF_ARGS);
+
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+ RTMPusecDelay(5000);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Delete a entry via WCID */
+ MacTableDeleteEntry(pAd, i, pAd->MacTab.Content[i].Addr);
+ }
+ else
+ {
+ /* Delete a entry via WCID */
+ MacTableDeleteEntry(pAd, i, pAd->MacTab.Content[i].Addr);
+ }
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ for (apidx = MAIN_MBSSID; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+#ifdef WSC_AP_SUPPORT
+ BOOLEAN Cancelled;
+
+ RTMPCancelTimer(&pAd->ApCfg.MBSSID[apidx].WscControl.EapolTimer, &Cancelled);
+ pAd->ApCfg.MBSSID[apidx].WscControl.EapolTimerRunning = FALSE;
+ NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].WscControl.EntryAddr, MAC_ADDR_LEN);
+ pAd->ApCfg.MBSSID[apidx].WscControl.EapMsgRunning = FALSE;
+#endif /* WSC_AP_SUPPORT */
+ pAd->ApCfg.MBSSID[apidx].StaCount = 0;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("McastPsQueue.Number %ld...\n",pAd->MacTab.McastPsQueue.Number));
+ if (pAd->MacTab.McastPsQueue.Number > 0)
+ APCleanupPsQueue(pAd, &pAd->MacTab.McastPsQueue);
+ DBGPRINT(RT_DEBUG_TRACE, ("2McastPsQueue.Number %ld...\n",pAd->MacTab.McastPsQueue.Number));
+
+ /* ENTRY PREEMPTION: Zero Mac Table but entry's content */
+/* NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE));*/
+ NdisZeroMemory(&pAd->MacTab.Size,
+ sizeof(MAC_TABLE)-
+ sizeof(pAd->MacTab.Hash)-
+ sizeof(pAd->MacTab.Content));
+
+ InitializeQueueHeader(&pAd->MacTab.McastPsQueue);
+ /*NdisReleaseSpinLock(&pAd->MacTabLock);*/
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID AssocParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
+ IN PUCHAR pAddr,
+ IN USHORT CapabilityInfo,
+ IN ULONG Timeout,
+ IN USHORT ListenIntv)
+{
+ COPY_MAC_ADDR(AssocReq->Addr, pAddr);
+ /* Add mask to support 802.11b mode only */
+ AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; /* not cf-pollable, not cf-poll-request*/
+ AssocReq->Timeout = Timeout;
+ AssocReq->ListenIntv = ListenIntv;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID DisassocParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
+ IN PUCHAR pAddr,
+ IN USHORT Reason)
+{
+ COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
+ DisassocReq->Reason = Reason;
+}
+
+
+BOOLEAN RTMPCheckEtherType(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN PMAC_TABLE_ENTRY pMacEntry,
+ IN UCHAR OpMode,
+ OUT PUCHAR pUserPriority,
+ OUT PUCHAR pQueIdx)
+{
+ USHORT TypeLen;
+ UCHAR Byte0, Byte1;
+ PUCHAR pSrcBuf;
+ UINT32 pktLen;
+ UINT16 srcPort, dstPort;
+#ifdef CONFIG_AP_SUPPORT
+ MULTISSID_STRUCT *pMbss;
+#endif /* CONFIG_AP_SUPPORT */
+ BOOLEAN bWmmReq;
+
+#ifdef CONFIG_AP_SUPPORT
+/* if (IS_ENTRY_CLIENT(pMacEntry))*/
+/* pMbss = pMacEntry->pMbss;*/
+/* else*/
+/* pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID];*/
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* for APClient, WDS, Mesh, they use MAIN BSS */
+ UCHAR apidx;
+ apidx = RTMP_GET_PACKET_NET_DEVICE(pPacket);
+ if (apidx >= MAX_MBSSID_NUM(pAd))
+ apidx = MAIN_MBSSID;
+ pMbss = &pAd->ApCfg.MBSSID[apidx];
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /*
+ for bc/mc packets, if it has VLAN tag or DSCP field, we also need
+ to get UP for IGMP use.
+ */
+ bWmmReq = (
+#ifdef CONFIG_AP_SUPPORT
+ (
+ (pMbss->bWmmCapable)) ||
+#endif /* CONFIG_AP_SUPPORT */
+ OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
+ && ((pMacEntry) &&
+ ((VALID_WCID(pMacEntry->Aid) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
+ || (pMacEntry->Aid == MCAST_WCID)));
+
+ pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
+ pktLen = GET_OS_PKT_LEN(pPacket);
+
+ ASSERT(pSrcBuf);
+
+ RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
+
+ /* get Ethernet protocol field*/
+ TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13];
+
+ pSrcBuf += LENGTH_802_3; /* Skip the Ethernet Header.*/
+
+ if (TypeLen <= 1500)
+ { /* 802.3, 802.3 LLC*/
+ /*
+ DestMAC(6) + SrcMAC(6) + Lenght(2) +
+ DSAP(1) + SSAP(1) + Control(1) +
+ if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
+ => + SNAP (5, OriginationID(3) + etherType(2))
+ */
+ if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
+ {
+ Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 6, &Byte0, &Byte1);
+ RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
+ TypeLen = (USHORT)((Byte0 << 8) + Byte1);
+ pSrcBuf += 8; /* Skip this LLC/SNAP header*/
+ }
+ else
+ {
+ /*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.*/
+ }
+ }
+
+ /* If it's a VLAN packet, get the real Type/Length field.*/
+ if (TypeLen == 0x8100)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ USHORT VLAN_VID = 0;
+
+ /* 0x8100 means VLAN packets */
+
+ /* Dest. MAC Address (6-bytes) +
+ Source MAC Address (6-bytes) +
+ Length/Type = 802.1Q Tag Type (2-byte) +
+ Tag Control Information (2-bytes) +
+ Length / Type (2-bytes) +
+ data payload (0-n bytes) +
+ Pad (0-p bytes) +
+ Frame Check Sequence (4-bytes) */
+
+ /* No matter unicast or multicast */
+ /*if (IS_ENTRY_CLIENT(pMacEntry))*/
+#ifdef WDS_VLAN_SUPPORT
+ if (IS_ENTRY_WDS(pMacEntry))
+ {
+ UINT32 WdsId;
+
+ WdsId = RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_WDS;
+ if (WdsId < MAX_WDS_ENTRY)
+ VLAN_VID = pAd->WdsTab.WdsEntry[WdsId].VLAN_VID;
+ }
+ else
+#endif /* WDS_VLAN_SUPPORT */
+ {
+ VLAN_VID = pMbss->VLAN_VID;
+ } /* End of if */
+
+ if (VLAN_VID != 0)
+ {
+ /* check if the packet is my VLAN */
+ /* VLAN tag: 3-bit UP + 1-bit CFI + 12-bit VLAN ID */
+ USHORT vlan_id = *(USHORT *)pSrcBuf;
+
+ vlan_id = cpu2be16(vlan_id);
+ vlan_id = vlan_id & 0x0FFF; /* 12 bit */
+ if (vlan_id != VLAN_VID)
+ {
+ /* not my VLAN packet, discard it */
+ return FALSE;
+ } /* End of if */
+ } /* End of if */
+#endif /* CONFIG_AP_SUPPORT */
+
+ RTMP_SET_PACKET_VLAN(pPacket, 1);
+ Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 2, &Byte0, &Byte1);
+ TypeLen = (USHORT)((Byte0 << 8) + Byte1);
+
+ /* only use VLAN tag */
+ if (bWmmReq)
+ {
+ *pUserPriority = (*pSrcBuf & 0xe0) >> 5;
+ *pQueIdx = MapUserPriorityToAccessCategory[*pUserPriority];
+ }
+
+ pSrcBuf += 4; /* Skip the VLAN Header.*/
+ }
+ else if (TypeLen == 0x0800)
+ {
+ if (bWmmReq)
+ {
+ if ((*pSrcBuf & 0xf0) == 0x40) /* IPv4 */
+ {
+ /*
+ Version - 4-bit Internet Protocol version number.
+ Length - 4-bit IP header length.
+ Traffic Class - 8-bit TOS field.
+ */
+ *pUserPriority = (*(pSrcBuf + 1) & 0xe0) >> 5;
+ }
+
+ *pQueIdx = MapUserPriorityToAccessCategory[*pUserPriority];
+ }
+ }
+ else if (TypeLen == 0x86dd)
+ {
+ if (bWmmReq)
+ {
+ if ((*pSrcBuf & 0xf0) == 0x60) /* IPv6 */
+ {
+ /*
+ Version - 4-bit Internet Protocol version number.
+ Traffic Class - 8-bit traffic class field.
+ */
+ *pUserPriority = ((*pSrcBuf) & 0x0e) >> 1;
+ }
+
+ *pQueIdx = MapUserPriorityToAccessCategory[*pUserPriority];
+ }
+ }
+
+ switch (TypeLen)
+ {
+ case 0x0800:
+ {
+ /* return AC_BE if packet is not IPv4*/
+ if (bWmmReq && (*pSrcBuf & 0xf0) != 0x40)
+ {
+ *pUserPriority = 0;
+ *pQueIdx = QID_AC_BE;
+ }
+ else
+ RTMP_SET_PACKET_IPV4(pPacket, 1);
+
+ ASSERT((pktLen > 34));
+ if (*(pSrcBuf + 9) == 0x11)
+ { /* udp packet*/
+ ASSERT((pktLen > 34)); /* 14 for ethernet header, 20 for IP header*/
+
+ pSrcBuf += 20; /* Skip the IP header*/
+ srcPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf)));
+ dstPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf+2)));
+
+ if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
+ { /*It's a BOOTP/DHCP packet*/
+ RTMP_SET_PACKET_DHCP(pPacket, 1);
+ }
+ }
+ }
+ break;
+ case 0x86dd:
+ {
+ /* return AC_BE if packet is not IPv6 */
+ if (bWmmReq &&
+ ((*pSrcBuf & 0xf0) != 0x60))
+ {
+ *pUserPriority = 0;
+ *pQueIdx = QID_AC_BE;
+ }
+ }
+ break;
+ case 0x0806:
+ {
+ /*ARP Packet.*/
+ RTMP_SET_PACKET_DHCP(pPacket, 1);
+ }
+ break;
+ case 0x888e:
+ {
+ /* EAPOL Packet.*/
+ RTMP_SET_PACKET_EAPOL(pPacket, 1);
+ }
+ break;
+#ifdef WAPI_SUPPORT
+ case 0x88b4:
+ {
+ /* WAI Packet.*/
+ /*hex_dump("WAI Packet", pSrcBuf, pktLen);*/
+ RTMP_SET_PACKET_WAI(pPacket, 1);
+ }
+ break;
+#endif /* WAPI_SUPPORT */
+
+
+ default:
+ break;
+ }
+
+#ifdef VENDOR_FEATURE1_SUPPORT
+ RTMP_SET_PACKET_PROTOCOL(pPacket, TypeLen);
+#endif /* VENDOR_FEATURE1_SUPPORT */
+
+ /* have to check ACM bit. downgrade UP & QueIdx before passing ACM*/
+ /* NOTE: AP doesn't have to negotiate TSPEC. ACM is controlled purely via user setup, not protocol handshaking*/
+ /*
+ Under WMM ACM control, we dont need to check the bit;
+ Or when a TSPEC is built for VO but we will change priority to
+ BE here and when we issue a BA session, the BA session will
+ be BE session, not VO session.
+ */
+ if (pAd->CommonCfg.APEdcaParm.bACM[*pQueIdx])
+ {
+ *pUserPriority = 0;
+ *pQueIdx = QID_AC_BE;
+ }
+
+
+ return TRUE;
+
+}
+
+
+VOID Update_Rssi_Sample(
+ IN PRTMP_ADAPTER pAd,
+ IN RSSI_SAMPLE *pRssi,
+ IN PRXWI_STRUC pRxWI)
+{
+ CHAR rssi0 = pRxWI->RSSI0;
+ CHAR rssi1 = pRxWI->RSSI1;
+ CHAR rssi2 = pRxWI->RSSI2;
+ UCHAR snr0 = pRxWI->SNR0;
+ UCHAR snr1 = pRxWI->SNR1;
+ CHAR Phymode = pRxWI->PHYMODE;
+ BOOLEAN bInitial = FALSE;
+
+ if (!(pRssi->AvgRssi0 | pRssi->AvgRssi0X8 | pRssi->LastRssi0))
+ {
+ bInitial = TRUE;
+ }
+
+ if (rssi0 != 0)
+ {
+
+ pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
+
+ if (bInitial)
+ {
+ pRssi->AvgRssi0X8 = pRssi->LastRssi0 << 3;
+ pRssi->AvgRssi0 = pRssi->LastRssi0;
+ }
+ else
+ {
+ pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
+ }
+
+ pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
+ }
+
+ if (snr0 != 0 && Phymode != MODE_CCK)
+ {
+ pRssi->LastSnr0 = ConvertToSnr(pAd, (UCHAR)snr0);
+
+ if (bInitial)
+ {
+ pRssi->AvgSnr0X8 = pRssi->LastSnr0 << 3;
+ pRssi->AvgSnr0 = pRssi->LastSnr0;
+ }
+ else
+ {
+ pRssi->AvgSnr0X8 = (pRssi->AvgSnr0X8 - pRssi->AvgSnr0) + pRssi->LastSnr0;
+ }
+
+ pRssi->AvgSnr0 = pRssi->AvgSnr0X8 >> 3;
+ /*pRssi->LastNoiseLevel0 = pRssi->AvgRssi0 - pRssi->AvgSnr0;*/
+ }
+
+ if (rssi1 != 0)
+ {
+ pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
+
+ if (bInitial)
+ {
+ pRssi->AvgRssi1X8 = pRssi->LastRssi1 << 3;
+ pRssi->AvgRssi1 = pRssi->LastRssi1;
+ }
+ else
+ {
+ pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
+ }
+
+ pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
+ }
+
+ if (snr1 != 0 && Phymode != MODE_CCK)
+ {
+ pRssi->LastSnr1 = ConvertToSnr(pAd, (UCHAR)snr1);
+
+ if (bInitial)
+ {
+ pRssi->AvgSnr1X8 = pRssi->LastSnr1 << 3;
+ pRssi->AvgSnr1 = pRssi->LastSnr1;
+ }
+ else
+ {
+ pRssi->AvgSnr1X8 = (pRssi->AvgSnr1X8 - pRssi->AvgSnr1) + pRssi->LastSnr1;
+ }
+
+ pRssi->AvgSnr1 = pRssi->AvgSnr1X8 >> 3;
+ /*pRssi->LastNoiseLevel1 = pRssi->AvgRssi1 - pRssi->AvgSnr1;*/
+ }
+
+ if (rssi2 != 0)
+ {
+ pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
+
+ if (bInitial)
+ {
+ pRssi->AvgRssi2X8 = pRssi->LastRssi2 << 3;
+ pRssi->AvgRssi2 = pRssi->LastRssi2;
+ }
+ else
+ {
+ pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
+ }
+
+ pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
+ }
+}
+
+
+
+/* Normal legacy Rx packet indication*/
+VOID Indicate_Legacy_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
+ UCHAR Header802_3[LENGTH_802_3];
+ USHORT VLAN_VID = 0, VLAN_Priority = 0;
+
+ /*
+ 1. get 802.3 Header
+ 2. remove LLC
+ a. pointer pRxBlk->pData to payload
+ b. modify pRxBlk->DataSize
+ */
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
+ {
+
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+
+ STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
+
+#ifdef RTMP_MAC_USB
+#ifdef DOT11_N_SUPPORT
+ if (pAd->CommonCfg.bDisableReordering == 0)
+ {
+ PBA_REC_ENTRY pBAEntry;
+ ULONG Now32;
+ UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
+ UCHAR TID = pRxBlk->pRxWI->TID;
+ USHORT Idx;
+
+#define REORDERING_PACKET_TIMEOUT ((100 * OS_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)))
+ )
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
+ pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU));
+ hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
+ ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
+ }
+ }
+ }
+ }
+#endif /* DOT11_N_SUPPORT */
+#endif /* RTMP_MAC_USB */
+
+#ifdef CONFIG_AP_SUPPORT
+ MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+
+#ifdef WDS_VLAN_SUPPORT
+ if (VLAN_VID == 0) /* maybe WDS packet */
+ WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#endif /* WDS_VLAN_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ RT_80211_TO_8023_PACKET(pAd, VLAN_VID, VLAN_Priority,
+ pRxBlk, Header802_3, FromWhichBSSID, TPID);
+
+ /* pass this 802.3 packet to upper layer or forward this packet to WM directly*/
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
+#endif /* CONFIG_AP_SUPPORT */
+
+}
+
+
+/* Normal, AMPDU or AMSDU*/
+VOID CmmRxnonRalinkFrameIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+#ifdef DOT11_N_SUPPORT
+ if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
+ {
+ Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
+ }
+ else
+#endif /* DOT11_N_SUPPORT */
+ {
+#ifdef DOT11_N_SUPPORT
+ if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
+ {
+ /* handle A-MSDU*/
+ Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
+ }
+ else
+#endif /* DOT11_N_SUPPORT */
+ {
+ Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
+ }
+ }
+}
+
+
+VOID CmmRxRalinkFrameIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ UCHAR Header802_3[LENGTH_802_3];
+ UINT16 Msdu2Size;
+ UINT16 Payload1Size, Payload2Size;
+ PUCHAR pData2;
+ PNDIS_PACKET pPacket2 = NULL;
+ USHORT VLAN_VID = 0, VLAN_Priority = 0;
+
+
+ Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
+
+ if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
+ {
+ /* skip two byte MSDU2 len */
+ pRxBlk->pData += 2;
+ pRxBlk->DataSize -= 2;
+ }
+ else
+ {
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ /* get 802.3 Header and remove LLC*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ ASSERT(pRxBlk->pRxPacket);
+
+ /* Ralink Aggregation frame*/
+ pAd->RalinkCounters.OneSecRxAggregationCount ++;
+ Payload1Size = pRxBlk->DataSize - Msdu2Size;
+ Payload2Size = Msdu2Size - LENGTH_802_3;
+
+ pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ USHORT VLAN_VID = 0, VLAN_Priority = 0;
+
+ MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#ifdef WDS_VLAN_SUPPORT
+ if (VLAN_VID == 0) /* maybe WDS packet */
+ WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#endif /* WDS_VLAN_SUPPORT */
+
+ RT_VLAN_PKT_DUPLICATE(pPacket2, pAd, VLAN_VID, VLAN_Priority,
+ (pData2-LENGTH_802_3), LENGTH_802_3, pData2,
+ Payload2Size, FromWhichBSSID, TPID);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (!pPacket2)
+ {
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ /* update payload size of 1st packet*/
+ pRxBlk->DataSize = Payload1Size;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+
+#ifdef WDS_VLAN_SUPPORT
+ if (VLAN_VID == 0) /* maybe WDS packet */
+ WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#endif /* WDS_VLAN_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ RT_80211_TO_8023_PACKET(pAd, VLAN_VID, VLAN_Priority,
+ pRxBlk, Header802_3, FromWhichBSSID, TPID);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pPacket2)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
+#endif /* CONFIG_AP_SUPPORT */
+ }
+}
+
+
+#define RESET_FRAGFRAME(_fragFrame) \
+ { \
+ _fragFrame.RxSize = 0; \
+ _fragFrame.Sequence = 0; \
+ _fragFrame.LastFrag = 0; \
+ _fragFrame.Flags = 0; \
+ }
+
+
+PNDIS_PACKET RTMPDeFragmentDataFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk)
+{
+ PHEADER_802_11 pHeader = pRxBlk->pHeader;
+ PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
+ UCHAR *pData = pRxBlk->pData;
+ USHORT DataSize = pRxBlk->DataSize;
+ PNDIS_PACKET pRetPacket = NULL;
+ UCHAR *pFragBuffer = NULL;
+ BOOLEAN bReassDone = FALSE;
+ UCHAR HeaderRoom = 0;
+
+
+ ASSERT(pHeader);
+
+ HeaderRoom = pData - (UCHAR *)pHeader;
+
+ /* Re-assemble the fragmented packets*/
+ if (pHeader->Frag == 0) /* Frag. Number is 0 : First frag or only one pkt*/
+ {
+ /* the first pkt of fragment, record it.*/
+ if (pHeader->FC.MoreFrag)
+ {
+ ASSERT(pAd->FragFrame.pFragPacket);
+ pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
+ pAd->FragFrame.RxSize = DataSize + HeaderRoom;
+ NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
+ pAd->FragFrame.Sequence = pHeader->Sequence;
+ pAd->FragFrame.LastFrag = pHeader->Frag; /* Should be 0*/
+ ASSERT(pAd->FragFrame.LastFrag == 0);
+ goto done; /* end of processing this frame*/
+ }
+ }
+ else /*Middle & End of fragment*/
+ {
+ if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
+ (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
+ {
+ /* Fragment is not the same sequence or out of fragment number order*/
+ /* Reset Fragment control blk*/
+ RESET_FRAGFRAME(pAd->FragFrame);
+ DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
+ goto done; /* give up this frame*/
+ }
+ else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
+ {
+ /* Fragment frame is too large, it exeeds the maximum frame size.*/
+ /* Reset Fragment control blk*/
+ RESET_FRAGFRAME(pAd->FragFrame);
+ DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
+ goto done; /* give up this frame*/
+ }
+
+
+ /* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.*/
+ /* In this case, we will dropt it.*/
+
+ if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
+ goto done; /* give up this frame*/
+ }
+
+ pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
+
+ /* concatenate this fragment into the re-assembly buffer*/
+ NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
+ pAd->FragFrame.RxSize += DataSize;
+ pAd->FragFrame.LastFrag = pHeader->Frag; /* Update fragment number*/
+
+ /* Last fragment*/
+ if (pHeader->FC.MoreFrag == FALSE)
+ {
+ bReassDone = TRUE;
+ }
+ }
+
+done:
+ /* always release rx fragmented packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+
+ /* return defragmented packet if packet is reassembled completely*/
+ /* otherwise return NULL*/
+ if (bReassDone)
+ {
+ PNDIS_PACKET pNewFragPacket;
+
+ /* allocate a new packet buffer for fragment*/
+ pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
+ if (pNewFragPacket)
+ {
+ /* update RxBlk*/
+ pRetPacket = pAd->FragFrame.pFragPacket;
+ pAd->FragFrame.pFragPacket = pNewFragPacket;
+ pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
+ pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
+ pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
+ pRxBlk->pRxPacket = pRetPacket;
+ }
+ else
+ {
+ RESET_FRAGFRAME(pAd->FragFrame);
+ }
+ }
+
+ return pRetPacket;
+}
+
+VOID Indicate_EAPOL_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ MAC_TABLE_ENTRY *pEntry = NULL;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (pRxBlk->pRxWI->WirelessCliID >= MAX_LEN_OF_MAC_TABLE)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: invalid wcid.\n"));
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ pEntry = &pAd->MacTab.Content[pRxBlk->pRxWI->WirelessCliID];
+ if (pEntry)
+ {
+ APRxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
+ return;
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if (pEntry == NULL)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+}
+
+#define BCN_TBTT_OFFSET 64 /*defer 64 us*/
+VOID ReSyncBeaconTime(
+ IN PRTMP_ADAPTER pAd)
+{
+
+ UINT32 Offset;
+
+
+ Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
+
+ pAd->TbttTickCount++;
+
+
+ /*
+ The updated BeaconInterval Value will affect Beacon Interval after two TBTT
+ beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
+ */
+ if (Offset == (BCN_TBTT_OFFSET-2))
+ {
+ BCN_TIME_CFG_STRUC csr;
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+ csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; /* ASIC register in units of 1/16 TU = 64us*/
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+ }
+ else
+ {
+ if (Offset == (BCN_TBTT_OFFSET-1))
+ {
+ BCN_TIME_CFG_STRUC csr;
+
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+ csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; /* ASIC register in units of 1/16 TU*/
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+ }
+ }
+}
+
+#ifdef SOFT_ENCRYPT
+BOOLEAN RTMPExpandPacketForSwEncrypt(
+ IN PRTMP_ADAPTER pAd,
+ IN PTX_BLK pTxBlk)
+{
+ PACKET_INFO PacketInfo;
+ UINT32 ex_head = 0, ex_tail = 0;
+ UCHAR NumberOfFrag = RTMP_GET_PACKET_FRAGMENTS(pTxBlk->pPacket);
+
+#ifdef WAPI_SUPPORT
+ if (pTxBlk->CipherAlg == CIPHER_SMS4)
+ ex_tail = LEN_WPI_MIC;
+ else
+#endif /* WAPI_SUPPORT */
+ if (pTxBlk->CipherAlg == CIPHER_AES)
+ ex_tail = LEN_CCMP_MIC;
+
+ ex_tail = (NumberOfFrag * ex_tail);
+
+ pTxBlk->pPacket = ExpandPacket(pAd, pTxBlk->pPacket, ex_head, ex_tail);
+ if (pTxBlk->pPacket == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: out of resource.\n", __FUNCTION__));
+ return FALSE;
+ }
+ RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
+
+ return TRUE;
+}
+
+VOID RTMPUpdateSwCacheCipherInfo(
+ IN PRTMP_ADAPTER pAd,
+ IN PTX_BLK pTxBlk,
+ IN PUCHAR pHdr)
+{
+ PHEADER_802_11 pHeader_802_11;
+ PMAC_TABLE_ENTRY pMacEntry;
+
+ pHeader_802_11 = (HEADER_802_11 *) pHdr;
+ pMacEntry = pTxBlk->pMacEntry;
+
+ if (pMacEntry && pHeader_802_11->FC.Wep &&
+ CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT))
+ {
+ PCIPHER_KEY pKey = &pMacEntry->PairwiseKey;
+
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt);
+
+ pTxBlk->CipherAlg = pKey->CipherAlg;
+ pTxBlk->pKey = pKey;
+#ifdef WAPI_SUPPORT
+ pTxBlk->KeyIdx = pMacEntry->usk_id;
+
+ /* TSC increment pre encryption transmittion */
+ if (pKey->CipherAlg == CIPHER_SMS4)
+ inc_iv_byte(pKey->TxTsc, LEN_WAPI_TSC, 2);
+ else
+#endif /* WAPI_SUPPORT */
+ if ((pKey->CipherAlg == CIPHER_WEP64) || (pKey->CipherAlg == CIPHER_WEP128))
+ inc_iv_byte(pKey->TxTsc, LEN_WEP_TSC, 1);
+ else if ((pKey->CipherAlg == CIPHER_TKIP) || (pKey->CipherAlg == CIPHER_AES))
+ inc_iv_byte(pKey->TxTsc, LEN_WPA_TSC, 1);
+
+ }
+
+}
+
+#endif /* SOFT_ENCRYPT */
+
+/*
+ ==========================================================================
+ Description:
+ Send out a NULL frame to a specified STA at a higher TX rate. The
+ purpose is to ensure the designated client is okay to received at this
+ rate.
+ ==========================================================================
+ */
+VOID RtmpEnqueueNullFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UCHAR TxRate,
+ IN UCHAR PID,
+ IN UCHAR apidx,
+ IN BOOLEAN bQosNull,
+ IN BOOLEAN bEOSP,
+ IN UCHAR OldUP)
+{
+ NDIS_STATUS NState;
+ PHEADER_802_11 pNullFr;
+ PUCHAR pFrame;
+ ULONG Length;
+
+ /* since TxRate may change, we have to change Duration each time */
+ NState = MlmeAllocateMemory(pAd, (PUCHAR *)&pFrame);
+ pNullFr = (PHEADER_802_11) pFrame;
+ Length = sizeof(HEADER_802_11);
+
+ if (NState == NDIS_STATUS_SUCCESS)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ MgtMacHeaderInit(pAd, pNullFr, SUBTYPE_NULL_FUNC, 0, pAddr,
+ pAd->ApCfg.MBSSID[apidx].Bssid);
+#endif /* CONFIG_AP_SUPPORT */
+
+ pNullFr->FC.Type = BTYPE_DATA;
+ pNullFr->FC.FrDs = 1;
+ pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, 14);
+
+
+#ifdef UAPSD_SUPPORT
+ if (bQosNull)
+ {
+ UCHAR *qos_p = ((UCHAR *)pNullFr) + Length;
+
+ pNullFr->FC.SubType = SUBTYPE_QOS_NULL;
+
+ /* copy QOS control bytes */
+ qos_p[0] = ((bEOSP) ? (1 << 4) : 0) | OldUP;
+ qos_p[1] = 0;
+ Length += 2;
+ } /* End of if */
+#endif /* UAPSD_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_INFO, ("send NULL Frame @%d Mbps to AID#%d...\n", RateIdToMbps[TxRate], PID & 0x3f));
+ MiniportMMRequest(pAd, MapUserPriorityToAccessCategory[7], (PUCHAR)pNullFr, Length);
+ MlmeFreeMemory(pAd, pFrame);
+ }
+}
+
+