blob: 2d2c311bc7a4d54c43fdaaebde52eba4cf5df2be [file] [log] [blame]
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001/*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 * *
25 *************************************************************************
26*/
27
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020028#include "../rt_config.h"
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070029
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080030u8 SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
31u8 SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070032
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080033/* Add Cisco Aironet SNAP heade for CCX2 support */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080034u8 SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 };
35u8 CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 };
36u8 EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
37u8 EAPOL[] = { 0x88, 0x8e };
38u8 TPID[] = { 0x81, 0x00 }; /* VLAN related */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070039
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080040u8 IPX[] = { 0x81, 0x37 };
41u8 APPLE_TALK[] = { 0x80, 0xf3 };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070042
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080043u8 RateIdToPlcpSignal[12] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080044 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 *//* see BBP spec */
45 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 *//* see IEEE802.11a-1999 p.14 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080046 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080047}; /* see IEEE802.11a-1999 p.14 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080048
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080049u8 OfdmSignalToRateId[16] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080050 RATE_54, RATE_54, RATE_54, RATE_54, /* OFDM PLCP Signal = 0, 1, 2, 3 respectively */
51 RATE_54, RATE_54, RATE_54, RATE_54, /* OFDM PLCP Signal = 4, 5, 6, 7 respectively */
52 RATE_48, RATE_24, RATE_12, RATE_6, /* OFDM PLCP Signal = 8, 9, 10, 11 respectively */
53 RATE_54, RATE_36, RATE_18, RATE_9, /* OFDM PLCP Signal = 12, 13, 14, 15 respectively */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070054};
55
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080056u8 OfdmRateToRxwiMCS[12] = {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080057 0, 0, 0, 0,
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080058 0, 1, 2, 3, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */
59 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070060};
61
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080062u8 RxwiMCSToOfdmRate[12] = {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080063 RATE_6, RATE_9, RATE_12, RATE_18,
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080064 RATE_24, RATE_36, RATE_48, RATE_54, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */
65 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080066};
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070067
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080068char *MCSToMbps[] =
69 { "1Mbps", "2Mbps", "5.5Mbps", "11Mbps", "06Mbps", "09Mbps", "12Mbps",
70"18Mbps", "24Mbps", "36Mbps", "48Mbps", "54Mbps", "MM-0", "MM-1", "MM-2", "MM-3",
71"MM-4", "MM-5", "MM-6", "MM-7", "MM-8", "MM-9", "MM-10", "MM-11", "MM-12", "MM-13",
72"MM-14", "MM-15", "MM-32", "ee1", "ee2", "ee3" };
73
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080074u8 default_cwmin[] =
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080075 { CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS - 1, CW_MIN_IN_BITS - 2 };
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080076/*u8 default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; */
77u8 default_sta_aifsn[] = { 3, 7, 2, 2 };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070078
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080079u8 MapUserPriorityToAccessCategory[8] =
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080080 { QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI,
81QID_AC_VO, QID_AC_VO };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070082
83/*
84 ========================================================================
85
86 Routine Description:
87 API for MLME to transmit management frame to AP (BSS Mode)
88 or station (IBSS Mode)
89
90 Arguments:
91 pAd Pointer to our adapter
92 pData Pointer to the outgoing 802.11 frame
93 Length Size of outgoing management frame
94
95 Return Value:
96 NDIS_STATUS_FAILURE
97 NDIS_STATUS_PENDING
98 NDIS_STATUS_SUCCESS
99
100 IRQL = PASSIVE_LEVEL
101 IRQL = DISPATCH_LEVEL
102
103 Note:
104
105 ========================================================================
106*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800107int MiniportMMRequest(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800108 u8 QueIdx, u8 *pData, u32 Length)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700109{
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800110 void *pPacket;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800111 int Status = NDIS_STATUS_SUCCESS;
112 unsigned long FreeNum;
113 u8 rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; /*RTMP_HW_HDR_LEN]; */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200114#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800115 unsigned long IrqFlags = 0;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800116 u8 IrqState;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800117#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800118 BOOLEAN bUseDataQ = FALSE;
119 int retryCnt = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700120
121 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
122
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800123 if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200124 bUseDataQ = TRUE;
125 QueIdx &= (~MGMT_USE_QUEUE_FLAG);
126 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200127#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800128 /* 2860C use Tx Ring */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700129 IrqState = pAd->irq_disabled;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800130 if (pAd->MACVersion == 0x28600100) {
131 QueIdx = (bUseDataQ == TRUE ? QueIdx : 3);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200132 bUseDataQ = TRUE;
133 }
134 if (bUseDataQ && (!IrqState))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700135 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800136#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200137
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800138 do {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800139 /* Reset is in progress, stop immediately */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200140 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800141 RTMP_TEST_FLAG(pAd,
142 fRTMP_ADAPTER_HALT_IN_PROGRESS |
143 fRTMP_ADAPTER_NIC_NOT_EXIST)
144 || !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700145 Status = NDIS_STATUS_FAILURE;
146 break;
147 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800148 /* Check Free priority queue */
149 /* Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200150#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800151 if (bUseDataQ) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200152 retryCnt = MAX_DATAMM_RETRY;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800153 /* free Tx(QueIdx) resources */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200154 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700155 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800156 } else
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800157#endif /* RTMP_MAC_PCI // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700158 {
159 FreeNum = GET_MGMTRING_FREENO(pAd);
160 }
161
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800162 if ((FreeNum > 0)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800163 /* We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700164 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800165 Status =
166 RTMPAllocateNdisPacket(pAd, &pPacket,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800167 (u8 *)& rtmpHwHdr,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800168 (TXINFO_SIZE + TXWI_SIZE),
169 pData, Length);
170 if (Status != NDIS_STATUS_SUCCESS) {
171 DBGPRINT(RT_DEBUG_WARN,
172 ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700173 break;
174 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800175 /*pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; */
176 /*pAd->CommonCfg.MlmeRate = RATE_2; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700177
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200178#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800179 if (bUseDataQ) {
180 Status =
181 MlmeDataHardTransmit(pAd, QueIdx, pPacket);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200182 retryCnt--;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800183 } else
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800184#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800185 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200186 if (Status == NDIS_STATUS_SUCCESS)
187 retryCnt = 0;
188 else
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700189 RTMPFreeNdisPacket(pAd, pPacket);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800190 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700191 pAd->RalinkCounters.MgmtRingFullCount++;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200192#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800193 if (bUseDataQ) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200194 retryCnt--;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800195 DBGPRINT(RT_DEBUG_TRACE,
196 ("retryCnt %d\n", retryCnt));
197 if (retryCnt == 0) {
198 DBGPRINT(RT_DEBUG_ERROR,
199 ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
200 QueIdx,
201 pAd->RalinkCounters.
202 MgmtRingFullCount));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200203 }
204 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800205#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800206 DBGPRINT(RT_DEBUG_ERROR,
207 ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
208 QueIdx,
209 pAd->RalinkCounters.MgmtRingFullCount));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700210 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200211 } while (retryCnt > 0);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700212
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200213#ifdef RTMP_MAC_PCI
214 if (bUseDataQ && (!IrqState))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700215 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800216#endif /* RTMP_MAC_PCI // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700217
218 return Status;
219}
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200220
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700221/*
222 ========================================================================
223
224 Routine Description:
225 Copy frame from waiting queue into relative ring buffer and set
226 appropriate ASIC register to kick hardware transmit function
227
228 Arguments:
229 pAd Pointer to our adapter
230 pBuffer Pointer to memory of outgoing frame
231 Length Size of outgoing management frame
232
233 Return Value:
234 NDIS_STATUS_FAILURE
235 NDIS_STATUS_PENDING
236 NDIS_STATUS_SUCCESS
237
238 IRQL = PASSIVE_LEVEL
239 IRQL = DISPATCH_LEVEL
240
241 Note:
242
243 ========================================================================
244*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800245int MlmeHardTransmit(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800246 u8 QueIdx, void *pPacket)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700247{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800248 struct rt_packet_info PacketInfo;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800249 u8 *pSrcBufVA;
250 u32 SrcBufLen;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800251 struct rt_header_802_11 * pHeader_802_11;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200252
253 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800254 ) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700255 return NDIS_STATUS_FAILURE;
256 }
257
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200258 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
259 if (pSrcBufVA == NULL)
260 return NDIS_STATUS_FAILURE;
261
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800262 pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200263
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200264#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800265 if (pAd->MACVersion == 0x28600100)
266 return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700267 else
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800268#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800269 return MlmeHardTransmitMgmtRing(pAd, QueIdx, pPacket);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700270
271}
272
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800273int MlmeHardTransmitMgmtRing(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800274 u8 QueIdx, void *pPacket)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700275{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800276 struct rt_packet_info PacketInfo;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800277 u8 *pSrcBufVA;
278 u32 SrcBufLen;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800279 struct rt_header_802_11 * pHeader_802_11;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800280 BOOLEAN bAckRequired, bInsertTimestamp;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800281 u8 MlmeRate;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800282 struct rt_txwi * pFirstTxWI;
283 struct rt_mac_table_entry *pMacEntry = NULL;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800284 u8 PID;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700285
286 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700287
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800288 /* Make sure MGMT ring resource won't be used by other threads */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200289 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800290 if (pSrcBufVA == NULL) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800291 /* The buffer shouldn't be NULL */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700292 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
293 return NDIS_STATUS_FAILURE;
294 }
295
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200296 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800297 /* outgoing frame always wakeup PHY to prevent frame lost */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800298 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
299 AsicForceWakeup(pAd, TRUE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200300 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700301
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800302 pFirstTxWI = (struct rt_txwi *) (pSrcBufVA + TXINFO_SIZE);
303 pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); /*TXWI_SIZE); */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700304
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800305 if (pHeader_802_11->Addr1[0] & 0x01) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700306 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800307 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700308 MlmeRate = pAd->CommonCfg.MlmeRate;
309 }
310
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800311 /* Verify Mlme rate for a / g bands. */
312 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700313 MlmeRate = RATE_6;
314
315 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800316 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700317 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
318 }
319
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700320 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800321 /* Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700322 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800323 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700324 if (pAd->LatchRfRegs.Channel > 14)
325 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
326 else
327 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
328 }
329 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700330
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800331 /* */
332 /* Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) */
333 /* Snice it's been set to 0 while on MgtMacHeaderInit */
334 /* By the way this will cause frame to be send on PWR_SAVE failed. */
335 /* */
336 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; /* (pAd->StaCfg.Psm == PWR_SAVE); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200337
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800338 /* */
339 /* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */
340 /* Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */
341/* if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700342 {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200343 if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800344 ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
345 ((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) ||
346 (pHeader_802_11->FC.SubType == SUBTYPE_NULL_FUNC)))) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200347 if (pAd->StaCfg.Psm == PWR_SAVE)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800348 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
349 else
350 pHeader_802_11->FC.PwrMgmt =
351 pAd->CommonCfg.bAPSDForcePowerSave;
352 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700353 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700354
355 bInsertTimestamp = FALSE;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800356 if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700357 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800358 /*Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800359 if ((pAd->OpMode == OPMODE_STA)
360 && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700361 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
362 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700363 bAckRequired = FALSE;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800364 } else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame) */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700365 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800366 /*pAd->Sequence++; */
367 /*pHeader_802_11->Sequence = pAd->Sequence; */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200368
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800369 if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700370 {
371 bAckRequired = FALSE;
372 pHeader_802_11->Duration = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800373 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700374 bAckRequired = TRUE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800375 pHeader_802_11->Duration =
376 RTMPCalcDuration(pAd, MlmeRate, 14);
377 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
378 && (pHeader_802_11->FC.Type == BTYPE_MGMT)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700379 bInsertTimestamp = TRUE;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800380 bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Response */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800381 } else
382 if ((pHeader_802_11->FC.SubType ==
383 SUBTYPE_PROBE_REQ)
384 && (pHeader_802_11->FC.Type == BTYPE_MGMT)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800385 bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Request */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700386 }
387 }
388 }
389
390 pHeader_802_11->Sequence = pAd->Sequence++;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800391 if (pAd->Sequence > 0xfff)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700392 pAd->Sequence = 0;
393
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800394 /* Before radar detection done, mgmt frame can not be sent but probe req */
395 /* Because we need to use probe req to trigger driver to send probe req in passive scan */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700396 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800397 && (pAd->CommonCfg.bIEEE80211H == 1)
398 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) {
399 DBGPRINT(RT_DEBUG_ERROR,
400 ("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800401/* if (!IrqState) */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700402 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
403 return (NDIS_STATUS_FAILURE);
404 }
405
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800406 /* */
407 /* fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET */
408 /* should always has only one physical buffer, and the whole frame size equals */
409 /* to the first scatter buffer size */
410 /* */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700411
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800412 /* Initialize TX Descriptor */
413 /* For inter-frame gap, the number is for this frame and next frame */
414 /* For MLME rate, we will fix as 2Mb to match other vendor's implement */
415/* pAd->CommonCfg.MlmeTransmit.field.MODE = 1; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700416
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800417/* management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200418 PID = PID_MGMT;
419
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800420 if (pMacEntry == NULL) {
421 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp,
422 FALSE, bAckRequired, FALSE, 0, RESERVED_WCID,
423 (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID, 0,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800424 (u8)pAd->CommonCfg.MlmeTransmit.field.MCS,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800425 IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
426 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200427 /* dont use low rate to send QoS Null data frame */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700428 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800429 bInsertTimestamp, FALSE, bAckRequired, FALSE,
430 0, pMacEntry->Aid,
431 (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
432 pMacEntry->MaxHTPhyMode.field.MCS, 0,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800433 (u8)pMacEntry->MaxHTPhyMode.field.MCS,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800434 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700435 }
436
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800437 /* Now do hardware-depened kick out. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700438 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
439
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800440 /* Make sure to release MGMT ring resource */
441/* if (!IrqState) */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700442 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
443 return NDIS_STATUS_SUCCESS;
444}
445
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700446/********************************************************************************
447
448 New DeQueue Procedures.
449
450 ********************************************************************************/
451
452#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
453 do{ \
454 if (bIntContext == FALSE) \
455 RTMP_IRQ_LOCK((lock), IrqFlags); \
456 }while(0)
457
458#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
459 do{ \
460 if (bIntContext == FALSE) \
461 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
462 }while(0)
463
464/*
465 ========================================================================
466 Tx Path design algorithm:
467 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
468 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
469 Classification Rule=>
470 Multicast: (*addr1 & 0x01) == 0x01
471 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
472 11N Rate : If peer support HT
473 (1).AMPDU -- If TXBA is negotiated.
474 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
475 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
476 (3).Normal -- Other packets which send as 11n rate.
477
478 B/G Rate : If peer is b/g only.
479 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
480 (2).Normal -- Other packets which send as b/g rate.
481 Fragment:
482 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
483
484 Classified Packet Handle Rule=>
485 Multicast:
486 No ACK, //pTxBlk->bAckRequired = FALSE;
487 No WMM, //pTxBlk->bWMM = FALSE;
488 No piggyback, //pTxBlk->bPiggyBack = FALSE;
489 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
490 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
491 the same policy to handle it.
492 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
493
494 11N Rate :
495 No piggyback, //pTxBlk->bPiggyBack = FALSE;
496
497 (1).AMSDU
498 pTxBlk->bWMM = TRUE;
499 (2).AMPDU
500 pTxBlk->bWMM = TRUE;
501 (3).Normal
502
503 B/G Rate :
504 (1).ARALINK
505
506 (2).Normal
507 ========================================================================
508*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800509static u8 TxPktClassification(struct rt_rtmp_adapter *pAd, void *pPacket)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700510{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800511 u8 TxFrameType = TX_UNKOWN_FRAME;
512 u8 Wcid;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800513 struct rt_mac_table_entry *pMacEntry = NULL;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800514 BOOLEAN bHTRate = FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700515
516 Wcid = RTMP_GET_PACKET_WCID(pPacket);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800517 if (Wcid == MCAST_WCID) { /* Handle for RA is Broadcast/Multicast Address. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700518 return TX_MCAST_FRAME;
519 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800520 /* Handle for unicast packets */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700521 pMacEntry = &pAd->MacTab.Content[Wcid];
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800522 if (RTMP_GET_PACKET_LOWRATE(pPacket)) { /* It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700523 TxFrameType = TX_LEGACY_FRAME;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800524 } else if (IS_HT_RATE(pMacEntry)) { /* it's a 11n capable packet */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700525
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800526 /* Depends on HTPhyMode to check if the peer support the HTRate transmission. */
527 /* Currently didn't support A-MSDU embedded in A-MPDU */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700528 bHTRate = TRUE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800529 if (RTMP_GET_PACKET_MOREDATA(pPacket)
530 || (pMacEntry->PsMode == PWR_SAVE))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700531 TxFrameType = TX_LEGACY_FRAME;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800532 else if ((pMacEntry->
533 TXBAbitmap & (1 << (RTMP_GET_PACKET_UP(pPacket)))) !=
534 0)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700535 return TX_AMPDU_FRAME;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800536 else if (CLIENT_STATUS_TEST_FLAG
537 (pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700538 return TX_AMSDU_FRAME;
539 else
540 TxFrameType = TX_LEGACY_FRAME;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800541 } else { /* it's a legacy b/g packet. */
542 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. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700543 TxFrameType = TX_RALINK_FRAME;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800544 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700545 TxFrameType = TX_LEGACY_FRAME;
546 }
547 }
548
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800549 /* Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800550 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1)
551 && (TxFrameType == TX_LEGACY_FRAME))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700552 TxFrameType = TX_FRAG_FRAME;
553
554 return TxFrameType;
555}
556
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800557BOOLEAN RTMP_FillTxBlkInfo(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700558{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800559 struct rt_packet_info PacketInfo;
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800560 void *pPacket;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800561 struct rt_mac_table_entry *pMacEntry = NULL;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700562
563 pPacket = pTxBlk->pPacket;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800564 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader,
565 &pTxBlk->SrcBufLen);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700566
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800567 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
568 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
569 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800570 pTxBlk->FrameGap = IFS_HTTXOP; /* ASIC determine Frame Gap */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700571
572 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
573 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
574 else
575 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
576
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800577 /* Default to clear this flag */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700578 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
579
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800580 if (pTxBlk->Wcid == MCAST_WCID) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700581 pTxBlk->pMacEntry = NULL;
582 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800583 pTxBlk->pTransmit =
584 &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700585 }
586
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800587 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); /* AckRequired = FALSE, when broadcast packet in Adhoc mode. */
588 /*TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700589 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
590 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800591 if (RTMP_GET_PACKET_MOREDATA(pPacket)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700592 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
593 }
594
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800595 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700596 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
597 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
598
599 pMacEntry = pTxBlk->pMacEntry;
600
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800601 /* For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700602 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
603 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
604 else
605 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
606
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200607 if ((pAd->OpMode == OPMODE_STA) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800608 (ADHOC_ON(pAd)) &&
609 (RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS))) {
610 if (pAd->CommonCfg.PSPXlink)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200611 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
612 }
613
614 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800615 {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200616
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800617 /* If support WMM, enable it. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800618 if (OPSTATUS_TEST_FLAG
619 (pAd, fOP_STATUS_WMM_INUSED)
620 && CLIENT_STATUS_TEST_FLAG(pMacEntry,
621 fCLIENT_STATUS_WMM_CAPABLE))
622 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200623
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800624/* if (pAd->StaCfg.bAutoTxRateSwitch) */
625/* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200626 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700627 }
628
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800629 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800630 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. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800631 pTxBlk->pTransmit =
632 &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
Bartlomiej Zolnierkiewicz16232672009-04-26 16:06:00 +0200633
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800634 /* Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700635 if (IS_HT_STA(pTxBlk->pMacEntry) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800636 (CLIENT_STATUS_TEST_FLAG
637 (pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET))
638 && ((pAd->CommonCfg.bRdg == TRUE)
639 && CLIENT_STATUS_TEST_FLAG(pMacEntry,
640 fCLIENT_STATUS_RDG_CAPABLE)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700641 {
642 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800643 TX_BLK_SET_FLAG(pTxBlk,
644 fTX_bForceNonQoS);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700645 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700646 }
647
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800648 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. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700649 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
650 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700651
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800652 if (RTMP_GET_PACKET_MOREDATA(pPacket)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700653 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
654 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800655 } else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700656 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
657 }
658
659 pMacEntry->DebugTxCount++;
660 }
661
662 return TRUE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700663}
664
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800665BOOLEAN CanDoAggregateTransmit(struct rt_rtmp_adapter *pAd,
666 char * pPacket, struct rt_tx_blk *pTxBlk)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700667{
668
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800669 /*DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType)); */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700670
671 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
672 return FALSE;
673
674 if (RTMP_GET_PACKET_DHCP(pPacket) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800675 RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_WAI(pPacket))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700676 return FALSE;
677
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800678 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 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700679 return FALSE;
680 }
681
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800682 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && (pTxBlk->TxPacketList.Number == 2)) { /* For RALINK-Aggregation, allow two frames in one batch. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700683 return FALSE;
684 }
685
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800686 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) /* must be unicast to AP */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700687 return TRUE;
688 else
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700689 return FALSE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200690
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700691}
692
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700693/*
694 ========================================================================
695
696 Routine Description:
697 To do the enqueue operation and extract the first item of waiting
698 list. If a number of available shared memory segments could meet
699 the request of extracted item, the extracted item will be fragmented
700 into shared memory segments.
701
702 Arguments:
703 pAd Pointer to our adapter
704 pQueue Pointer to Waiting Queue
705
706 Return Value:
707 None
708
709 IRQL = DISPATCH_LEVEL
710
711 Note:
712
713 ========================================================================
714*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800715void RTMPDeQueuePacket(struct rt_rtmp_adapter *pAd, IN BOOLEAN bIntContext, u8 QIdx, /* BulkOutPipeId */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800716 u8 Max_Tx_Packets)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700717{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800718 struct rt_queue_entry *pEntry = NULL;
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800719 void *pPacket;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800720 int Status = NDIS_STATUS_SUCCESS;
721 u8 Count = 0;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800722 struct rt_queue_header *pQueue;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800723 unsigned long FreeNumber[NUM_OF_TX_RING];
724 u8 QueIdx, sQIdx, eQIdx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800725 unsigned long IrqFlags = 0;
726 BOOLEAN hasTxDesc = FALSE;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800727 struct rt_tx_blk TxBlk;
728 struct rt_tx_blk *pTxBlk;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700729
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800730 if (QIdx == NUM_OF_TX_RING) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700731 sQIdx = 0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800732 eQIdx = 3; /* 4 ACs, start from 0. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800733 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700734 sQIdx = eQIdx = QIdx;
735 }
736
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800737 for (QueIdx = sQIdx; QueIdx <= eQIdx; QueIdx++) {
738 Count = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700739
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200740 RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700741
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800742 while (1) {
743 if ((RTMP_TEST_FLAG
744 (pAd,
745 (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
746 fRTMP_ADAPTER_RADIO_OFF |
747 fRTMP_ADAPTER_RESET_IN_PROGRESS |
748 fRTMP_ADAPTER_HALT_IN_PROGRESS |
749 fRTMP_ADAPTER_NIC_NOT_EXIST)))) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200750 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700751 return;
752 }
753
754 if (Count >= Max_Tx_Packets)
755 break;
756
757 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800758 if (&pAd->TxSwQueue[QueIdx] == NULL) {
759 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
760 IrqFlags);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700761 break;
762 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200763#ifdef RTMP_MAC_PCI
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700764 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
765
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800766 if (FreeNumber[QueIdx] <= 5) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800767 /* free Tx(QueIdx) resources */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700768 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800769 FreeNumber[QueIdx] =
770 GET_TXRING_FREENO(pAd, QueIdx);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700771 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800772#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200773
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800774 /* probe the Queue Head */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700775 pQueue = &pAd->TxSwQueue[QueIdx];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800776 if ((pEntry = pQueue->Head) == NULL) {
777 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
778 IrqFlags);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700779 break;
780 }
781
782 pTxBlk = &TxBlk;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800783 NdisZeroMemory((u8 *)pTxBlk, sizeof(struct rt_tx_blk));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800784 /*InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700785 pTxBlk->QueIdx = QueIdx;
786
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200787 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
788
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800789 /* Early check to make sure we have enoguh Tx Resource. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800790 hasTxDesc =
791 RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk,
792 FreeNumber[QueIdx],
793 pPacket);
794 if (!hasTxDesc) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700795 pAd->PrivateInfo.TxRingFullCnt++;
796
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800797 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
798 IrqFlags);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700799
800 break;
801 }
802
803 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
804 pEntry = RemoveHeadQueue(pQueue);
805 pTxBlk->TotalFrameNum++;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800806 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700807 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
808 pTxBlk->pPacket = pPacket;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800809 InsertTailQueue(&pTxBlk->TxPacketList,
810 PACKET_TO_QUEUE_ENTRY(pPacket));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700811
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800812 if (pTxBlk->TxFrameType == TX_RALINK_FRAME
813 || pTxBlk->TxFrameType == TX_AMSDU_FRAME) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800814 /* Enhance SW Aggregation Mechanism */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800815 if (NEED_QUEUE_BACK_FOR_AGG
816 (pAd, QueIdx, FreeNumber[QueIdx],
817 pTxBlk->TxFrameType)) {
818 InsertHeadQueue(pQueue,
819 PACKET_TO_QUEUE_ENTRY
820 (pPacket));
821 DEQUEUE_UNLOCK(&pAd->irq_lock,
822 bIntContext, IrqFlags);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700823 break;
824 }
825
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800826 do {
827 if ((pEntry = pQueue->Head) == NULL)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700828 break;
829
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800830 /* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200831 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800832 FreeNumber[QueIdx] =
833 GET_TXRING_FREENO(pAd, QueIdx);
834 hasTxDesc =
835 RTMP_HAS_ENOUGH_FREE_DESC(pAd,
836 pTxBlk,
837 FreeNumber
838 [QueIdx],
839 pPacket);
840 if ((hasTxDesc == FALSE)
841 ||
842 (CanDoAggregateTransmit
843 (pAd, pPacket, pTxBlk) == FALSE))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700844 break;
845
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800846 /*Remove the packet from the TxSwQueue and insert into pTxBlk */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700847 pEntry = RemoveHeadQueue(pQueue);
848 ASSERT(pEntry);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200849 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700850 pTxBlk->TotalFrameNum++;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800851 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800852 pTxBlk->TotalFrameLen +=
853 GET_OS_PKT_LEN(pPacket);
854 InsertTailQueue(&pTxBlk->TxPacketList,
855 PACKET_TO_QUEUE_ENTRY
856 (pPacket));
857 } while (1);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700858
859 if (pTxBlk->TxPacketList.Number == 1)
860 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
861 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200862#ifdef RTMP_MAC_USB
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +0200863 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800864#endif /* RTMP_MAC_USB // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700865 Count += pTxBlk->TxPacketList.Number;
866
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800867 /* Do HardTransmit now. */
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +0200868 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700869
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200870#ifdef RTMP_MAC_PCI
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700871 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800872 /* static rate also need NICUpdateFifoStaCounters() function. */
873 /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800874 NICUpdateFifoStaCounters(pAd);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800875#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200876
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700877 }
878
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200879 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +0200880
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200881#ifdef RTMP_MAC_USB
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +0200882 if (!hasTxDesc)
883 RTUSBKickBulkOut(pAd);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800884#endif /* RTMP_MAC_USB // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700885 }
886
887}
888
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700889/*
890 ========================================================================
891
892 Routine Description:
893 Calculates the duration which is required to transmit out frames
894 with given size and specified rate.
895
896 Arguments:
897 pAd Pointer to our adapter
898 Rate Transmit rate
899 Size Frame size in units of byte
900
901 Return Value:
902 Duration number in units of usec
903
904 IRQL = PASSIVE_LEVEL
905 IRQL = DISPATCH_LEVEL
906
907 Note:
908
909 ========================================================================
910*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800911u16 RTMPCalcDuration(struct rt_rtmp_adapter *pAd, u8 Rate, unsigned long Size)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700912{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800913 unsigned long Duration = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700914
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800915 if (Rate < RATE_FIRST_OFDM_RATE) /* CCK */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700916 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800917 if ((Rate > RATE_1)
918 && OPSTATUS_TEST_FLAG(pAd,
919 fOP_STATUS_SHORT_PREAMBLE_INUSED))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800920 Duration = 96; /* 72+24 preamble+plcp */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700921 else
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800922 Duration = 192; /* 144+48 preamble+plcp */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700923
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800924 Duration += (u16)((Size << 4) / RateIdTo500Kbps[Rate]);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700925 if ((Size << 4) % RateIdTo500Kbps[Rate])
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800926 Duration++;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800927 } else if (Rate <= RATE_LAST_OFDM_RATE) /* OFDM rates */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700928 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800929 Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800930 Duration +=
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800931 4 * (u16)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700932 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
933 Duration += 4;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800934 } else /*mimo rate */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700935 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800936 Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700937 }
938
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800939 return (u16)Duration;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700940}
941
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700942/*
943 ========================================================================
944
945 Routine Description:
946 Calculates the duration which is required to transmit out frames
947 with given size and specified rate.
948
949 Arguments:
950 pTxWI Pointer to head of each MPDU to HW.
951 Ack Setting for Ack requirement bit
952 Fragment Setting for Fragment bit
953 RetryMode Setting for retry mode
954 Ifs Setting for IFS gap
955 Rate Setting for transmit rate
956 Service Setting for service
957 Length Frame length
958 TxPreamble Short or Long preamble when using CCK rates
959 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
960
961 Return Value:
962 None
963
964 IRQL = PASSIVE_LEVEL
965 IRQL = DISPATCH_LEVEL
966
967 See also : BASmartHardTransmit() !!!
968
969 ========================================================================
970*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800971void RTMPWriteTxWI(struct rt_rtmp_adapter *pAd, struct rt_txwi * pOutTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq, /* HW new a sequence. */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800972 u8 BASize,
973 u8 WCID,
974 unsigned long Length,
975 u8 PID,
976 u8 TID,
977 u8 TxRate,
978 u8 Txopmode,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800979 IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700980{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800981 struct rt_mac_table_entry *pMac = NULL;
982 struct rt_txwi TxWI;
983 struct rt_txwi * pTxWI;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700984
985 if (WCID < MAX_LEN_OF_MAC_TABLE)
986 pMac = &pAd->MacTab.Content[WCID];
987
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800988 /* */
989 /* Always use Long preamble before verifiation short preamble functionality works well. */
990 /* Todo: remove the following line if short preamble functionality works */
991 /* */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700992 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
993 NdisZeroMemory(&TxWI, TXWI_SIZE);
994 pTxWI = &TxWI;
995
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800996 pTxWI->FRAG = FRAG;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700997
998 pTxWI->CFACK = CFACK;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800999 pTxWI->TS = InsTimestamp;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001000 pTxWI->AMPDU = AMPDU;
1001 pTxWI->ACK = Ack;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001002 pTxWI->txop = Txopmode;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001003
1004 pTxWI->NSEQ = NSeq;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001005 /* John tune the performace with Intel Client in 20 MHz performance */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001006 BASize = pAd->CommonCfg.TxBASize;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001007 if (pAd->MACVersion == 0x28720200) {
1008 if (BASize > 13)
1009 BASize = 13;
1010 } else {
1011 if (BASize > 7)
1012 BASize = 7;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001013 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001014 pTxWI->BAWinSize = BASize;
1015 pTxWI->ShortGI = pTransmit->field.ShortGI;
1016 pTxWI->STBC = pTransmit->field.STBC;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001017
1018 pTxWI->WirelessCliID = WCID;
1019 pTxWI->MPDUtotalByteCount = Length;
1020 pTxWI->PacketId = PID;
1021
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001022 /* If CCK or OFDM, BW must be 20 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001023 pTxWI->BW =
1024 (pTransmit->field.MODE <=
1025 MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001026
1027 pTxWI->MCS = pTransmit->field.MCS;
1028 pTxWI->PHYMODE = pTransmit->field.MODE;
1029 pTxWI->CFACK = CfAck;
1030
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001031 if (pMac) {
1032 if (pAd->CommonCfg.bMIMOPSEnable) {
1033 if ((pMac->MmpsMode == MMPS_DYNAMIC)
1034 && (pTransmit->field.MCS > 7)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001035 /* Dynamic MIMO Power Save Mode */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001036 pTxWI->MIMOps = 1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001037 } else if (pMac->MmpsMode == MMPS_STATIC) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001038 /* Static MIMO Power Save Mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001039 if (pTransmit->field.MODE >= MODE_HTMIX
1040 && pTransmit->field.MCS > 7) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001041 pTxWI->MCS = 7;
1042 pTxWI->MIMOps = 0;
1043 }
1044 }
1045 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001046 /*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001047 if (pMac->bIAmBadAtheros
1048 && (pMac->WepStatus != Ndis802_11WEPDisabled)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001049 pTxWI->MpduDensity = 7;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001050 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001051 pTxWI->MpduDensity = pMac->MpduDensity;
1052 }
1053 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001054
1055 pTxWI->PacketId = pTxWI->MCS;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001056 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(struct rt_txwi));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001057}
1058
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001059void RTMPWriteTxWI_Data(struct rt_rtmp_adapter *pAd,
1060 struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001061{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001062 HTTRANSMIT_SETTING *pTransmit;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001063 struct rt_mac_table_entry *pMacEntry;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001064 u8 BASize;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001065
1066 ASSERT(pTxWI);
1067
1068 pTransmit = pTxBlk->pTransmit;
1069 pMacEntry = pTxBlk->pMacEntry;
1070
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001071 /* */
1072 /* Always use Long preamble before verifiation short preamble functionality works well. */
1073 /* Todo: remove the following line if short preamble functionality works */
1074 /* */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001075 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1076 NdisZeroMemory(pTxWI, TXWI_SIZE);
1077
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001078 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1079 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1080 pTxWI->txop = pTxBlk->FrameGap;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001081
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001082 pTxWI->WirelessCliID = pTxBlk->Wcid;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001083
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001084 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1085 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001086
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001087 /* If CCK or OFDM, BW must be 20 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001088 pTxWI->BW =
1089 (pTransmit->field.MODE <=
1090 MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1091 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001092
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001093 /* John tune the performace with Intel Client in 20 MHz performance */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001094 BASize = pAd->CommonCfg.TxBASize;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001095 if ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001096 u8 RABAOriIdx = 0; /*The RA's BA Originator table index. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001097
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001098 RABAOriIdx =
1099 pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001100 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1101 }
1102
1103 pTxWI->TxBF = pTransmit->field.TxBF;
1104 pTxWI->BAWinSize = BASize;
1105 pTxWI->ShortGI = pTransmit->field.ShortGI;
1106 pTxWI->STBC = pTransmit->field.STBC;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001107
1108 pTxWI->MCS = pTransmit->field.MCS;
1109 pTxWI->PHYMODE = pTransmit->field.MODE;
1110
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001111 if (pMacEntry) {
1112 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1113 && (pTransmit->field.MCS > 7)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001114 /* Dynamic MIMO Power Save Mode */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001115 pTxWI->MIMOps = 1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001116 } else if (pMacEntry->MmpsMode == MMPS_STATIC) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001117 /* Static MIMO Power Save Mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001118 if (pTransmit->field.MODE >= MODE_HTMIX
1119 && pTransmit->field.MCS > 7) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001120 pTxWI->MCS = 7;
1121 pTxWI->MIMOps = 0;
1122 }
1123 }
1124
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001125 if (pMacEntry->bIAmBadAtheros
1126 && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001127 pTxWI->MpduDensity = 7;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001128 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001129 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1130 }
1131 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001132
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001133 /* for rate adapation */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001134 pTxWI->PacketId = pTxWI->MCS;
1135}
1136
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001137void RTMPWriteTxWI_Cache(struct rt_rtmp_adapter *pAd,
1138 struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001139{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001140 PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001141 struct rt_mac_table_entry *pMacEntry;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001142
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001143 /* */
1144 /* update TXWI */
1145 /* */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001146 pMacEntry = pTxBlk->pMacEntry;
1147 pTransmit = pTxBlk->pTransmit;
1148
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001149 /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
1150 /*if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) */
1151 /*if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001152 if (pMacEntry->bAutoTxRateSwitch) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001153 pTxWI->txop = IFS_HTTXOP;
1154
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001155 /* If CCK or OFDM, BW must be 20 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001156 pTxWI->BW =
1157 (pTransmit->field.MODE <=
1158 MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001159 pTxWI->ShortGI = pTransmit->field.ShortGI;
1160 pTxWI->STBC = pTransmit->field.STBC;
1161
1162 pTxWI->MCS = pTransmit->field.MCS;
1163 pTxWI->PHYMODE = pTransmit->field.MODE;
1164
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001165 /* set PID for TxRateSwitching */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001166 pTxWI->PacketId = pTransmit->field.MCS;
1167 }
1168
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001169 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE : FALSE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001170 pTxWI->MIMOps = 0;
1171
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001172 if (pAd->CommonCfg.bMIMOPSEnable) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001173 /* MIMO Power Save Mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001174 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1175 && (pTransmit->field.MCS > 7)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001176 /* Dynamic MIMO Power Save Mode */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001177 pTxWI->MIMOps = 1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001178 } else if (pMacEntry->MmpsMode == MMPS_STATIC) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001179 /* Static MIMO Power Save Mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001180 if ((pTransmit->field.MODE >= MODE_HTMIX)
1181 && (pTransmit->field.MCS > 7)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001182 pTxWI->MCS = 7;
1183 pTxWI->MIMOps = 0;
1184 }
1185 }
1186 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001187
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001188 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1189
1190}
1191
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001192/* should be called only when - */
1193/* 1. MEADIA_CONNECTED */
1194/* 2. AGGREGATION_IN_USED */
1195/* 3. Fragmentation not in used */
1196/* 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001197BOOLEAN TxFrameIsAggregatible(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001198 u8 *pPrevAddr1, u8 *p8023hdr)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001199{
1200
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001201 /* can't aggregate EAPOL (802.1x) frame */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001202 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1203 return FALSE;
1204
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001205 /* can't aggregate multicast/broadcast frame */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001206 if (p8023hdr[0] & 0x01)
1207 return FALSE;
1208
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001209 if (INFRA_ON(pAd)) /* must be unicast to AP */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001210 return TRUE;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001211 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) /* unicast to same STA */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001212 return TRUE;
1213 else
1214 return FALSE;
1215}
1216
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001217/*
1218 ========================================================================
1219
1220 Routine Description:
1221 Check the MSDU Aggregation policy
1222 1.HT aggregation is A-MSDU
1223 2.legaacy rate aggregation is software aggregation by Ralink.
1224
1225 Arguments:
1226
1227 Return Value:
1228
1229 Note:
1230
1231 ========================================================================
1232*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001233BOOLEAN PeerIsAggreOn(struct rt_rtmp_adapter *pAd,
1234 unsigned long TxRate, struct rt_mac_table_entry *pMacEntry)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001235{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001236 unsigned long AFlags =
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001237 (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001238
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001239 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) {
1240 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001241 return TRUE;
1242 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001243#ifdef AGGREGATION_SUPPORT
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001244 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) { /* legacy Ralink Aggregation support */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001245 return TRUE;
1246 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001247#endif /* AGGREGATION_SUPPORT // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001248 }
1249
1250 return FALSE;
1251
1252}
1253
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001254/*
1255 ========================================================================
1256
1257 Routine Description:
1258 Check and fine the packet waiting in SW queue with highest priority
1259
1260 Arguments:
1261 pAd Pointer to our adapter
1262
1263 Return Value:
1264 pQueue Pointer to Waiting Queue
1265
1266 IRQL = DISPATCH_LEVEL
1267
1268 Note:
1269
1270 ========================================================================
1271*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001272struct rt_queue_header *RTMPCheckTxSwQueue(struct rt_rtmp_adapter *pAd, u8 *pQueIdx)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001273{
1274
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001275 unsigned long Number;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001276 /* 2004-11-15 to be removed. test aggregation only */
1277/* if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) */
1278/* return NULL; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001279
1280 Number = pAd->TxSwQueue[QID_AC_BK].Number
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001281 + pAd->TxSwQueue[QID_AC_BE].Number
1282 + pAd->TxSwQueue[QID_AC_VI].Number
1283 + pAd->TxSwQueue[QID_AC_VO].Number;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001284
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001285 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001286 *pQueIdx = QID_AC_VO;
1287 return (&pAd->TxSwQueue[QID_AC_VO]);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001288 } else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001289 *pQueIdx = QID_AC_VI;
1290 return (&pAd->TxSwQueue[QID_AC_VI]);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001291 } else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001292 *pQueIdx = QID_AC_BE;
1293 return (&pAd->TxSwQueue[QID_AC_BE]);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001294 } else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001295 *pQueIdx = QID_AC_BK;
1296 return (&pAd->TxSwQueue[QID_AC_BK]);
1297 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001298 /* No packet pending in Tx Sw queue */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001299 *pQueIdx = QID_AC_BK;
1300
1301 return (NULL);
1302}
1303
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001304/*
1305 ========================================================================
1306
1307 Routine Description:
1308 Suspend MSDU transmission
1309
1310 Arguments:
1311 pAd Pointer to our adapter
1312
1313 Return Value:
1314 None
1315
1316 Note:
1317
1318 ========================================================================
1319*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001320void RTMPSuspendMsduTransmission(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001321{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001322 DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001323
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001324 /* */
1325 /* Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and */
1326 /* use Lowbound as R66 value on ScanNextChannel(...) */
1327 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001328 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66,
1329 &pAd->BbpTuning.R66CurrentValue);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001330
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001331 /* set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) */
1332 /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001333 RTMPSetAGCInitValue(pAd, BW_20);
1334
1335 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001336 /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001337}
1338
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001339/*
1340 ========================================================================
1341
1342 Routine Description:
1343 Resume MSDU transmission
1344
1345 Arguments:
1346 pAd Pointer to our adapter
1347
1348 Return Value:
1349 None
1350
1351 IRQL = DISPATCH_LEVEL
1352
1353 Note:
1354
1355 ========================================================================
1356*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001357void RTMPResumeMsduTransmission(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001358{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001359/* u8 IrqState; */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001360
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001361 DBGPRINT(RT_DEBUG_TRACE, ("SCAN done, resume MSDU transmission ...\n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001362
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001363 /* After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value */
1364 /* R66 should not be 0 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001365 if (pAd->BbpTuning.R66CurrentValue == 0) {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02001366 pAd->BbpTuning.R66CurrentValue = 0x38;
1367 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1368 }
Bartlomiej Zolnierkiewicz7765e892009-08-23 15:30:24 +02001369
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001370 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66,
1371 pAd->BbpTuning.R66CurrentValue);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001372
1373 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001374/* sample, for IRQ LOCK to SEM LOCK */
1375/* IrqState = pAd->irq_disabled; */
1376/* if (IrqState) */
1377/* RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); */
1378/* else */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001379 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1380}
1381
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001382u32 deaggregate_AMSDU_announce(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -08001383 void *pPacket,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001384 u8 *pData, unsigned long DataSize)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001385{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001386 u16 PayloadSize;
1387 u16 SubFrameSize;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001388 struct rt_header_802_3 * pAMSDUsubheader;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001389 u32 nMSDU;
1390 u8 Header802_3[14];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001391
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001392 u8 *pPayload, *pDA, *pSA, *pRemovedLLCSNAP;
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -08001393 void *pClonePacket;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001394
1395 nMSDU = 0;
1396
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001397 while (DataSize > LENGTH_802_3) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001398
1399 nMSDU++;
1400
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001401 /*hex_dump("subheader", pData, 64); */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001402 pAMSDUsubheader = (struct rt_header_802_3 *) pData;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001403 /*pData += LENGTH_802_3; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001404 PayloadSize =
1405 pAMSDUsubheader->Octet[1] +
1406 (pAMSDUsubheader->Octet[0] << 8);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001407 SubFrameSize = PayloadSize + LENGTH_802_3;
1408
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001409 if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001410 break;
1411 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001412 /*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize)); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001413
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001414 pPayload = pData + LENGTH_802_3;
1415 pDA = pData;
1416 pSA = pData + MAC_ADDR_LEN;
1417
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001418 /* convert to 802.3 header */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001419 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize,
1420 pRemovedLLCSNAP);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001421
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001422 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001423 /* avoid local heap overflow, use dyanamic allocation */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001424 struct rt_mlme_queue_elem *Elem =
1425 (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem),
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001426 MEM_ALLOC_FLAG);
1427 if (Elem != NULL) {
1428 memmove(Elem->Msg +
1429 (LENGTH_802_11 + LENGTH_802_1_H),
1430 pPayload, PayloadSize);
1431 Elem->MsgLen =
1432 LENGTH_802_11 + LENGTH_802_1_H +
1433 PayloadSize;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001434 /*WpaEAPOLKeyAction(pAd, Elem); */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001435 REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID,
1436 Elem->Msg,
1437 Elem->MsgLen, 0, 0, 0,
1438 0);
1439 kfree(Elem);
1440 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001441 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001442
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001443 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001444 if (pRemovedLLCSNAP) {
1445 pPayload -= LENGTH_802_3;
1446 PayloadSize += LENGTH_802_3;
1447 NdisMoveMemory(pPayload, &Header802_3[0],
1448 LENGTH_802_3);
1449 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001450 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001451
1452 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001453 if (pClonePacket) {
1454 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket,
1455 RTMP_GET_PACKET_IF
1456 (pPacket));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001457 }
1458
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001459 /* A-MSDU has padding to multiple of 4 including subframe header. */
1460 /* align SubFrameSize up to multiple of 4 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001461 SubFrameSize = (SubFrameSize + 3) & (~0x3);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001462
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001463 if (SubFrameSize > 1528 || SubFrameSize < 32) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001464 break;
1465 }
1466
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001467 if (DataSize > SubFrameSize) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001468 pData += SubFrameSize;
1469 DataSize -= SubFrameSize;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001470 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001471 /* end of A-MSDU */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001472 DataSize = 0;
1473 }
1474 }
1475
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001476 /* finally release original rx packet */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001477 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1478
1479 return nMSDU;
1480}
1481
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001482u32 BA_Reorder_AMSDU_Annnounce(struct rt_rtmp_adapter *pAd, void *pPacket)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001483{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001484 u8 *pData;
1485 u16 DataSize;
1486 u32 nMSDU = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001487
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001488 pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket);
1489 DataSize = (u16)GET_OS_PKT_LEN(pPacket);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001490
1491 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1492
1493 return nMSDU;
1494}
1495
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001496/*
1497 ==========================================================================
1498 Description:
1499 Look up the MAC address in the MAC table. Return NULL if not found.
1500 Return:
1501 pEntry - pointer to the MAC entry; NULL is not found
1502 ==========================================================================
1503*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001504struct rt_mac_table_entry *MacTableLookup(struct rt_rtmp_adapter *pAd, u8 *pAddr)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001505{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001506 unsigned long HashIdx;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001507 struct rt_mac_table_entry *pEntry = NULL;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001508
1509 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1510 pEntry = pAd->MacTab.Hash[HashIdx];
1511
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001512 while (pEntry
1513 && (pEntry->ValidAsCLI || pEntry->ValidAsWDS
1514 || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) {
1515 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001516 break;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001517 } else
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001518 pEntry = pEntry->pNext;
1519 }
1520
1521 return pEntry;
1522}
1523
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001524struct rt_mac_table_entry *MacTableInsertEntry(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001525 u8 *pAddr,
1526 u8 apidx, IN BOOLEAN CleanAll)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001527{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001528 u8 HashIdx;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001529 int i, FirstWcid;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001530 struct rt_mac_table_entry *pEntry = NULL, *pCurrEntry;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001531/* u16 offset; */
1532/* unsigned long addr; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001533
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001534 /* if FULL, return */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001535 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1536 return NULL;
1537
1538 FirstWcid = 1;
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02001539
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001540 if (pAd->StaCfg.BssType == BSS_INFRA)
1541 FirstWcid = 2;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001542
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001543 /* allocate one MAC entry */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001544 NdisAcquireSpinLock(&pAd->MacTabLock);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001545 for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++) /* skip entry#0 so that "entry index == AID" for fast lookup */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001546 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001547 /* pick up the first available vacancy */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001548 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001549 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1550 (pAd->MacTab.Content[i].ValidAsApCli == FALSE) &&
1551 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1552 ) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001553 pEntry = &pAd->MacTab.Content[i];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001554 if (CleanAll == TRUE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001555 pEntry->MaxSupportedRate = RATE_11;
1556 pEntry->CurrTxRate = RATE_11;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001557 NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001558 pEntry->PairwiseKey.KeyLen = 0;
1559 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1560 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001561 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001562 {
1563 pEntry->ValidAsCLI = TRUE;
1564 pEntry->ValidAsWDS = FALSE;
1565 pEntry->ValidAsApCli = FALSE;
1566 pEntry->ValidAsMesh = FALSE;
1567 pEntry->ValidAsDls = FALSE;
1568 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001569 }
1570
1571 pEntry->bIAmBadAtheros = FALSE;
1572 pEntry->pAd = pAd;
1573 pEntry->CMTimerRunning = FALSE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001574 pEntry->EnqueueEapolStartTimerRunning =
1575 EAPOL_START_DISABLE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001576 pEntry->RSNIE_Len = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001577 NdisZeroMemory(pEntry->R_Counter,
1578 sizeof(pEntry->R_Counter));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001579 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1580
1581 if (pEntry->ValidAsMesh)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001582 pEntry->apidx =
1583 (apidx - MIN_NET_DEVICE_FOR_MESH);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001584 else if (pEntry->ValidAsApCli)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001585 pEntry->apidx =
1586 (apidx - MIN_NET_DEVICE_FOR_APCLI);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001587 else if (pEntry->ValidAsWDS)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001588 pEntry->apidx =
1589 (apidx - MIN_NET_DEVICE_FOR_WDS);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001590 else
1591 pEntry->apidx = apidx;
1592
1593 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001594 {
1595 pEntry->AuthMode = pAd->StaCfg.AuthMode;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001596 pEntry->WepStatus =
1597 pAd->StaCfg.WepStatus;
1598 pEntry->PrivacyFilter =
1599 Ndis802_11PrivFilterAcceptAll;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001600#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001601 AsicRemovePairwiseKeyEntry(pAd,
1602 pEntry->
1603 apidx,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001604 (u8)i);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001605#endif /* RTMP_MAC_PCI // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001606 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001607 }
1608
1609 pEntry->GTKState = REKEY_NEGOTIATING;
1610 pEntry->PairwiseKey.KeyLen = 0;
1611 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001612 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02001613
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001614 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1615 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1616 pEntry->Sst = SST_NOT_AUTH;
1617 pEntry->AuthState = AS_NOT_AUTH;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001618 pEntry->Aid = (u16)i; /*0; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001619 pEntry->CapabilityInfo = 0;
1620 pEntry->PsMode = PWR_ACTIVE;
1621 pEntry->PsQIdleCount = 0;
1622 pEntry->NoDataIdleCount = 0;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001623 pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001624 pEntry->ContinueTxFailCnt = 0;
1625 InitializeQueueHeader(&pEntry->PsQueue);
1626
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001627 pAd->MacTab.Size++;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001628 /* Add this entry into ASIC RX WCID search table */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001629 RTMP_STA_ENTRY_ADD(pAd, pEntry);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001630
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001631 DBGPRINT(RT_DEBUG_TRACE,
1632 ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",
1633 i, pAd->MacTab.Size));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001634 break;
1635 }
1636 }
1637
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001638 /* add this MAC entry into HASH table */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001639 if (pEntry) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001640 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001641 if (pAd->MacTab.Hash[HashIdx] == NULL) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001642 pAd->MacTab.Hash[HashIdx] = pEntry;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001643 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001644 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1645 while (pCurrEntry->pNext != NULL)
1646 pCurrEntry = pCurrEntry->pNext;
1647 pCurrEntry->pNext = pEntry;
1648 }
1649 }
1650
1651 NdisReleaseSpinLock(&pAd->MacTabLock);
1652 return pEntry;
1653}
1654
1655/*
1656 ==========================================================================
1657 Description:
1658 Delete a specified client from MAC table
1659 ==========================================================================
1660 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001661BOOLEAN MacTableDeleteEntry(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001662 u16 wcid, u8 *pAddr)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001663{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001664 u16 HashIdx;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001665 struct rt_mac_table_entry *pEntry, *pPrevEntry, *pProbeEntry;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001666 BOOLEAN Cancelled;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001667 /*u16 offset; // unused variable */
1668 /*u8 j; // unused variable */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001669
1670 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1671 return FALSE;
1672
1673 NdisAcquireSpinLock(&pAd->MacTabLock);
1674
1675 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001676 /*pEntry = pAd->MacTab.Hash[HashIdx]; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001677 pEntry = &pAd->MacTab.Content[wcid];
1678
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001679 if (pEntry
1680 && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS
1681 || pEntry->ValidAsMesh)) {
1682 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001683
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001684 /* Delete this entry from ASIC on-chip WCID Table */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001685 RTMP_STA_ENTRY_MAC_RESET(pAd, wcid);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001686
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001687 /* free resources of BA */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001688 BASessionTearDownALL(pAd, pEntry->Aid);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001689
1690 pPrevEntry = NULL;
1691 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1692 ASSERT(pProbeEntry);
1693
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001694 /* update Hash list */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001695 do {
1696 if (pProbeEntry == pEntry) {
1697 if (pPrevEntry == NULL) {
1698 pAd->MacTab.Hash[HashIdx] =
1699 pEntry->pNext;
1700 } else {
1701 pPrevEntry->pNext =
1702 pEntry->pNext;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001703 }
1704 break;
1705 }
1706
1707 pPrevEntry = pProbeEntry;
1708 pProbeEntry = pProbeEntry->pNext;
1709 } while (pProbeEntry);
1710
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001711 /* not found !!! */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001712 ASSERT(pProbeEntry != NULL);
1713
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001714 RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001715
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001716 if (pEntry->EnqueueEapolStartTimerRunning !=
1717 EAPOL_START_DISABLE) {
1718 RTMPCancelTimer(&pEntry->
1719 EnqueueStartForPSKTimer,
1720 &Cancelled);
1721 pEntry->EnqueueEapolStartTimerRunning =
1722 EAPOL_START_DISABLE;
1723 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001724
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001725 NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001726 pAd->MacTab.Size--;
1727 DBGPRINT(RT_DEBUG_TRACE,
1728 ("MacTableDeleteEntry1 - Total= %d\n",
1729 pAd->MacTab.Size));
1730 } else {
1731 DBGPRINT(RT_DEBUG_OFF,
1732 ("\n%s: Impossible Wcid = %d !!!!!\n",
1733 __func__, wcid));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001734 }
1735 }
1736
1737 NdisReleaseSpinLock(&pAd->MacTabLock);
1738
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001739 /*Reset operating mode when no Sta. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001740 if (pAd->MacTab.Size == 0) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001741 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001742 RTMP_UPDATE_PROTECT(pAd); /* edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001743 }
1744
1745 return TRUE;
1746}
1747
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001748/*
1749 ==========================================================================
1750 Description:
1751 This routine reset the entire MAC table. All packets pending in
1752 the power-saving queues are freed here.
1753 ==========================================================================
1754 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001755void MacTableReset(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001756{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001757 int i;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001758
1759 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001760 /*NdisAcquireSpinLock(&pAd->MacTabLock); */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001761
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001762 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001763#ifdef RTMP_MAC_PCI
1764 RTMP_STA_ENTRY_MAC_RESET(pAd, i);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001765#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001766 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001767
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001768 /* free resources of BA */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001769 BASessionTearDownALL(pAd, i);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001770
1771 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1772
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001773#ifdef RTMP_MAC_USB
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02001774 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001775 RTMP_STA_ENTRY_MAC_RESET(pAd, i);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001776#endif /* RTMP_MAC_USB // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001777
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001778 /*AsicDelWcidTab(pAd, i); */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001779 }
1780 }
1781
1782 return;
1783}
1784
1785/*
1786 ==========================================================================
1787 Description:
1788
1789 IRQL = DISPATCH_LEVEL
1790
1791 ==========================================================================
1792*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001793void AssocParmFill(struct rt_rtmp_adapter *pAd,
1794 struct rt_mlme_assoc_req *AssocReq,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001795 u8 *pAddr,
1796 u16 CapabilityInfo,
1797 unsigned long Timeout, u16 ListenIntv)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001798{
1799 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001800 /* Add mask to support 802.11b mode only */
1801 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; /* not cf-pollable, not cf-poll-request */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001802 AssocReq->Timeout = Timeout;
1803 AssocReq->ListenIntv = ListenIntv;
1804}
1805
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001806/*
1807 ==========================================================================
1808 Description:
1809
1810 IRQL = DISPATCH_LEVEL
1811
1812 ==========================================================================
1813*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001814void DisassocParmFill(struct rt_rtmp_adapter *pAd,
1815 struct rt_mlme_disassoc_req *DisassocReq,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001816 u8 *pAddr, u16 Reason)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001817{
1818 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
1819 DisassocReq->Reason = Reason;
1820}
1821
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001822/*
1823 ========================================================================
1824
1825 Routine Description:
1826 Check the out going frame, if this is an DHCP or ARP datagram
1827 will be duplicate another frame at low data rate transmit.
1828
1829 Arguments:
1830 pAd Pointer to our adapter
1831 pPacket Pointer to outgoing Ndis frame
1832
1833 Return Value:
1834 TRUE To be duplicate at Low data rate transmit. (1mb)
1835 FALSE Do nothing.
1836
1837 IRQL = DISPATCH_LEVEL
1838
1839 Note:
1840
1841 MAC header + IP Header + UDP Header
1842 14 Bytes 20 Bytes
1843
1844 UDP Header
1845 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
1846 Source Port
1847 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
1848 Destination Port
1849
1850 port 0x43 means Bootstrap Protocol, server.
1851 Port 0x44 means Bootstrap Protocol, client.
1852
1853 ========================================================================
1854*/
1855
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001856BOOLEAN RTMPCheckDHCPFrame(struct rt_rtmp_adapter *pAd, void *pPacket)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001857{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001858 struct rt_packet_info PacketInfo;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001859 unsigned long NumberOfBytesRead = 0;
1860 unsigned long CurrentOffset = 0;
1861 void *pVirtualAddress = NULL;
1862 u32 NdisBufferLength;
1863 u8 *pSrc;
1864 u16 Protocol;
1865 u8 ByteOffset36 = 0;
1866 u8 ByteOffset38 = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001867 BOOLEAN ReadFirstParm = TRUE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001868
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001869 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (u8 **) & pVirtualAddress,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001870 &NdisBufferLength);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001871
1872 NumberOfBytesRead += NdisBufferLength;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001873 pSrc = (u8 *)pVirtualAddress;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001874 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
1875
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001876 /* */
1877 /* Check DHCP & BOOTP protocol */
1878 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001879 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) {
1880 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) {
1881 CurrentOffset =
1882 35 - (NumberOfBytesRead - NdisBufferLength);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001883 ByteOffset36 = *(pSrc + CurrentOffset);
1884 ReadFirstParm = FALSE;
1885 }
1886
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001887 if (NumberOfBytesRead >= 37) {
1888 CurrentOffset =
1889 37 - (NumberOfBytesRead - NdisBufferLength);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001890 ByteOffset38 = *(pSrc + CurrentOffset);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001891 /*End of Read */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001892 break;
1893 }
1894 return FALSE;
1895 }
1896
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001897 /* Check for DHCP & BOOTP protocol */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001898 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001899 /* */
1900 /* 2054 (hex 0806) for ARP datagrams */
1901 /* if this packet is not ARP datagrams, then do nothing */
1902 /* ARP datagrams will also be duplicate at 1mb broadcast frames */
1903 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001904 if (Protocol != 0x0806)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001905 return FALSE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001906 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001907
1908 return TRUE;
1909}
1910
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001911BOOLEAN RTMPCheckEtherType(struct rt_rtmp_adapter *pAd, void *pPacket)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001912{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001913 u16 TypeLen;
1914 u8 Byte0, Byte1;
1915 u8 *pSrcBuf;
1916 u32 pktLen;
1917 u16 srcPort, dstPort;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001918 BOOLEAN status = TRUE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001919
1920 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
1921 pktLen = GET_OS_PKT_LEN(pPacket);
1922
1923 ASSERT(pSrcBuf);
1924
1925 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
1926
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001927 /* get Ethernet protocol field */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001928 TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001929
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001930 pSrcBuf += LENGTH_802_3; /* Skip the Ethernet Header. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001931
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001932 if (TypeLen <= 1500) { /* 802.3, 802.3 LLC */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001933 /*
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001934 DestMAC(6) + SrcMAC(6) + Lenght(2) +
1935 DSAP(1) + SSAP(1) + Control(1) +
1936 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
1937 => + SNAP (5, OriginationID(3) + etherType(2))
1938 */
1939 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA
1940 && pSrcBuf[2] == 0x03) {
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -08001941 Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 6,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001942 &Byte0, &Byte1);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001943 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001944 TypeLen = (u16)((Byte0 << 8) + Byte1);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001945 pSrcBuf += 8; /* Skip this LLC/SNAP header */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001946 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001947 /*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001948 }
1949 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001950 /* If it's a VLAN packet, get the real Type/Length field. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001951 if (TypeLen == 0x8100) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001952 /* 0x8100 means VLAN packets */
1953
1954 /* Dest. MAC Address (6-bytes) +
1955 Source MAC Address (6-bytes) +
1956 Length/Type = 802.1Q Tag Type (2-byte) +
1957 Tag Control Information (2-bytes) +
1958 Length / Type (2-bytes) +
1959 data payload (0-n bytes) +
1960 Pad (0-p bytes) +
1961 Frame Check Sequence (4-bytes) */
1962
1963 RTMP_SET_PACKET_VLAN(pPacket, 1);
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -08001964 Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 2, &Byte0,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001965 &Byte1);
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001966 TypeLen = (u16)((Byte0 << 8) + Byte1);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001967
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001968 pSrcBuf += 4; /* Skip the VLAN Header. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001969 }
1970
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001971 switch (TypeLen) {
1972 case 0x0800:
1973 {
1974 ASSERT((pktLen > 34));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001975 if (*(pSrcBuf + 9) == 0x11) { /* udp packet */
1976 ASSERT((pktLen > 34)); /* 14 for ethernet header, 20 for IP header */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001977
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001978 pSrcBuf += 20; /* Skip the IP header */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001979 srcPort =
1980 OS_NTOHS(get_unaligned
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001981 ((u16 *)(pSrcBuf)));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001982 dstPort =
1983 OS_NTOHS(get_unaligned
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001984 ((u16 *)(pSrcBuf + 2)));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001985
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001986 if ((srcPort == 0x44 && dstPort == 0x43) || (srcPort == 0x43 && dstPort == 0x44)) { /*It's a BOOTP/DHCP packet */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001987 RTMP_SET_PACKET_DHCP(pPacket, 1);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001988 }
1989 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001990 }
1991 break;
1992 case 0x0806:
1993 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001994 /*ARP Packet. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001995 RTMP_SET_PACKET_DHCP(pPacket, 1);
1996 }
1997 break;
1998 case 0x888e:
1999 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002000 /* EAPOL Packet. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002001 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2002 }
2003 break;
2004 default:
2005 status = FALSE;
2006 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002007 }
2008
2009 return status;
2010
2011}
2012
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002013void Update_Rssi_Sample(struct rt_rtmp_adapter *pAd,
2014 struct rt_rssi_sample *pRssi, struct rt_rxwi * pRxWI)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002015{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002016 char rssi0 = pRxWI->RSSI0;
2017 char rssi1 = pRxWI->RSSI1;
2018 char rssi2 = pRxWI->RSSI2;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002019
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002020 if (rssi0 != 0) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002021 pRssi->LastRssi0 = ConvertToRssi(pAd, (char)rssi0, RSSI_0);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002022 pRssi->AvgRssi0X8 =
2023 (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2024 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002025 }
2026
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002027 if (rssi1 != 0) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002028 pRssi->LastRssi1 = ConvertToRssi(pAd, (char)rssi1, RSSI_1);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002029 pRssi->AvgRssi1X8 =
2030 (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2031 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002032 }
2033
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002034 if (rssi2 != 0) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002035 pRssi->LastRssi2 = ConvertToRssi(pAd, (char)rssi2, RSSI_2);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002036 pRssi->AvgRssi2X8 =
2037 (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002038 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2039 }
2040}
2041
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002042/* Normal legacy Rx packet indication */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002043void Indicate_Legacy_Packet(struct rt_rtmp_adapter *pAd,
2044 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002045{
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -08002046 void *pRxPacket = pRxBlk->pRxPacket;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002047 u8 Header802_3[LENGTH_802_3];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002048
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002049 /* 1. get 802.3 Header */
2050 /* 2. remove LLC */
2051 /* a. pointer pRxBlk->pData to payload */
2052 /* b. modify pRxBlk->DataSize */
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02002053 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002054
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002055 if (pRxBlk->DataSize > MAX_RX_PKT_LEN) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002056
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002057 /* release packet */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002058 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2059 return;
2060 }
2061
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002062 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2063
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002064#ifdef RTMP_MAC_USB
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002065 if (pAd->CommonCfg.bDisableReordering == 0) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002066 struct rt_ba_rec_entry *pBAEntry;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002067 unsigned long Now32;
2068 u8 Wcid = pRxBlk->pRxWI->WirelessCliID;
2069 u8 TID = pRxBlk->pRxWI->TID;
2070 u16 Idx;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002071
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002072#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002073
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002074 if (Wcid < MAX_LEN_OF_MAC_TABLE) {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002075 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002076 if (Idx != 0) {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002077 pBAEntry = &pAd->BATable.BARecEntry[Idx];
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002078 /* update last rx time */
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002079 NdisGetSystemUpTime(&Now32);
2080 if ((pBAEntry->list.qlen > 0) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002081 RTMP_TIME_AFTER((unsigned long)Now32,
2082 (unsigned long)(pBAEntry->
2083 LastIndSeqAtTimer
2084 +
2085 (REORDERING_PACKET_TIMEOUT)))
2086 ) {
2087 DBGPRINT(RT_DEBUG_OFF,
2088 ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
2089 pRxBlk->Flags,
2090 pRxBlk->pRxWI->TID,
2091 pRxBlk->RxD.AMPDU));
2092 hex_dump("Dump the legacy Packet:",
2093 GET_OS_PKT_DATAPTR(pRxBlk->
2094 pRxPacket),
2095 64);
2096 ba_flush_reordering_timeout_mpdus(pAd,
2097 pBAEntry,
2098 Now32);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002099 }
2100 }
2101 }
2102 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002103#endif /* RTMP_MAC_USB // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002104
2105 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2106
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002107 /* */
2108 /* pass this 802.3 packet to upper layer or forward this packet to WM directly */
2109 /* */
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02002110 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002111}
2112
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002113/* Normal, AMPDU or AMSDU */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002114void CmmRxnonRalinkFrameIndicate(struct rt_rtmp_adapter *pAd,
2115 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002116{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002117 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
2118 && (pAd->CommonCfg.bDisableReordering == 0)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002119 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002120 } else {
2121 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002122 /* handle A-MSDU */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002123 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002124 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002125 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2126 }
2127 }
2128}
2129
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002130void CmmRxRalinkFrameIndicate(struct rt_rtmp_adapter *pAd,
2131 struct rt_mac_table_entry *pEntry,
2132 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002133{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002134 u8 Header802_3[LENGTH_802_3];
2135 u16 Msdu2Size;
2136 u16 Payload1Size, Payload2Size;
2137 u8 *pData2;
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -08002138 void *pPacket2 = NULL;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002139
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002140 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002141
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002142 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002143 /* skip two byte MSDU2 len */
2144 pRxBlk->pData += 2;
2145 pRxBlk->DataSize -= 2;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002146 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002147 /* release packet */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002148 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2149 NDIS_STATUS_FAILURE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002150 return;
2151 }
2152
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002153 /* get 802.3 Header and remove LLC */
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02002154 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002155
2156 ASSERT(pRxBlk->pRxPacket);
2157
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002158 /* Ralink Aggregation frame */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002159 pAd->RalinkCounters.OneSecRxAggregationCount++;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002160 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2161 Payload2Size = Msdu2Size - LENGTH_802_3;
2162
2163 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02002164
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002165 pPacket2 =
2166 duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2,
2167 Payload2Size, FromWhichBSSID);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002168
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002169 if (!pPacket2) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002170 /* release packet */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002171 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2172 NDIS_STATUS_FAILURE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002173 return;
2174 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002175 /* update payload size of 1st packet */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002176 pRxBlk->DataSize = Payload1Size;
2177 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2178
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002179 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket,
2180 FromWhichBSSID);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002181
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002182 if (pPacket2) {
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02002183 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002184 }
2185}
2186
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002187#define RESET_FRAGFRAME(_fragFrame) \
2188 { \
2189 _fragFrame.RxSize = 0; \
2190 _fragFrame.Sequence = 0; \
2191 _fragFrame.LastFrag = 0; \
2192 _fragFrame.Flags = 0; \
2193 }
2194
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002195void *RTMPDeFragmentDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002196{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002197 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -08002198 void *pRxPacket = pRxBlk->pRxPacket;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002199 u8 *pData = pRxBlk->pData;
2200 u16 DataSize = pRxBlk->DataSize;
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -08002201 void *pRetPacket = NULL;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002202 u8 *pFragBuffer = NULL;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002203 BOOLEAN bReassDone = FALSE;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002204 u8 HeaderRoom = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002205
2206 ASSERT(pHeader);
2207
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002208 HeaderRoom = pData - (u8 *) pHeader;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002209
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002210 /* Re-assemble the fragmented packets */
2211 if (pHeader->Frag == 0) /* Frag. Number is 0 : First frag or only one pkt */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002212 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002213 /* the first pkt of fragment, record it. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002214 if (pHeader->FC.MoreFrag) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002215 ASSERT(pAd->FragFrame.pFragPacket);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002216 pFragBuffer =
2217 GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2218 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2219 NdisMoveMemory(pFragBuffer, pHeader,
2220 pAd->FragFrame.RxSize);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002221 pAd->FragFrame.Sequence = pHeader->Sequence;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002222 pAd->FragFrame.LastFrag = pHeader->Frag; /* Should be 0 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002223 ASSERT(pAd->FragFrame.LastFrag == 0);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002224 goto done; /* end of processing this frame */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002225 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002226 } else /*Middle & End of fragment */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002227 {
2228 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002229 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002230 /* Fragment is not the same sequence or out of fragment number order */
2231 /* Reset Fragment control blk */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002232 RESET_FRAGFRAME(pAd->FragFrame);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002233 DBGPRINT(RT_DEBUG_ERROR,
2234 ("Fragment is not the same sequence or out of fragment number order.\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002235 goto done; /* give up this frame */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002236 } else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002237 /* Fragment frame is too large, it exeeds the maximum frame size. */
2238 /* Reset Fragment control blk */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002239 RESET_FRAGFRAME(pAd->FragFrame);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002240 DBGPRINT(RT_DEBUG_ERROR,
2241 ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002242 goto done; /* give up this frame */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002243 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002244 /* */
2245 /* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. */
2246 /* In this case, we will dropt it. */
2247 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002248 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) {
2249 DBGPRINT(RT_DEBUG_ERROR,
2250 ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n",
2251 pHeader->Sequence, pHeader->Frag));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002252 goto done; /* give up this frame */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002253 }
2254
2255 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2256
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002257 /* concatenate this fragment into the re-assembly buffer */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002258 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData,
2259 DataSize);
2260 pAd->FragFrame.RxSize += DataSize;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002261 pAd->FragFrame.LastFrag = pHeader->Frag; /* Update fragment number */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002262
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002263 /* Last fragment */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002264 if (pHeader->FC.MoreFrag == FALSE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002265 bReassDone = TRUE;
2266 }
2267 }
2268
2269done:
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002270 /* always release rx fragmented packet */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002271 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2272
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002273 /* return defragmented packet if packet is reassembled completely */
2274 /* otherwise return NULL */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002275 if (bReassDone) {
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -08002276 void *pNewFragPacket;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002277
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002278 /* allocate a new packet buffer for fragment */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002279 pNewFragPacket =
2280 RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2281 if (pNewFragPacket) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002282 /* update RxBlk */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002283 pRetPacket = pAd->FragFrame.pFragPacket;
2284 pAd->FragFrame.pFragPacket = pNewFragPacket;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002285 pRxBlk->pHeader =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002286 (struct rt_header_802_11 *) GET_OS_PKT_DATAPTR(pRetPacket);
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002287 pRxBlk->pData = (u8 *) pRxBlk->pHeader + HeaderRoom;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002288 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2289 pRxBlk->pRxPacket = pRetPacket;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002290 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002291 RESET_FRAGFRAME(pAd->FragFrame);
2292 }
2293 }
2294
2295 return pRetPacket;
2296}
2297
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002298void Indicate_AMSDU_Packet(struct rt_rtmp_adapter *pAd,
2299 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002300{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002301 u32 nMSDU;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002302
2303 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2304 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002305 nMSDU =
2306 deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData,
2307 pRxBlk->DataSize);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002308}
2309
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002310void Indicate_EAPOL_Packet(struct rt_rtmp_adapter *pAd,
2311 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002312{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002313 struct rt_mac_table_entry *pEntry = NULL;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002314
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002315 {
2316 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2317 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2318 return;
2319 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002320
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002321 if (pEntry == NULL) {
2322 DBGPRINT(RT_DEBUG_WARN,
2323 ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002324 /* release packet */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002325 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2326 NDIS_STATUS_FAILURE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002327 return;
2328 }
2329}
2330
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002331#define BCN_TBTT_OFFSET 64 /*defer 64 us */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002332void ReSyncBeaconTime(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002333{
2334
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002335 u32 Offset;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002336
2337 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2338
2339 pAd->TbttTickCount++;
2340
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002341 /* */
2342 /* The updated BeaconInterval Value will affect Beacon Interval after two TBTT */
2343 /* beacasue the original BeaconInterval had been loaded into next TBTT_TIMER */
2344 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002345 if (Offset == (BCN_TBTT_OFFSET - 2)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002346 BCN_TIME_CFG_STRUC csr;
2347 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002348 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1; /* ASIC register in units of 1/16 TU = 64us */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002349 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002350 } else {
2351 if (Offset == (BCN_TBTT_OFFSET - 1)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002352 BCN_TIME_CFG_STRUC csr;
2353
2354 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002355 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; /* ASIC register in units of 1/16 TU */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002356 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2357 }
2358 }
2359}