Commit | Line | Data |
---|---|---|
91980990 GKH |
1 | /* |
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 | ||
ca97b838 | 28 | #include "../rt_config.h" |
91980990 | 29 | |
96b3c83d BZ |
30 | UCHAR SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; |
31 | UCHAR SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; | |
91980990 | 32 | |
ec278fa2 | 33 | /* Add Cisco Aironet SNAP heade for CCX2 support */ |
96b3c83d BZ |
34 | UCHAR SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 }; |
35 | UCHAR CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 }; | |
36 | UCHAR EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e }; | |
37 | UCHAR EAPOL[] = { 0x88, 0x8e }; | |
38 | UCHAR TPID[] = { 0x81, 0x00 }; /* VLAN related */ | |
39 | ||
40 | UCHAR IPX[] = { 0x81, 0x37 }; | |
41 | UCHAR APPLE_TALK[] = { 0x80, 0xf3 }; | |
42 | ||
43 | UCHAR RateIdToPlcpSignal[12] = { | |
ec278fa2 BZ |
44 | 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 */ | |
96b3c83d | 46 | 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ |
ec278fa2 | 47 | }; /* see IEEE802.11a-1999 p.14 */ |
96b3c83d BZ |
48 | |
49 | UCHAR OfdmSignalToRateId[16] = { | |
ec278fa2 BZ |
50 | 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 */ | |
91980990 GKH |
54 | }; |
55 | ||
96b3c83d BZ |
56 | UCHAR OfdmRateToRxwiMCS[12] = { |
57 | 0, 0, 0, 0, | |
ec278fa2 BZ |
58 | 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 */ | |
91980990 | 60 | }; |
96b3c83d BZ |
61 | |
62 | UCHAR RxwiMCSToOfdmRate[12] = { | |
63 | RATE_6, RATE_9, RATE_12, RATE_18, | |
ec278fa2 BZ |
64 | 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 */ | |
91980990 GKH |
66 | }; |
67 | ||
96b3c83d BZ |
68 | char *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" }; | |
91980990 | 73 | |
96b3c83d BZ |
74 | UCHAR default_cwmin[] = |
75 | { CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS - 1, CW_MIN_IN_BITS - 2 }; | |
ec278fa2 | 76 | /*UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; */ |
96b3c83d | 77 | UCHAR default_sta_aifsn[] = { 3, 7, 2, 2 }; |
91980990 | 78 | |
96b3c83d BZ |
79 | UCHAR MapUserPriorityToAccessCategory[8] = |
80 | { QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, | |
81 | QID_AC_VO, QID_AC_VO }; | |
91980990 GKH |
82 | |
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 | */ | |
96b3c83d BZ |
107 | NDIS_STATUS MiniportMMRequest(IN PRTMP_ADAPTER pAd, |
108 | IN UCHAR QueIdx, IN PUCHAR pData, IN UINT Length) | |
91980990 | 109 | { |
96b3c83d BZ |
110 | PNDIS_PACKET pPacket; |
111 | NDIS_STATUS Status = NDIS_STATUS_SUCCESS; | |
112 | ULONG FreeNum; | |
ec278fa2 | 113 | UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; /*RTMP_HW_HDR_LEN]; */ |
ca97b838 | 114 | #ifdef RTMP_MAC_PCI |
96b3c83d BZ |
115 | unsigned long IrqFlags = 0; |
116 | UCHAR IrqState; | |
ec278fa2 | 117 | #endif /* RTMP_MAC_PCI // */ |
96b3c83d BZ |
118 | BOOLEAN bUseDataQ = FALSE; |
119 | int retryCnt = 0; | |
91980990 GKH |
120 | |
121 | ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); | |
122 | ||
96b3c83d | 123 | if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) { |
ca97b838 BZ |
124 | bUseDataQ = TRUE; |
125 | QueIdx &= (~MGMT_USE_QUEUE_FLAG); | |
126 | } | |
ca97b838 | 127 | #ifdef RTMP_MAC_PCI |
ec278fa2 | 128 | /* 2860C use Tx Ring */ |
91980990 | 129 | IrqState = pAd->irq_disabled; |
96b3c83d BZ |
130 | if (pAd->MACVersion == 0x28600100) { |
131 | QueIdx = (bUseDataQ == TRUE ? QueIdx : 3); | |
ca97b838 BZ |
132 | bUseDataQ = TRUE; |
133 | } | |
134 | if (bUseDataQ && (!IrqState)) | |
91980990 | 135 | RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); |
ec278fa2 | 136 | #endif /* RTMP_MAC_PCI // */ |
ca97b838 | 137 | |
96b3c83d | 138 | do { |
ec278fa2 | 139 | /* Reset is in progress, stop immediately */ |
ca97b838 | 140 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || |
96b3c83d BZ |
141 | 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)) { | |
91980990 GKH |
145 | Status = NDIS_STATUS_FAILURE; |
146 | break; | |
147 | } | |
ec278fa2 BZ |
148 | /* Check Free priority queue */ |
149 | /* Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. */ | |
ca97b838 | 150 | #ifdef RTMP_MAC_PCI |
96b3c83d | 151 | if (bUseDataQ) { |
ca97b838 | 152 | retryCnt = MAX_DATAMM_RETRY; |
ec278fa2 | 153 | /* free Tx(QueIdx) resources */ |
ca97b838 | 154 | RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); |
91980990 | 155 | FreeNum = GET_TXRING_FREENO(pAd, QueIdx); |
96b3c83d | 156 | } else |
ec278fa2 | 157 | #endif /* RTMP_MAC_PCI // */ |
91980990 GKH |
158 | { |
159 | FreeNum = GET_MGMTRING_FREENO(pAd); | |
160 | } | |
161 | ||
96b3c83d | 162 | if ((FreeNum > 0)) { |
ec278fa2 | 163 | /* We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 */ |
91980990 | 164 | NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE)); |
96b3c83d BZ |
165 | Status = |
166 | RTMPAllocateNdisPacket(pAd, &pPacket, | |
167 | (PUCHAR) & rtmpHwHdr, | |
168 | (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")); | |
91980990 GKH |
173 | break; |
174 | } | |
ec278fa2 BZ |
175 | /*pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; */ |
176 | /*pAd->CommonCfg.MlmeRate = RATE_2; */ | |
91980990 | 177 | |
ca97b838 | 178 | #ifdef RTMP_MAC_PCI |
96b3c83d BZ |
179 | if (bUseDataQ) { |
180 | Status = | |
181 | MlmeDataHardTransmit(pAd, QueIdx, pPacket); | |
ca97b838 | 182 | retryCnt--; |
96b3c83d | 183 | } else |
ec278fa2 | 184 | #endif /* RTMP_MAC_PCI // */ |
96b3c83d | 185 | Status = MlmeHardTransmit(pAd, QueIdx, pPacket); |
ca97b838 BZ |
186 | if (Status == NDIS_STATUS_SUCCESS) |
187 | retryCnt = 0; | |
188 | else | |
91980990 | 189 | RTMPFreeNdisPacket(pAd, pPacket); |
96b3c83d | 190 | } else { |
91980990 | 191 | pAd->RalinkCounters.MgmtRingFullCount++; |
ca97b838 | 192 | #ifdef RTMP_MAC_PCI |
96b3c83d | 193 | if (bUseDataQ) { |
ca97b838 | 194 | retryCnt--; |
96b3c83d BZ |
195 | 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)); | |
ca97b838 BZ |
203 | } |
204 | } | |
ec278fa2 | 205 | #endif /* RTMP_MAC_PCI // */ |
96b3c83d BZ |
206 | DBGPRINT(RT_DEBUG_ERROR, |
207 | ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n", | |
208 | QueIdx, | |
209 | pAd->RalinkCounters.MgmtRingFullCount)); | |
91980990 | 210 | } |
ca97b838 | 211 | } while (retryCnt > 0); |
91980990 | 212 | |
ca97b838 BZ |
213 | #ifdef RTMP_MAC_PCI |
214 | if (bUseDataQ && (!IrqState)) | |
91980990 | 215 | RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); |
ec278fa2 | 216 | #endif /* RTMP_MAC_PCI // */ |
ca97b838 | 217 | |
91980990 GKH |
218 | return Status; |
219 | } | |
220 | ||
91980990 GKH |
221 | /* |
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 | */ | |
96b3c83d BZ |
245 | NDIS_STATUS MlmeHardTransmit(IN PRTMP_ADAPTER pAd, |
246 | IN UCHAR QueIdx, IN PNDIS_PACKET pPacket) | |
91980990 | 247 | { |
96b3c83d BZ |
248 | PACKET_INFO PacketInfo; |
249 | PUCHAR pSrcBufVA; | |
250 | UINT SrcBufLen; | |
251 | PHEADER_802_11 pHeader_802_11; | |
91980990 | 252 | |
ca97b838 | 253 | if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) |
96b3c83d | 254 | ) { |
91980990 GKH |
255 | return NDIS_STATUS_FAILURE; |
256 | } | |
257 | ||
ca97b838 BZ |
258 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); |
259 | if (pSrcBufVA == NULL) | |
91980990 | 260 | return NDIS_STATUS_FAILURE; |
91980990 | 261 | |
ca97b838 | 262 | pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); |
6a28a69a | 263 | |
ca97b838 | 264 | #ifdef RTMP_MAC_PCI |
96b3c83d BZ |
265 | if (pAd->MACVersion == 0x28600100) |
266 | return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket); | |
91980990 | 267 | else |
ec278fa2 | 268 | #endif /* RTMP_MAC_PCI // */ |
96b3c83d | 269 | return MlmeHardTransmitMgmtRing(pAd, QueIdx, pPacket); |
91980990 | 270 | |
91980990 | 271 | } |
ca97b838 | 272 | |
96b3c83d BZ |
273 | NDIS_STATUS MlmeHardTransmitMgmtRing(IN PRTMP_ADAPTER pAd, |
274 | IN UCHAR QueIdx, IN PNDIS_PACKET pPacket) | |
91980990 | 275 | { |
96b3c83d BZ |
276 | PACKET_INFO PacketInfo; |
277 | PUCHAR pSrcBufVA; | |
278 | UINT SrcBufLen; | |
279 | PHEADER_802_11 pHeader_802_11; | |
280 | BOOLEAN bAckRequired, bInsertTimestamp; | |
281 | UCHAR MlmeRate; | |
282 | PTXWI_STRUC pFirstTxWI; | |
283 | MAC_TABLE_ENTRY *pMacEntry = NULL; | |
284 | UCHAR PID; | |
91980990 GKH |
285 | |
286 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); | |
91980990 | 287 | |
ec278fa2 | 288 | /* Make sure MGMT ring resource won't be used by other threads */ |
ca97b838 | 289 | RTMP_SEM_LOCK(&pAd->MgmtRingLock); |
96b3c83d | 290 | if (pSrcBufVA == NULL) { |
ec278fa2 | 291 | /* The buffer shouldn't be NULL */ |
91980990 GKH |
292 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); |
293 | return NDIS_STATUS_FAILURE; | |
294 | } | |
295 | ||
ca97b838 | 296 | { |
ec278fa2 | 297 | /* outgoing frame always wakeup PHY to prevent frame lost */ |
96b3c83d BZ |
298 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) |
299 | AsicForceWakeup(pAd, TRUE); | |
ca97b838 | 300 | } |
91980990 | 301 | |
96b3c83d | 302 | pFirstTxWI = (PTXWI_STRUC) (pSrcBufVA + TXINFO_SIZE); |
ec278fa2 | 303 | pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); /*TXWI_SIZE); */ |
91980990 | 304 | |
96b3c83d | 305 | if (pHeader_802_11->Addr1[0] & 0x01) { |
91980990 | 306 | MlmeRate = pAd->CommonCfg.BasicMlmeRate; |
96b3c83d | 307 | } else { |
91980990 GKH |
308 | MlmeRate = pAd->CommonCfg.MlmeRate; |
309 | } | |
310 | ||
ec278fa2 BZ |
311 | /* Verify Mlme rate for a / g bands. */ |
312 | if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band */ | |
91980990 GKH |
313 | MlmeRate = RATE_6; |
314 | ||
315 | if ((pHeader_802_11->FC.Type == BTYPE_DATA) && | |
96b3c83d | 316 | (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) { |
91980990 GKH |
317 | pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); |
318 | } | |
319 | ||
91980990 | 320 | { |
ec278fa2 | 321 | /* Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. */ |
91980990 | 322 | if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED |
96b3c83d | 323 | || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) { |
91980990 GKH |
324 | if (pAd->LatchRfRegs.Channel > 14) |
325 | pAd->CommonCfg.MlmeTransmit.field.MODE = 1; | |
326 | else | |
327 | pAd->CommonCfg.MlmeTransmit.field.MODE = 0; | |
328 | } | |
329 | } | |
91980990 | 330 | |
ec278fa2 BZ |
331 | /* */ |
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); */ | |
337 | ||
338 | /* */ | |
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)) */ | |
91980990 | 342 | { |
ca97b838 | 343 | if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) || |
96b3c83d BZ |
344 | ((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)))) { | |
ca97b838 | 347 | if (pAd->StaCfg.Psm == PWR_SAVE) |
96b3c83d BZ |
348 | pHeader_802_11->FC.PwrMgmt = PWR_SAVE; |
349 | else | |
350 | pHeader_802_11->FC.PwrMgmt = | |
351 | pAd->CommonCfg.bAPSDForcePowerSave; | |
352 | } | |
ca97b838 BZ |
353 | } |
354 | ||
91980990 | 355 | bInsertTimestamp = FALSE; |
ec278fa2 | 356 | if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL */ |
91980990 | 357 | { |
ec278fa2 | 358 | /*Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. */ |
96b3c83d BZ |
359 | if ((pAd->OpMode == OPMODE_STA) |
360 | && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) { | |
91980990 GKH |
361 | pHeader_802_11->FC.PwrMgmt = PWR_SAVE; |
362 | } | |
91980990 | 363 | bAckRequired = FALSE; |
ec278fa2 | 364 | } else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame) */ |
91980990 | 365 | { |
ec278fa2 BZ |
366 | /*pAd->Sequence++; */ |
367 | /*pHeader_802_11->Sequence = pAd->Sequence; */ | |
ca97b838 | 368 | |
ec278fa2 | 369 | if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */ |
91980990 GKH |
370 | { |
371 | bAckRequired = FALSE; | |
372 | pHeader_802_11->Duration = 0; | |
96b3c83d | 373 | } else { |
91980990 | 374 | bAckRequired = TRUE; |
96b3c83d BZ |
375 | 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)) { | |
91980990 | 379 | bInsertTimestamp = TRUE; |
ec278fa2 | 380 | bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Response */ |
96b3c83d BZ |
381 | } else |
382 | if ((pHeader_802_11->FC.SubType == | |
383 | SUBTYPE_PROBE_REQ) | |
384 | && (pHeader_802_11->FC.Type == BTYPE_MGMT)) { | |
ec278fa2 | 385 | bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Request */ |
91980990 GKH |
386 | } |
387 | } | |
388 | } | |
389 | ||
390 | pHeader_802_11->Sequence = pAd->Sequence++; | |
96b3c83d | 391 | if (pAd->Sequence > 0xfff) |
91980990 GKH |
392 | pAd->Sequence = 0; |
393 | ||
ec278fa2 BZ |
394 | /* 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 */ | |
91980990 | 396 | if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) |
96b3c83d BZ |
397 | && (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")); | |
ec278fa2 | 401 | /* if (!IrqState) */ |
91980990 GKH |
402 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); |
403 | return (NDIS_STATUS_FAILURE); | |
404 | } | |
405 | ||
ec278fa2 BZ |
406 | /* */ |
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 | /* */ | |
91980990 | 411 | |
ec278fa2 BZ |
412 | /* 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; */ | |
91980990 | 416 | |
ec278fa2 | 417 | /* management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. */ |
ca97b838 BZ |
418 | PID = PID_MGMT; |
419 | ||
96b3c83d BZ |
420 | 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, | |
424 | (UCHAR) pAd->CommonCfg.MlmeTransmit.field.MCS, | |
425 | IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); | |
426 | } else { | |
ca97b838 | 427 | /* dont use low rate to send QoS Null data frame */ |
91980990 | 428 | RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, |
96b3c83d BZ |
429 | bInsertTimestamp, FALSE, bAckRequired, FALSE, |
430 | 0, pMacEntry->Aid, | |
431 | (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), | |
432 | pMacEntry->MaxHTPhyMode.field.MCS, 0, | |
433 | (UCHAR) pMacEntry->MaxHTPhyMode.field.MCS, | |
434 | IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); | |
91980990 GKH |
435 | } |
436 | ||
ec278fa2 | 437 | /* Now do hardware-depened kick out. */ |
91980990 GKH |
438 | HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen); |
439 | ||
ec278fa2 BZ |
440 | /* Make sure to release MGMT ring resource */ |
441 | /* if (!IrqState) */ | |
91980990 GKH |
442 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); |
443 | return NDIS_STATUS_SUCCESS; | |
444 | } | |
445 | ||
91980990 GKH |
446 | /******************************************************************************** |
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 | */ | |
96b3c83d | 509 | static UCHAR TxPktClassification(IN RTMP_ADAPTER * pAd, IN PNDIS_PACKET pPacket) |
91980990 | 510 | { |
96b3c83d BZ |
511 | UCHAR TxFrameType = TX_UNKOWN_FRAME; |
512 | UCHAR Wcid; | |
513 | MAC_TABLE_ENTRY *pMacEntry = NULL; | |
514 | BOOLEAN bHTRate = FALSE; | |
91980990 GKH |
515 | |
516 | Wcid = RTMP_GET_PACKET_WCID(pPacket); | |
ec278fa2 | 517 | if (Wcid == MCAST_WCID) { /* Handle for RA is Broadcast/Multicast Address. */ |
91980990 GKH |
518 | return TX_MCAST_FRAME; |
519 | } | |
ec278fa2 | 520 | /* Handle for unicast packets */ |
91980990 | 521 | pMacEntry = &pAd->MacTab.Content[Wcid]; |
ec278fa2 | 522 | if (RTMP_GET_PACKET_LOWRATE(pPacket)) { /* It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame */ |
91980990 | 523 | TxFrameType = TX_LEGACY_FRAME; |
ec278fa2 | 524 | } else if (IS_HT_RATE(pMacEntry)) { /* it's a 11n capable packet */ |
91980990 | 525 | |
ec278fa2 BZ |
526 | /* Depends on HTPhyMode to check if the peer support the HTRate transmission. */ |
527 | /* Currently didn't support A-MSDU embedded in A-MPDU */ | |
91980990 | 528 | bHTRate = TRUE; |
96b3c83d BZ |
529 | if (RTMP_GET_PACKET_MOREDATA(pPacket) |
530 | || (pMacEntry->PsMode == PWR_SAVE)) | |
91980990 | 531 | TxFrameType = TX_LEGACY_FRAME; |
96b3c83d BZ |
532 | else if ((pMacEntry-> |
533 | TXBAbitmap & (1 << (RTMP_GET_PACKET_UP(pPacket)))) != | |
534 | 0) | |
91980990 | 535 | return TX_AMPDU_FRAME; |
96b3c83d BZ |
536 | else if (CLIENT_STATUS_TEST_FLAG |
537 | (pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)) | |
91980990 GKH |
538 | return TX_AMSDU_FRAME; |
539 | else | |
540 | TxFrameType = TX_LEGACY_FRAME; | |
ec278fa2 BZ |
541 | } 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. */ | |
91980990 | 543 | TxFrameType = TX_RALINK_FRAME; |
96b3c83d | 544 | } else { |
91980990 GKH |
545 | TxFrameType = TX_LEGACY_FRAME; |
546 | } | |
547 | } | |
548 | ||
ec278fa2 | 549 | /* Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. */ |
96b3c83d BZ |
550 | if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) |
551 | && (TxFrameType == TX_LEGACY_FRAME)) | |
91980990 GKH |
552 | TxFrameType = TX_FRAG_FRAME; |
553 | ||
554 | return TxFrameType; | |
555 | } | |
556 | ||
96b3c83d | 557 | BOOLEAN RTMP_FillTxBlkInfo(IN RTMP_ADAPTER * pAd, IN TX_BLK * pTxBlk) |
91980990 | 558 | { |
96b3c83d BZ |
559 | PACKET_INFO PacketInfo; |
560 | PNDIS_PACKET pPacket; | |
561 | PMAC_TABLE_ENTRY pMacEntry = NULL; | |
91980990 GKH |
562 | |
563 | pPacket = pTxBlk->pPacket; | |
96b3c83d BZ |
564 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, |
565 | &pTxBlk->SrcBufLen); | |
91980990 | 566 | |
96b3c83d BZ |
567 | pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); |
568 | pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket); | |
569 | pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); | |
ec278fa2 | 570 | pTxBlk->FrameGap = IFS_HTTXOP; /* ASIC determine Frame Gap */ |
91980990 GKH |
571 | |
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 | ||
ec278fa2 | 577 | /* Default to clear this flag */ |
91980990 GKH |
578 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS); |
579 | ||
96b3c83d | 580 | if (pTxBlk->Wcid == MCAST_WCID) { |
91980990 GKH |
581 | pTxBlk->pMacEntry = NULL; |
582 | { | |
96b3c83d BZ |
583 | pTxBlk->pTransmit = |
584 | &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; | |
91980990 GKH |
585 | } |
586 | ||
ec278fa2 BZ |
587 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); /* AckRequired = FALSE, when broadcast packet in Adhoc mode. */ |
588 | /*TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); */ | |
91980990 GKH |
589 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag); |
590 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); | |
96b3c83d | 591 | if (RTMP_GET_PACKET_MOREDATA(pPacket)) { |
91980990 GKH |
592 | TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); |
593 | } | |
594 | ||
96b3c83d | 595 | } else { |
91980990 GKH |
596 | pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid]; |
597 | pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode; | |
598 | ||
599 | pMacEntry = pTxBlk->pMacEntry; | |
600 | ||
ec278fa2 | 601 | /* For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. */ |
91980990 GKH |
602 | 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 | ||
ca97b838 | 607 | if ((pAd->OpMode == OPMODE_STA) && |
96b3c83d BZ |
608 | (ADHOC_ON(pAd)) && |
609 | (RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS))) { | |
610 | if (pAd->CommonCfg.PSPXlink) | |
ca97b838 BZ |
611 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); |
612 | } | |
613 | ||
614 | { | |
96b3c83d | 615 | { |
ca97b838 | 616 | |
ec278fa2 | 617 | /* If support WMM, enable it. */ |
96b3c83d BZ |
618 | 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); | |
ca97b838 | 623 | |
ec278fa2 BZ |
624 | /* if (pAd->StaCfg.bAutoTxRateSwitch) */ |
625 | /* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch); */ | |
ca97b838 | 626 | } |
91980990 GKH |
627 | } |
628 | ||
96b3c83d | 629 | if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) { |
ec278fa2 | 630 | 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. */ |
96b3c83d BZ |
631 | pTxBlk->pTransmit = |
632 | &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; | |
1623267a | 633 | |
ec278fa2 | 634 | /* Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? */ |
91980990 | 635 | if (IS_HT_STA(pTxBlk->pMacEntry) && |
96b3c83d BZ |
636 | (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))) | |
91980990 GKH |
641 | { |
642 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); | |
96b3c83d BZ |
643 | TX_BLK_SET_FLAG(pTxBlk, |
644 | fTX_bForceNonQoS); | |
91980990 | 645 | } |
91980990 GKH |
646 | } |
647 | ||
ec278fa2 | 648 | 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. */ |
91980990 GKH |
649 | TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack); |
650 | } | |
91980990 | 651 | |
96b3c83d | 652 | if (RTMP_GET_PACKET_MOREDATA(pPacket)) { |
91980990 GKH |
653 | TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); |
654 | } | |
96b3c83d | 655 | } else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) { |
91980990 GKH |
656 | TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag); |
657 | } | |
658 | ||
659 | pMacEntry->DebugTxCount++; | |
660 | } | |
661 | ||
662 | return TRUE; | |
91980990 GKH |
663 | } |
664 | ||
96b3c83d BZ |
665 | BOOLEAN CanDoAggregateTransmit(IN RTMP_ADAPTER * pAd, |
666 | IN NDIS_PACKET * pPacket, IN TX_BLK * pTxBlk) | |
91980990 GKH |
667 | { |
668 | ||
ec278fa2 | 669 | /*DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType)); */ |
91980990 GKH |
670 | |
671 | if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID) | |
672 | return FALSE; | |
673 | ||
674 | if (RTMP_GET_PACKET_DHCP(pPacket) || | |
96b3c83d | 675 | RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_WAI(pPacket)) |
91980990 GKH |
676 | return FALSE; |
677 | ||
ec278fa2 | 678 | 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 */ |
91980990 GKH |
679 | return FALSE; |
680 | } | |
681 | ||
ec278fa2 | 682 | if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && (pTxBlk->TxPacketList.Number == 2)) { /* For RALINK-Aggregation, allow two frames in one batch. */ |
91980990 GKH |
683 | return FALSE; |
684 | } | |
685 | ||
ec278fa2 | 686 | if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) /* must be unicast to AP */ |
91980990 GKH |
687 | return TRUE; |
688 | else | |
91980990 | 689 | return FALSE; |
ca97b838 | 690 | |
91980990 GKH |
691 | } |
692 | ||
91980990 GKH |
693 | /* |
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 | */ | |
96b3c83d BZ |
715 | VOID RTMPDeQueuePacket(IN PRTMP_ADAPTER pAd, IN BOOLEAN bIntContext, IN UCHAR QIdx, /* BulkOutPipeId */ |
716 | IN UCHAR Max_Tx_Packets) | |
91980990 | 717 | { |
96b3c83d BZ |
718 | PQUEUE_ENTRY pEntry = NULL; |
719 | PNDIS_PACKET pPacket; | |
720 | NDIS_STATUS Status = NDIS_STATUS_SUCCESS; | |
721 | UCHAR Count = 0; | |
722 | PQUEUE_HEADER pQueue; | |
723 | ULONG FreeNumber[NUM_OF_TX_RING]; | |
724 | UCHAR QueIdx, sQIdx, eQIdx; | |
725 | unsigned long IrqFlags = 0; | |
726 | BOOLEAN hasTxDesc = FALSE; | |
727 | TX_BLK TxBlk; | |
728 | TX_BLK *pTxBlk; | |
729 | ||
730 | if (QIdx == NUM_OF_TX_RING) { | |
91980990 | 731 | sQIdx = 0; |
ec278fa2 | 732 | eQIdx = 3; /* 4 ACs, start from 0. */ |
96b3c83d | 733 | } else { |
91980990 GKH |
734 | sQIdx = eQIdx = QIdx; |
735 | } | |
736 | ||
96b3c83d BZ |
737 | for (QueIdx = sQIdx; QueIdx <= eQIdx; QueIdx++) { |
738 | Count = 0; | |
91980990 | 739 | |
ca97b838 | 740 | RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags); |
91980990 | 741 | |
96b3c83d BZ |
742 | 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)))) { | |
ca97b838 | 750 | RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); |
91980990 GKH |
751 | return; |
752 | } | |
753 | ||
754 | if (Count >= Max_Tx_Packets) | |
755 | break; | |
756 | ||
757 | DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags); | |
96b3c83d BZ |
758 | if (&pAd->TxSwQueue[QueIdx] == NULL) { |
759 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, | |
760 | IrqFlags); | |
91980990 GKH |
761 | break; |
762 | } | |
ca97b838 | 763 | #ifdef RTMP_MAC_PCI |
91980990 GKH |
764 | FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); |
765 | ||
96b3c83d | 766 | if (FreeNumber[QueIdx] <= 5) { |
ec278fa2 | 767 | /* free Tx(QueIdx) resources */ |
91980990 | 768 | RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); |
96b3c83d BZ |
769 | FreeNumber[QueIdx] = |
770 | GET_TXRING_FREENO(pAd, QueIdx); | |
91980990 | 771 | } |
ec278fa2 | 772 | #endif /* RTMP_MAC_PCI // */ |
ca97b838 | 773 | |
ec278fa2 | 774 | /* probe the Queue Head */ |
91980990 | 775 | pQueue = &pAd->TxSwQueue[QueIdx]; |
96b3c83d BZ |
776 | if ((pEntry = pQueue->Head) == NULL) { |
777 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, | |
778 | IrqFlags); | |
91980990 GKH |
779 | break; |
780 | } | |
781 | ||
782 | pTxBlk = &TxBlk; | |
96b3c83d | 783 | NdisZeroMemory((PUCHAR) pTxBlk, sizeof(TX_BLK)); |
ec278fa2 | 784 | /*InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it. */ |
91980990 GKH |
785 | pTxBlk->QueIdx = QueIdx; |
786 | ||
ca97b838 BZ |
787 | pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); |
788 | ||
ec278fa2 | 789 | /* Early check to make sure we have enoguh Tx Resource. */ |
96b3c83d BZ |
790 | hasTxDesc = |
791 | RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, | |
792 | FreeNumber[QueIdx], | |
793 | pPacket); | |
794 | if (!hasTxDesc) { | |
91980990 GKH |
795 | pAd->PrivateInfo.TxRingFullCnt++; |
796 | ||
96b3c83d BZ |
797 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, |
798 | IrqFlags); | |
91980990 GKH |
799 | |
800 | break; | |
801 | } | |
802 | ||
803 | pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket); | |
804 | pEntry = RemoveHeadQueue(pQueue); | |
805 | pTxBlk->TotalFrameNum++; | |
ec278fa2 | 806 | pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */ |
91980990 GKH |
807 | pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); |
808 | pTxBlk->pPacket = pPacket; | |
96b3c83d BZ |
809 | InsertTailQueue(&pTxBlk->TxPacketList, |
810 | PACKET_TO_QUEUE_ENTRY(pPacket)); | |
91980990 | 811 | |
96b3c83d BZ |
812 | if (pTxBlk->TxFrameType == TX_RALINK_FRAME |
813 | || pTxBlk->TxFrameType == TX_AMSDU_FRAME) { | |
ec278fa2 | 814 | /* Enhance SW Aggregation Mechanism */ |
96b3c83d BZ |
815 | 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); | |
91980990 GKH |
823 | break; |
824 | } | |
825 | ||
96b3c83d BZ |
826 | do { |
827 | if ((pEntry = pQueue->Head) == NULL) | |
91980990 GKH |
828 | break; |
829 | ||
ec278fa2 | 830 | /* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. */ |
ca97b838 | 831 | pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); |
96b3c83d BZ |
832 | 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)) | |
91980990 GKH |
844 | break; |
845 | ||
ec278fa2 | 846 | /*Remove the packet from the TxSwQueue and insert into pTxBlk */ |
91980990 GKH |
847 | pEntry = RemoveHeadQueue(pQueue); |
848 | ASSERT(pEntry); | |
ca97b838 | 849 | pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); |
91980990 | 850 | pTxBlk->TotalFrameNum++; |
ec278fa2 | 851 | pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */ |
96b3c83d BZ |
852 | pTxBlk->TotalFrameLen += |
853 | GET_OS_PKT_LEN(pPacket); | |
854 | InsertTailQueue(&pTxBlk->TxPacketList, | |
855 | PACKET_TO_QUEUE_ENTRY | |
856 | (pPacket)); | |
857 | } while (1); | |
91980990 GKH |
858 | |
859 | if (pTxBlk->TxPacketList.Number == 1) | |
860 | pTxBlk->TxFrameType = TX_LEGACY_FRAME; | |
861 | } | |
ca97b838 | 862 | #ifdef RTMP_MAC_USB |
59fe2d89 | 863 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); |
ec278fa2 | 864 | #endif /* RTMP_MAC_USB // */ |
91980990 GKH |
865 | Count += pTxBlk->TxPacketList.Number; |
866 | ||
ec278fa2 | 867 | /* Do HardTransmit now. */ |
5a911fd6 | 868 | Status = STAHardTransmit(pAd, pTxBlk, QueIdx); |
91980990 | 869 | |
ca97b838 | 870 | #ifdef RTMP_MAC_PCI |
91980990 | 871 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); |
ec278fa2 BZ |
872 | /* static rate also need NICUpdateFifoStaCounters() function. */ |
873 | /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ | |
96b3c83d | 874 | NICUpdateFifoStaCounters(pAd); |
ec278fa2 | 875 | #endif /* RTMP_MAC_PCI // */ |
ca97b838 | 876 | |
91980990 GKH |
877 | } |
878 | ||
ca97b838 | 879 | RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); |
59fe2d89 | 880 | |
ca97b838 | 881 | #ifdef RTMP_MAC_USB |
59fe2d89 BZ |
882 | if (!hasTxDesc) |
883 | RTUSBKickBulkOut(pAd); | |
ec278fa2 | 884 | #endif /* RTMP_MAC_USB // */ |
91980990 GKH |
885 | } |
886 | ||
887 | } | |
888 | ||
91980990 GKH |
889 | /* |
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 | */ | |
96b3c83d | 911 | USHORT RTMPCalcDuration(IN PRTMP_ADAPTER pAd, IN UCHAR Rate, IN ULONG Size) |
91980990 | 912 | { |
96b3c83d | 913 | ULONG Duration = 0; |
91980990 | 914 | |
ec278fa2 | 915 | if (Rate < RATE_FIRST_OFDM_RATE) /* CCK */ |
91980990 | 916 | { |
96b3c83d BZ |
917 | if ((Rate > RATE_1) |
918 | && OPSTATUS_TEST_FLAG(pAd, | |
919 | fOP_STATUS_SHORT_PREAMBLE_INUSED)) | |
ec278fa2 | 920 | Duration = 96; /* 72+24 preamble+plcp */ |
91980990 | 921 | else |
ec278fa2 | 922 | Duration = 192; /* 144+48 preamble+plcp */ |
91980990 | 923 | |
96b3c83d | 924 | Duration += (USHORT) ((Size << 4) / RateIdTo500Kbps[Rate]); |
91980990 | 925 | if ((Size << 4) % RateIdTo500Kbps[Rate]) |
96b3c83d | 926 | Duration++; |
ec278fa2 | 927 | } else if (Rate <= RATE_LAST_OFDM_RATE) /* OFDM rates */ |
91980990 | 928 | { |
ec278fa2 | 929 | Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */ |
96b3c83d BZ |
930 | Duration += |
931 | 4 * (USHORT) ((11 + Size * 4) / RateIdTo500Kbps[Rate]); | |
91980990 GKH |
932 | if ((11 + Size * 4) % RateIdTo500Kbps[Rate]) |
933 | Duration += 4; | |
ec278fa2 | 934 | } else /*mimo rate */ |
91980990 | 935 | { |
ec278fa2 | 936 | Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */ |
91980990 GKH |
937 | } |
938 | ||
96b3c83d | 939 | return (USHORT) Duration; |
91980990 GKH |
940 | } |
941 | ||
91980990 GKH |
942 | /* |
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 | */ | |
ec278fa2 | 971 | VOID RTMPWriteTxWI(IN PRTMP_ADAPTER pAd, IN PTXWI_STRUC pOutTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq, /* HW new a sequence. */ |
96b3c83d BZ |
972 | IN UCHAR BASize, |
973 | IN UCHAR WCID, | |
974 | IN ULONG Length, | |
975 | IN UCHAR PID, | |
976 | IN UCHAR TID, | |
977 | IN UCHAR TxRate, | |
978 | IN UCHAR Txopmode, | |
979 | IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit) | |
91980990 | 980 | { |
96b3c83d BZ |
981 | PMAC_TABLE_ENTRY pMac = NULL; |
982 | TXWI_STRUC TxWI; | |
983 | PTXWI_STRUC pTxWI; | |
91980990 GKH |
984 | |
985 | if (WCID < MAX_LEN_OF_MAC_TABLE) | |
986 | pMac = &pAd->MacTab.Content[WCID]; | |
987 | ||
ec278fa2 BZ |
988 | /* */ |
989 | /* Always use Long preamble before verifiation short preamble functionality works well. */ | |
990 | /* Todo: remove the following line if short preamble functionality works */ | |
991 | /* */ | |
91980990 GKH |
992 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); |
993 | NdisZeroMemory(&TxWI, TXWI_SIZE); | |
994 | pTxWI = &TxWI; | |
995 | ||
96b3c83d | 996 | pTxWI->FRAG = FRAG; |
91980990 GKH |
997 | |
998 | pTxWI->CFACK = CFACK; | |
96b3c83d | 999 | pTxWI->TS = InsTimestamp; |
91980990 GKH |
1000 | pTxWI->AMPDU = AMPDU; |
1001 | pTxWI->ACK = Ack; | |
96b3c83d | 1002 | pTxWI->txop = Txopmode; |
91980990 GKH |
1003 | |
1004 | pTxWI->NSEQ = NSeq; | |
ec278fa2 | 1005 | /* John tune the performace with Intel Client in 20 MHz performance */ |
91980990 | 1006 | BASize = pAd->CommonCfg.TxBASize; |
96b3c83d BZ |
1007 | if (pAd->MACVersion == 0x28720200) { |
1008 | if (BASize > 13) | |
1009 | BASize = 13; | |
1010 | } else { | |
1011 | if (BASize > 7) | |
1012 | BASize = 7; | |
ca97b838 | 1013 | } |
91980990 GKH |
1014 | pTxWI->BAWinSize = BASize; |
1015 | pTxWI->ShortGI = pTransmit->field.ShortGI; | |
1016 | pTxWI->STBC = pTransmit->field.STBC; | |
91980990 GKH |
1017 | |
1018 | pTxWI->WirelessCliID = WCID; | |
1019 | pTxWI->MPDUtotalByteCount = Length; | |
1020 | pTxWI->PacketId = PID; | |
1021 | ||
ec278fa2 | 1022 | /* If CCK or OFDM, BW must be 20 */ |
96b3c83d BZ |
1023 | pTxWI->BW = |
1024 | (pTransmit->field.MODE <= | |
1025 | MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | |
91980990 GKH |
1026 | |
1027 | pTxWI->MCS = pTransmit->field.MCS; | |
1028 | pTxWI->PHYMODE = pTransmit->field.MODE; | |
1029 | pTxWI->CFACK = CfAck; | |
1030 | ||
96b3c83d BZ |
1031 | if (pMac) { |
1032 | if (pAd->CommonCfg.bMIMOPSEnable) { | |
1033 | if ((pMac->MmpsMode == MMPS_DYNAMIC) | |
1034 | && (pTransmit->field.MCS > 7)) { | |
ec278fa2 | 1035 | /* Dynamic MIMO Power Save Mode */ |
91980990 | 1036 | pTxWI->MIMOps = 1; |
96b3c83d | 1037 | } else if (pMac->MmpsMode == MMPS_STATIC) { |
ec278fa2 | 1038 | /* Static MIMO Power Save Mode */ |
96b3c83d BZ |
1039 | if (pTransmit->field.MODE >= MODE_HTMIX |
1040 | && pTransmit->field.MCS > 7) { | |
91980990 GKH |
1041 | pTxWI->MCS = 7; |
1042 | pTxWI->MIMOps = 0; | |
1043 | } | |
1044 | } | |
1045 | } | |
ec278fa2 | 1046 | /*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; */ |
96b3c83d BZ |
1047 | if (pMac->bIAmBadAtheros |
1048 | && (pMac->WepStatus != Ndis802_11WEPDisabled)) { | |
91980990 | 1049 | pTxWI->MpduDensity = 7; |
96b3c83d | 1050 | } else { |
91980990 GKH |
1051 | pTxWI->MpduDensity = pMac->MpduDensity; |
1052 | } | |
1053 | } | |
91980990 GKH |
1054 | |
1055 | pTxWI->PacketId = pTxWI->MCS; | |
1056 | NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC)); | |
1057 | } | |
1058 | ||
96b3c83d BZ |
1059 | VOID RTMPWriteTxWI_Data(IN PRTMP_ADAPTER pAd, |
1060 | IN OUT PTXWI_STRUC pTxWI, IN TX_BLK * pTxBlk) | |
91980990 | 1061 | { |
96b3c83d BZ |
1062 | HTTRANSMIT_SETTING *pTransmit; |
1063 | PMAC_TABLE_ENTRY pMacEntry; | |
1064 | UCHAR BASize; | |
91980990 GKH |
1065 | |
1066 | ASSERT(pTxWI); | |
1067 | ||
1068 | pTransmit = pTxBlk->pTransmit; | |
1069 | pMacEntry = pTxBlk->pMacEntry; | |
1070 | ||
ec278fa2 BZ |
1071 | /* */ |
1072 | /* Always use Long preamble before verifiation short preamble functionality works well. */ | |
1073 | /* Todo: remove the following line if short preamble functionality works */ | |
1074 | /* */ | |
91980990 GKH |
1075 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); |
1076 | NdisZeroMemory(pTxWI, TXWI_SIZE); | |
1077 | ||
96b3c83d BZ |
1078 | pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); |
1079 | pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); | |
1080 | pTxWI->txop = pTxBlk->FrameGap; | |
91980990 | 1081 | |
96b3c83d | 1082 | pTxWI->WirelessCliID = pTxBlk->Wcid; |
91980990 | 1083 | |
96b3c83d BZ |
1084 | pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; |
1085 | pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); | |
91980990 | 1086 | |
ec278fa2 | 1087 | /* If CCK or OFDM, BW must be 20 */ |
96b3c83d BZ |
1088 | pTxWI->BW = |
1089 | (pTransmit->field.MODE <= | |
1090 | MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | |
1091 | pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); | |
91980990 | 1092 | |
ec278fa2 | 1093 | /* John tune the performace with Intel Client in 20 MHz performance */ |
91980990 | 1094 | BASize = pAd->CommonCfg.TxBASize; |
96b3c83d | 1095 | if ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) { |
ec278fa2 | 1096 | UCHAR RABAOriIdx = 0; /*The RA's BA Originator table index. */ |
91980990 | 1097 | |
96b3c83d BZ |
1098 | RABAOriIdx = |
1099 | pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; | |
91980990 GKH |
1100 | 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; | |
91980990 GKH |
1107 | |
1108 | pTxWI->MCS = pTransmit->field.MCS; | |
1109 | pTxWI->PHYMODE = pTransmit->field.MODE; | |
1110 | ||
96b3c83d BZ |
1111 | if (pMacEntry) { |
1112 | if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) | |
1113 | && (pTransmit->field.MCS > 7)) { | |
ec278fa2 | 1114 | /* Dynamic MIMO Power Save Mode */ |
91980990 | 1115 | pTxWI->MIMOps = 1; |
96b3c83d | 1116 | } else if (pMacEntry->MmpsMode == MMPS_STATIC) { |
ec278fa2 | 1117 | /* Static MIMO Power Save Mode */ |
96b3c83d BZ |
1118 | if (pTransmit->field.MODE >= MODE_HTMIX |
1119 | && pTransmit->field.MCS > 7) { | |
91980990 GKH |
1120 | pTxWI->MCS = 7; |
1121 | pTxWI->MIMOps = 0; | |
1122 | } | |
1123 | } | |
1124 | ||
96b3c83d BZ |
1125 | if (pMacEntry->bIAmBadAtheros |
1126 | && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) { | |
91980990 | 1127 | pTxWI->MpduDensity = 7; |
96b3c83d | 1128 | } else { |
91980990 GKH |
1129 | pTxWI->MpduDensity = pMacEntry->MpduDensity; |
1130 | } | |
1131 | } | |
91980990 | 1132 | |
ec278fa2 | 1133 | /* for rate adapation */ |
91980990 GKH |
1134 | pTxWI->PacketId = pTxWI->MCS; |
1135 | } | |
1136 | ||
96b3c83d BZ |
1137 | VOID RTMPWriteTxWI_Cache(IN PRTMP_ADAPTER pAd, |
1138 | IN OUT PTXWI_STRUC pTxWI, IN TX_BLK * pTxBlk) | |
91980990 | 1139 | { |
96b3c83d BZ |
1140 | PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit; |
1141 | PMAC_TABLE_ENTRY pMacEntry; | |
91980990 | 1142 | |
ec278fa2 BZ |
1143 | /* */ |
1144 | /* update TXWI */ | |
1145 | /* */ | |
91980990 GKH |
1146 | pMacEntry = pTxBlk->pMacEntry; |
1147 | pTransmit = pTxBlk->pTransmit; | |
1148 | ||
ec278fa2 BZ |
1149 | /*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)) */ | |
96b3c83d | 1152 | if (pMacEntry->bAutoTxRateSwitch) { |
91980990 GKH |
1153 | pTxWI->txop = IFS_HTTXOP; |
1154 | ||
ec278fa2 | 1155 | /* If CCK or OFDM, BW must be 20 */ |
96b3c83d BZ |
1156 | pTxWI->BW = |
1157 | (pTransmit->field.MODE <= | |
1158 | MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | |
91980990 GKH |
1159 | 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 | ||
ec278fa2 | 1165 | /* set PID for TxRateSwitching */ |
91980990 GKH |
1166 | pTxWI->PacketId = pTransmit->field.MCS; |
1167 | } | |
1168 | ||
96b3c83d | 1169 | pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE : FALSE); |
91980990 GKH |
1170 | pTxWI->MIMOps = 0; |
1171 | ||
96b3c83d | 1172 | if (pAd->CommonCfg.bMIMOPSEnable) { |
ec278fa2 | 1173 | /* MIMO Power Save Mode */ |
96b3c83d BZ |
1174 | if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) |
1175 | && (pTransmit->field.MCS > 7)) { | |
ec278fa2 | 1176 | /* Dynamic MIMO Power Save Mode */ |
91980990 | 1177 | pTxWI->MIMOps = 1; |
96b3c83d | 1178 | } else if (pMacEntry->MmpsMode == MMPS_STATIC) { |
ec278fa2 | 1179 | /* Static MIMO Power Save Mode */ |
96b3c83d BZ |
1180 | if ((pTransmit->field.MODE >= MODE_HTMIX) |
1181 | && (pTransmit->field.MCS > 7)) { | |
91980990 GKH |
1182 | pTxWI->MCS = 7; |
1183 | pTxWI->MIMOps = 0; | |
1184 | } | |
1185 | } | |
1186 | } | |
91980990 | 1187 | |
91980990 GKH |
1188 | pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; |
1189 | ||
1190 | } | |
1191 | ||
ec278fa2 BZ |
1192 | /* 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 */ | |
96b3c83d BZ |
1197 | BOOLEAN TxFrameIsAggregatible(IN PRTMP_ADAPTER pAd, |
1198 | IN PUCHAR pPrevAddr1, IN PUCHAR p8023hdr) | |
91980990 GKH |
1199 | { |
1200 | ||
ec278fa2 | 1201 | /* can't aggregate EAPOL (802.1x) frame */ |
91980990 GKH |
1202 | if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e)) |
1203 | return FALSE; | |
1204 | ||
ec278fa2 | 1205 | /* can't aggregate multicast/broadcast frame */ |
91980990 GKH |
1206 | if (p8023hdr[0] & 0x01) |
1207 | return FALSE; | |
1208 | ||
ec278fa2 | 1209 | if (INFRA_ON(pAd)) /* must be unicast to AP */ |
91980990 | 1210 | return TRUE; |
ec278fa2 | 1211 | else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) /* unicast to same STA */ |
91980990 GKH |
1212 | return TRUE; |
1213 | else | |
1214 | return FALSE; | |
1215 | } | |
1216 | ||
91980990 GKH |
1217 | /* |
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 | */ | |
96b3c83d BZ |
1233 | BOOLEAN PeerIsAggreOn(IN PRTMP_ADAPTER pAd, |
1234 | IN ULONG TxRate, IN PMAC_TABLE_ENTRY pMacEntry) | |
91980990 | 1235 | { |
96b3c83d BZ |
1236 | ULONG AFlags = |
1237 | (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE); | |
91980990 | 1238 | |
96b3c83d BZ |
1239 | if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) { |
1240 | if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) { | |
91980990 GKH |
1241 | return TRUE; |
1242 | } | |
91980990 | 1243 | #ifdef AGGREGATION_SUPPORT |
ec278fa2 | 1244 | 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 */ |
91980990 GKH |
1245 | return TRUE; |
1246 | } | |
ec278fa2 | 1247 | #endif /* AGGREGATION_SUPPORT // */ |
91980990 GKH |
1248 | } |
1249 | ||
1250 | return FALSE; | |
1251 | ||
1252 | } | |
1253 | ||
91980990 GKH |
1254 | /* |
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 | */ | |
96b3c83d | 1272 | PQUEUE_HEADER RTMPCheckTxSwQueue(IN PRTMP_ADAPTER pAd, OUT PUCHAR pQueIdx) |
91980990 GKH |
1273 | { |
1274 | ||
96b3c83d | 1275 | ULONG Number; |
ec278fa2 BZ |
1276 | /* 2004-11-15 to be removed. test aggregation only */ |
1277 | /* if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) */ | |
1278 | /* return NULL; */ | |
91980990 GKH |
1279 | |
1280 | Number = pAd->TxSwQueue[QID_AC_BK].Number | |
96b3c83d BZ |
1281 | + pAd->TxSwQueue[QID_AC_BE].Number |
1282 | + pAd->TxSwQueue[QID_AC_VI].Number | |
1283 | + pAd->TxSwQueue[QID_AC_VO].Number; | |
91980990 | 1284 | |
96b3c83d | 1285 | if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) { |
91980990 GKH |
1286 | *pQueIdx = QID_AC_VO; |
1287 | return (&pAd->TxSwQueue[QID_AC_VO]); | |
96b3c83d | 1288 | } else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) { |
91980990 GKH |
1289 | *pQueIdx = QID_AC_VI; |
1290 | return (&pAd->TxSwQueue[QID_AC_VI]); | |
96b3c83d | 1291 | } else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) { |
91980990 GKH |
1292 | *pQueIdx = QID_AC_BE; |
1293 | return (&pAd->TxSwQueue[QID_AC_BE]); | |
96b3c83d | 1294 | } else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) { |
91980990 GKH |
1295 | *pQueIdx = QID_AC_BK; |
1296 | return (&pAd->TxSwQueue[QID_AC_BK]); | |
1297 | } | |
ec278fa2 | 1298 | /* No packet pending in Tx Sw queue */ |
91980990 GKH |
1299 | *pQueIdx = QID_AC_BK; |
1300 | ||
1301 | return (NULL); | |
1302 | } | |
1303 | ||
91980990 GKH |
1304 | /* |
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 | */ | |
96b3c83d | 1320 | VOID RTMPSuspendMsduTransmission(IN PRTMP_ADAPTER pAd) |
91980990 | 1321 | { |
96b3c83d | 1322 | DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n")); |
91980990 | 1323 | |
ec278fa2 BZ |
1324 | /* */ |
1325 | /* Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and */ | |
1326 | /* use Lowbound as R66 value on ScanNextChannel(...) */ | |
1327 | /* */ | |
96b3c83d BZ |
1328 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, |
1329 | &pAd->BbpTuning.R66CurrentValue); | |
91980990 | 1330 | |
ec278fa2 BZ |
1331 | /* 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))); */ | |
91980990 GKH |
1333 | RTMPSetAGCInitValue(pAd, BW_20); |
1334 | ||
1335 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | |
ec278fa2 | 1336 | /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings */ |
91980990 GKH |
1337 | } |
1338 | ||
91980990 GKH |
1339 | /* |
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 | */ | |
96b3c83d | 1357 | VOID RTMPResumeMsduTransmission(IN PRTMP_ADAPTER pAd) |
91980990 | 1358 | { |
ec278fa2 | 1359 | /* UCHAR IrqState; */ |
91980990 | 1360 | |
96b3c83d | 1361 | DBGPRINT(RT_DEBUG_TRACE, ("SCAN done, resume MSDU transmission ...\n")); |
ca97b838 | 1362 | |
ec278fa2 BZ |
1363 | /* After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value */ |
1364 | /* R66 should not be 0 */ | |
96b3c83d | 1365 | if (pAd->BbpTuning.R66CurrentValue == 0) { |
59fe2d89 BZ |
1366 | pAd->BbpTuning.R66CurrentValue = 0x38; |
1367 | DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n")); | |
1368 | } | |
7765e89d | 1369 | |
96b3c83d BZ |
1370 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, |
1371 | pAd->BbpTuning.R66CurrentValue); | |
91980990 GKH |
1372 | |
1373 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | |
ec278fa2 BZ |
1374 | /* 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 */ | |
91980990 GKH |
1379 | RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); |
1380 | } | |
1381 | ||
96b3c83d BZ |
1382 | UINT deaggregate_AMSDU_announce(IN PRTMP_ADAPTER pAd, |
1383 | PNDIS_PACKET pPacket, | |
1384 | IN PUCHAR pData, IN ULONG DataSize) | |
91980990 | 1385 | { |
96b3c83d BZ |
1386 | USHORT PayloadSize; |
1387 | USHORT SubFrameSize; | |
1388 | PHEADER_802_3 pAMSDUsubheader; | |
1389 | UINT nMSDU; | |
1390 | UCHAR Header802_3[14]; | |
91980990 | 1391 | |
96b3c83d BZ |
1392 | PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP; |
1393 | PNDIS_PACKET pClonePacket; | |
91980990 GKH |
1394 | |
1395 | nMSDU = 0; | |
1396 | ||
96b3c83d | 1397 | while (DataSize > LENGTH_802_3) { |
91980990 GKH |
1398 | |
1399 | nMSDU++; | |
1400 | ||
ec278fa2 | 1401 | /*hex_dump("subheader", pData, 64); */ |
96b3c83d | 1402 | pAMSDUsubheader = (PHEADER_802_3) pData; |
ec278fa2 | 1403 | /*pData += LENGTH_802_3; */ |
96b3c83d BZ |
1404 | PayloadSize = |
1405 | pAMSDUsubheader->Octet[1] + | |
1406 | (pAMSDUsubheader->Octet[0] << 8); | |
91980990 GKH |
1407 | SubFrameSize = PayloadSize + LENGTH_802_3; |
1408 | ||
96b3c83d | 1409 | if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) { |
91980990 GKH |
1410 | break; |
1411 | } | |
ec278fa2 | 1412 | /*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize)); */ |
ca97b838 | 1413 | |
91980990 GKH |
1414 | pPayload = pData + LENGTH_802_3; |
1415 | pDA = pData; | |
1416 | pSA = pData + MAC_ADDR_LEN; | |
1417 | ||
ec278fa2 | 1418 | /* convert to 802.3 header */ |
96b3c83d BZ |
1419 | CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, |
1420 | pRemovedLLCSNAP); | |
91980990 | 1421 | |
96b3c83d | 1422 | if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) { |
ca97b838 | 1423 | /* avoid local heap overflow, use dyanamic allocation */ |
96b3c83d BZ |
1424 | MLME_QUEUE_ELEM *Elem = |
1425 | (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), | |
1426 | 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; | |
ec278fa2 | 1434 | /*WpaEAPOLKeyAction(pAd, Elem); */ |
96b3c83d BZ |
1435 | REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID, |
1436 | Elem->Msg, | |
1437 | Elem->MsgLen, 0, 0, 0, | |
1438 | 0); | |
1439 | kfree(Elem); | |
1440 | } | |
ca97b838 | 1441 | } |
91980990 | 1442 | |
91980990 | 1443 | { |
96b3c83d BZ |
1444 | if (pRemovedLLCSNAP) { |
1445 | pPayload -= LENGTH_802_3; | |
1446 | PayloadSize += LENGTH_802_3; | |
1447 | NdisMoveMemory(pPayload, &Header802_3[0], | |
1448 | LENGTH_802_3); | |
1449 | } | |
91980990 | 1450 | } |
91980990 GKH |
1451 | |
1452 | pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize); | |
96b3c83d BZ |
1453 | if (pClonePacket) { |
1454 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, | |
1455 | RTMP_GET_PACKET_IF | |
1456 | (pPacket)); | |
91980990 GKH |
1457 | } |
1458 | ||
ec278fa2 BZ |
1459 | /* A-MSDU has padding to multiple of 4 including subframe header. */ |
1460 | /* align SubFrameSize up to multiple of 4 */ | |
96b3c83d | 1461 | SubFrameSize = (SubFrameSize + 3) & (~0x3); |
91980990 | 1462 | |
96b3c83d | 1463 | if (SubFrameSize > 1528 || SubFrameSize < 32) { |
91980990 GKH |
1464 | break; |
1465 | } | |
1466 | ||
96b3c83d | 1467 | if (DataSize > SubFrameSize) { |
91980990 GKH |
1468 | pData += SubFrameSize; |
1469 | DataSize -= SubFrameSize; | |
96b3c83d | 1470 | } else { |
ec278fa2 | 1471 | /* end of A-MSDU */ |
91980990 GKH |
1472 | DataSize = 0; |
1473 | } | |
1474 | } | |
1475 | ||
ec278fa2 | 1476 | /* finally release original rx packet */ |
91980990 GKH |
1477 | RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); |
1478 | ||
1479 | return nMSDU; | |
1480 | } | |
1481 | ||
96b3c83d | 1482 | UINT BA_Reorder_AMSDU_Annnounce(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket) |
91980990 | 1483 | { |
96b3c83d BZ |
1484 | PUCHAR pData; |
1485 | USHORT DataSize; | |
1486 | UINT nMSDU = 0; | |
91980990 GKH |
1487 | |
1488 | pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); | |
1489 | DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); | |
1490 | ||
1491 | nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize); | |
1492 | ||
1493 | return nMSDU; | |
1494 | } | |
1495 | ||
91980990 GKH |
1496 | /* |
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 | */ | |
96b3c83d | 1504 | MAC_TABLE_ENTRY *MacTableLookup(IN PRTMP_ADAPTER pAd, PUCHAR pAddr) |
91980990 GKH |
1505 | { |
1506 | ULONG HashIdx; | |
1507 | MAC_TABLE_ENTRY *pEntry = NULL; | |
1508 | ||
1509 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | |
1510 | pEntry = pAd->MacTab.Hash[HashIdx]; | |
1511 | ||
96b3c83d BZ |
1512 | while (pEntry |
1513 | && (pEntry->ValidAsCLI || pEntry->ValidAsWDS | |
1514 | || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) { | |
1515 | if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) { | |
91980990 | 1516 | break; |
96b3c83d | 1517 | } else |
91980990 GKH |
1518 | pEntry = pEntry->pNext; |
1519 | } | |
1520 | ||
1521 | return pEntry; | |
1522 | } | |
1523 | ||
96b3c83d BZ |
1524 | MAC_TABLE_ENTRY *MacTableInsertEntry(IN PRTMP_ADAPTER pAd, |
1525 | IN PUCHAR pAddr, | |
1526 | IN UCHAR apidx, IN BOOLEAN CleanAll) | |
91980990 GKH |
1527 | { |
1528 | UCHAR HashIdx; | |
1529 | int i, FirstWcid; | |
1530 | MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; | |
ec278fa2 BZ |
1531 | /* USHORT offset; */ |
1532 | /* ULONG addr; */ | |
91980990 | 1533 | |
ec278fa2 | 1534 | /* if FULL, return */ |
91980990 GKH |
1535 | if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) |
1536 | return NULL; | |
1537 | ||
1538 | FirstWcid = 1; | |
6a28a69a | 1539 | |
91980990 GKH |
1540 | if (pAd->StaCfg.BssType == BSS_INFRA) |
1541 | FirstWcid = 2; | |
91980990 | 1542 | |
ec278fa2 | 1543 | /* allocate one MAC entry */ |
91980990 | 1544 | NdisAcquireSpinLock(&pAd->MacTabLock); |
ec278fa2 | 1545 | for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++) /* skip entry#0 so that "entry index == AID" for fast lookup */ |
91980990 | 1546 | { |
ec278fa2 | 1547 | /* pick up the first available vacancy */ |
91980990 | 1548 | if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) && |
96b3c83d BZ |
1549 | (pAd->MacTab.Content[i].ValidAsWDS == FALSE) && |
1550 | (pAd->MacTab.Content[i].ValidAsApCli == FALSE) && | |
1551 | (pAd->MacTab.Content[i].ValidAsMesh == FALSE) | |
1552 | ) { | |
91980990 | 1553 | pEntry = &pAd->MacTab.Content[i]; |
96b3c83d | 1554 | if (CleanAll == TRUE) { |
91980990 GKH |
1555 | pEntry->MaxSupportedRate = RATE_11; |
1556 | pEntry->CurrTxRate = RATE_11; | |
1557 | NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); | |
1558 | pEntry->PairwiseKey.KeyLen = 0; | |
1559 | pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; | |
1560 | } | |
91980990 | 1561 | { |
91980990 GKH |
1562 | { |
1563 | pEntry->ValidAsCLI = TRUE; | |
1564 | pEntry->ValidAsWDS = FALSE; | |
1565 | pEntry->ValidAsApCli = FALSE; | |
1566 | pEntry->ValidAsMesh = FALSE; | |
1567 | pEntry->ValidAsDls = FALSE; | |
1568 | } | |
91980990 GKH |
1569 | } |
1570 | ||
1571 | pEntry->bIAmBadAtheros = FALSE; | |
1572 | pEntry->pAd = pAd; | |
1573 | pEntry->CMTimerRunning = FALSE; | |
96b3c83d BZ |
1574 | pEntry->EnqueueEapolStartTimerRunning = |
1575 | EAPOL_START_DISABLE; | |
91980990 | 1576 | pEntry->RSNIE_Len = 0; |
96b3c83d BZ |
1577 | NdisZeroMemory(pEntry->R_Counter, |
1578 | sizeof(pEntry->R_Counter)); | |
91980990 GKH |
1579 | pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; |
1580 | ||
1581 | if (pEntry->ValidAsMesh) | |
96b3c83d BZ |
1582 | pEntry->apidx = |
1583 | (apidx - MIN_NET_DEVICE_FOR_MESH); | |
91980990 | 1584 | else if (pEntry->ValidAsApCli) |
96b3c83d BZ |
1585 | pEntry->apidx = |
1586 | (apidx - MIN_NET_DEVICE_FOR_APCLI); | |
91980990 | 1587 | else if (pEntry->ValidAsWDS) |
96b3c83d BZ |
1588 | pEntry->apidx = |
1589 | (apidx - MIN_NET_DEVICE_FOR_WDS); | |
91980990 GKH |
1590 | else |
1591 | pEntry->apidx = apidx; | |
1592 | ||
1593 | { | |
91980990 GKH |
1594 | { |
1595 | pEntry->AuthMode = pAd->StaCfg.AuthMode; | |
96b3c83d BZ |
1596 | pEntry->WepStatus = |
1597 | pAd->StaCfg.WepStatus; | |
1598 | pEntry->PrivacyFilter = | |
1599 | Ndis802_11PrivFilterAcceptAll; | |
ca97b838 | 1600 | #ifdef RTMP_MAC_PCI |
96b3c83d BZ |
1601 | AsicRemovePairwiseKeyEntry(pAd, |
1602 | pEntry-> | |
1603 | apidx, | |
1604 | (UCHAR) i); | |
ec278fa2 | 1605 | #endif /* RTMP_MAC_PCI // */ |
91980990 | 1606 | } |
91980990 GKH |
1607 | } |
1608 | ||
1609 | pEntry->GTKState = REKEY_NEGOTIATING; | |
1610 | pEntry->PairwiseKey.KeyLen = 0; | |
1611 | pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; | |
91980990 | 1612 | pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; |
6a28a69a | 1613 | |
91980990 GKH |
1614 | 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; | |
ec278fa2 | 1618 | pEntry->Aid = (USHORT) i; /*0; */ |
91980990 GKH |
1619 | pEntry->CapabilityInfo = 0; |
1620 | pEntry->PsMode = PWR_ACTIVE; | |
1621 | pEntry->PsQIdleCount = 0; | |
1622 | pEntry->NoDataIdleCount = 0; | |
ca97b838 | 1623 | pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT; |
91980990 GKH |
1624 | pEntry->ContinueTxFailCnt = 0; |
1625 | InitializeQueueHeader(&pEntry->PsQueue); | |
1626 | ||
96b3c83d | 1627 | pAd->MacTab.Size++; |
ec278fa2 | 1628 | /* Add this entry into ASIC RX WCID search table */ |
ca97b838 | 1629 | RTMP_STA_ENTRY_ADD(pAd, pEntry); |
91980990 | 1630 | |
96b3c83d BZ |
1631 | DBGPRINT(RT_DEBUG_TRACE, |
1632 | ("MacTableInsertEntry - allocate entry #%d, Total= %d\n", | |
1633 | i, pAd->MacTab.Size)); | |
91980990 GKH |
1634 | break; |
1635 | } | |
1636 | } | |
1637 | ||
ec278fa2 | 1638 | /* add this MAC entry into HASH table */ |
96b3c83d | 1639 | if (pEntry) { |
91980990 | 1640 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); |
96b3c83d | 1641 | if (pAd->MacTab.Hash[HashIdx] == NULL) { |
91980990 | 1642 | pAd->MacTab.Hash[HashIdx] = pEntry; |
96b3c83d | 1643 | } else { |
91980990 GKH |
1644 | 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 | */ | |
96b3c83d BZ |
1661 | BOOLEAN MacTableDeleteEntry(IN PRTMP_ADAPTER pAd, |
1662 | IN USHORT wcid, IN PUCHAR pAddr) | |
91980990 GKH |
1663 | { |
1664 | USHORT HashIdx; | |
1665 | MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; | |
1666 | BOOLEAN Cancelled; | |
ec278fa2 BZ |
1667 | /*USHORT offset; // unused variable */ |
1668 | /*UCHAR j; // unused variable */ | |
91980990 GKH |
1669 | |
1670 | if (wcid >= MAX_LEN_OF_MAC_TABLE) | |
1671 | return FALSE; | |
1672 | ||
1673 | NdisAcquireSpinLock(&pAd->MacTabLock); | |
1674 | ||
1675 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | |
ec278fa2 | 1676 | /*pEntry = pAd->MacTab.Hash[HashIdx]; */ |
91980990 GKH |
1677 | pEntry = &pAd->MacTab.Content[wcid]; |
1678 | ||
96b3c83d BZ |
1679 | if (pEntry |
1680 | && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS | |
1681 | || pEntry->ValidAsMesh)) { | |
1682 | if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) { | |
91980990 | 1683 | |
ec278fa2 | 1684 | /* Delete this entry from ASIC on-chip WCID Table */ |
ca97b838 | 1685 | RTMP_STA_ENTRY_MAC_RESET(pAd, wcid); |
91980990 | 1686 | |
ec278fa2 | 1687 | /* free resources of BA */ |
91980990 | 1688 | BASessionTearDownALL(pAd, pEntry->Aid); |
91980990 GKH |
1689 | |
1690 | pPrevEntry = NULL; | |
1691 | pProbeEntry = pAd->MacTab.Hash[HashIdx]; | |
1692 | ASSERT(pProbeEntry); | |
1693 | ||
ec278fa2 | 1694 | /* update Hash list */ |
96b3c83d BZ |
1695 | 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; | |
91980990 GKH |
1703 | } |
1704 | break; | |
1705 | } | |
1706 | ||
1707 | pPrevEntry = pProbeEntry; | |
1708 | pProbeEntry = pProbeEntry->pNext; | |
1709 | } while (pProbeEntry); | |
1710 | ||
ec278fa2 | 1711 | /* not found !!! */ |
91980990 GKH |
1712 | ASSERT(pProbeEntry != NULL); |
1713 | ||
ca97b838 | 1714 | RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid); |
91980990 | 1715 | |
96b3c83d BZ |
1716 | if (pEntry->EnqueueEapolStartTimerRunning != |
1717 | EAPOL_START_DISABLE) { | |
1718 | RTMPCancelTimer(&pEntry-> | |
1719 | EnqueueStartForPSKTimer, | |
1720 | &Cancelled); | |
1721 | pEntry->EnqueueEapolStartTimerRunning = | |
1722 | EAPOL_START_DISABLE; | |
1723 | } | |
91980990 | 1724 | |
96b3c83d BZ |
1725 | NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); |
1726 | 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)); | |
91980990 GKH |
1734 | } |
1735 | } | |
1736 | ||
1737 | NdisReleaseSpinLock(&pAd->MacTabLock); | |
1738 | ||
ec278fa2 | 1739 | /*Reset operating mode when no Sta. */ |
96b3c83d | 1740 | if (pAd->MacTab.Size == 0) { |
91980990 | 1741 | pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; |
ec278fa2 | 1742 | RTMP_UPDATE_PROTECT(pAd); /* edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */ |
91980990 GKH |
1743 | } |
1744 | ||
1745 | return TRUE; | |
1746 | } | |
1747 | ||
91980990 GKH |
1748 | /* |
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 | */ | |
96b3c83d | 1755 | VOID MacTableReset(IN PRTMP_ADAPTER pAd) |
91980990 | 1756 | { |
96b3c83d | 1757 | int i; |
91980990 GKH |
1758 | |
1759 | DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); | |
ec278fa2 | 1760 | /*NdisAcquireSpinLock(&pAd->MacTabLock); */ |
91980990 | 1761 | |
96b3c83d | 1762 | for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { |
ca97b838 BZ |
1763 | #ifdef RTMP_MAC_PCI |
1764 | RTMP_STA_ENTRY_MAC_RESET(pAd, i); | |
ec278fa2 | 1765 | #endif /* RTMP_MAC_PCI // */ |
96b3c83d | 1766 | if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) { |
ca97b838 | 1767 | |
ec278fa2 | 1768 | /* free resources of BA */ |
91980990 | 1769 | BASessionTearDownALL(pAd, i); |
91980990 GKH |
1770 | |
1771 | pAd->MacTab.Content[i].ValidAsCLI = FALSE; | |
1772 | ||
ca97b838 | 1773 | #ifdef RTMP_MAC_USB |
59fe2d89 | 1774 | NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6); |
ca97b838 | 1775 | RTMP_STA_ENTRY_MAC_RESET(pAd, i); |
ec278fa2 | 1776 | #endif /* RTMP_MAC_USB // */ |
91980990 | 1777 | |
ec278fa2 | 1778 | /*AsicDelWcidTab(pAd, i); */ |
91980990 GKH |
1779 | } |
1780 | } | |
1781 | ||
1782 | return; | |
1783 | } | |
1784 | ||
1785 | /* | |
1786 | ========================================================================== | |
1787 | Description: | |
1788 | ||
1789 | IRQL = DISPATCH_LEVEL | |
1790 | ||
1791 | ========================================================================== | |
1792 | */ | |
96b3c83d BZ |
1793 | VOID AssocParmFill(IN PRTMP_ADAPTER pAd, |
1794 | IN OUT MLME_ASSOC_REQ_STRUCT * AssocReq, | |
1795 | IN PUCHAR pAddr, | |
1796 | IN USHORT CapabilityInfo, | |
1797 | IN ULONG Timeout, IN USHORT ListenIntv) | |
91980990 GKH |
1798 | { |
1799 | COPY_MAC_ADDR(AssocReq->Addr, pAddr); | |
ec278fa2 BZ |
1800 | /* Add mask to support 802.11b mode only */ |
1801 | AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; /* not cf-pollable, not cf-poll-request */ | |
91980990 GKH |
1802 | AssocReq->Timeout = Timeout; |
1803 | AssocReq->ListenIntv = ListenIntv; | |
1804 | } | |
1805 | ||
91980990 GKH |
1806 | /* |
1807 | ========================================================================== | |
1808 | Description: | |
1809 | ||
1810 | IRQL = DISPATCH_LEVEL | |
1811 | ||
1812 | ========================================================================== | |
1813 | */ | |
96b3c83d BZ |
1814 | VOID DisassocParmFill(IN PRTMP_ADAPTER pAd, |
1815 | IN OUT MLME_DISASSOC_REQ_STRUCT * DisassocReq, | |
1816 | IN PUCHAR pAddr, IN USHORT Reason) | |
91980990 GKH |
1817 | { |
1818 | COPY_MAC_ADDR(DisassocReq->Addr, pAddr); | |
1819 | DisassocReq->Reason = Reason; | |
1820 | } | |
1821 | ||
91980990 GKH |
1822 | /* |
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 | ||
96b3c83d | 1856 | BOOLEAN RTMPCheckDHCPFrame(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket) |
91980990 | 1857 | { |
96b3c83d BZ |
1858 | PACKET_INFO PacketInfo; |
1859 | ULONG NumberOfBytesRead = 0; | |
1860 | ULONG CurrentOffset = 0; | |
1861 | PVOID pVirtualAddress = NULL; | |
1862 | UINT NdisBufferLength; | |
1863 | PUCHAR pSrc; | |
1864 | USHORT Protocol; | |
1865 | UCHAR ByteOffset36 = 0; | |
1866 | UCHAR ByteOffset38 = 0; | |
1867 | BOOLEAN ReadFirstParm = TRUE; | |
1868 | ||
1869 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *) & pVirtualAddress, | |
1870 | &NdisBufferLength); | |
91980990 GKH |
1871 | |
1872 | NumberOfBytesRead += NdisBufferLength; | |
1873 | pSrc = (PUCHAR) pVirtualAddress; | |
1874 | Protocol = *(pSrc + 12) * 256 + *(pSrc + 13); | |
1875 | ||
ec278fa2 BZ |
1876 | /* */ |
1877 | /* Check DHCP & BOOTP protocol */ | |
1878 | /* */ | |
96b3c83d BZ |
1879 | while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) { |
1880 | if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) { | |
1881 | CurrentOffset = | |
1882 | 35 - (NumberOfBytesRead - NdisBufferLength); | |
91980990 GKH |
1883 | ByteOffset36 = *(pSrc + CurrentOffset); |
1884 | ReadFirstParm = FALSE; | |
1885 | } | |
1886 | ||
96b3c83d BZ |
1887 | if (NumberOfBytesRead >= 37) { |
1888 | CurrentOffset = | |
1889 | 37 - (NumberOfBytesRead - NdisBufferLength); | |
91980990 | 1890 | ByteOffset38 = *(pSrc + CurrentOffset); |
ec278fa2 | 1891 | /*End of Read */ |
91980990 GKH |
1892 | break; |
1893 | } | |
1894 | return FALSE; | |
1895 | } | |
1896 | ||
ec278fa2 | 1897 | /* Check for DHCP & BOOTP protocol */ |
96b3c83d | 1898 | if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) { |
ec278fa2 BZ |
1899 | /* */ |
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 | /* */ | |
96b3c83d | 1904 | if (Protocol != 0x0806) |
91980990 | 1905 | return FALSE; |
96b3c83d | 1906 | } |
91980990 GKH |
1907 | |
1908 | return TRUE; | |
1909 | } | |
1910 | ||
96b3c83d | 1911 | BOOLEAN RTMPCheckEtherType(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket) |
91980990 | 1912 | { |
96b3c83d BZ |
1913 | USHORT TypeLen; |
1914 | UCHAR Byte0, Byte1; | |
1915 | PUCHAR pSrcBuf; | |
1916 | UINT32 pktLen; | |
1917 | UINT16 srcPort, dstPort; | |
1918 | BOOLEAN status = TRUE; | |
91980990 GKH |
1919 | |
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 | ||
ec278fa2 | 1927 | /* get Ethernet protocol field */ |
ca97b838 | 1928 | TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13]; |
91980990 | 1929 | |
ec278fa2 | 1930 | pSrcBuf += LENGTH_802_3; /* Skip the Ethernet Header. */ |
91980990 | 1931 | |
ec278fa2 | 1932 | if (TypeLen <= 1500) { /* 802.3, 802.3 LLC */ |
91980990 | 1933 | /* |
96b3c83d BZ |
1934 | 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) { | |
1941 | Sniff2BytesFromNdisBuffer((PNDIS_BUFFER) pSrcBuf, 6, | |
1942 | &Byte0, &Byte1); | |
91980990 | 1943 | RTMP_SET_PACKET_LLCSNAP(pPacket, 1); |
96b3c83d | 1944 | TypeLen = (USHORT) ((Byte0 << 8) + Byte1); |
ec278fa2 | 1945 | pSrcBuf += 8; /* Skip this LLC/SNAP header */ |
96b3c83d | 1946 | } else { |
ec278fa2 | 1947 | /*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. */ |
91980990 GKH |
1948 | } |
1949 | } | |
ec278fa2 | 1950 | /* If it's a VLAN packet, get the real Type/Length field. */ |
96b3c83d | 1951 | if (TypeLen == 0x8100) { |
91980990 GKH |
1952 | /* 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); | |
96b3c83d BZ |
1964 | Sniff2BytesFromNdisBuffer((PNDIS_BUFFER) pSrcBuf, 2, &Byte0, |
1965 | &Byte1); | |
1966 | TypeLen = (USHORT) ((Byte0 << 8) + Byte1); | |
91980990 | 1967 | |
ec278fa2 | 1968 | pSrcBuf += 4; /* Skip the VLAN Header. */ |
91980990 GKH |
1969 | } |
1970 | ||
96b3c83d BZ |
1971 | switch (TypeLen) { |
1972 | case 0x0800: | |
1973 | { | |
1974 | ASSERT((pktLen > 34)); | |
ec278fa2 BZ |
1975 | if (*(pSrcBuf + 9) == 0x11) { /* udp packet */ |
1976 | ASSERT((pktLen > 34)); /* 14 for ethernet header, 20 for IP header */ | |
96b3c83d | 1977 | |
ec278fa2 | 1978 | pSrcBuf += 20; /* Skip the IP header */ |
96b3c83d BZ |
1979 | srcPort = |
1980 | OS_NTOHS(get_unaligned | |
1981 | ((PUINT16) (pSrcBuf))); | |
1982 | dstPort = | |
1983 | OS_NTOHS(get_unaligned | |
1984 | ((PUINT16) (pSrcBuf + 2))); | |
1985 | ||
ec278fa2 | 1986 | if ((srcPort == 0x44 && dstPort == 0x43) || (srcPort == 0x43 && dstPort == 0x44)) { /*It's a BOOTP/DHCP packet */ |
96b3c83d | 1987 | RTMP_SET_PACKET_DHCP(pPacket, 1); |
91980990 GKH |
1988 | } |
1989 | } | |
96b3c83d BZ |
1990 | } |
1991 | break; | |
1992 | case 0x0806: | |
1993 | { | |
ec278fa2 | 1994 | /*ARP Packet. */ |
96b3c83d BZ |
1995 | RTMP_SET_PACKET_DHCP(pPacket, 1); |
1996 | } | |
1997 | break; | |
1998 | case 0x888e: | |
1999 | { | |
ec278fa2 | 2000 | /* EAPOL Packet. */ |
96b3c83d BZ |
2001 | RTMP_SET_PACKET_EAPOL(pPacket, 1); |
2002 | } | |
2003 | break; | |
2004 | default: | |
2005 | status = FALSE; | |
2006 | break; | |
91980990 GKH |
2007 | } |
2008 | ||
2009 | return status; | |
2010 | ||
2011 | } | |
2012 | ||
96b3c83d BZ |
2013 | VOID Update_Rssi_Sample(IN PRTMP_ADAPTER pAd, |
2014 | IN RSSI_SAMPLE * pRssi, IN PRXWI_STRUC pRxWI) | |
2015 | { | |
2016 | CHAR rssi0 = pRxWI->RSSI0; | |
2017 | CHAR rssi1 = pRxWI->RSSI1; | |
2018 | CHAR rssi2 = pRxWI->RSSI2; | |
91980990 | 2019 | |
96b3c83d BZ |
2020 | if (rssi0 != 0) { |
2021 | pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR) rssi0, RSSI_0); | |
2022 | pRssi->AvgRssi0X8 = | |
2023 | (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0; | |
2024 | pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3; | |
91980990 GKH |
2025 | } |
2026 | ||
96b3c83d BZ |
2027 | if (rssi1 != 0) { |
2028 | pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR) rssi1, RSSI_1); | |
2029 | pRssi->AvgRssi1X8 = | |
2030 | (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1; | |
2031 | pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3; | |
91980990 GKH |
2032 | } |
2033 | ||
96b3c83d BZ |
2034 | if (rssi2 != 0) { |
2035 | pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR) rssi2, RSSI_2); | |
2036 | pRssi->AvgRssi2X8 = | |
2037 | (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2; | |
91980990 GKH |
2038 | pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3; |
2039 | } | |
2040 | } | |
2041 | ||
ec278fa2 | 2042 | /* Normal legacy Rx packet indication */ |
96b3c83d BZ |
2043 | VOID Indicate_Legacy_Packet(IN PRTMP_ADAPTER pAd, |
2044 | IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID) | |
91980990 | 2045 | { |
96b3c83d BZ |
2046 | PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; |
2047 | UCHAR Header802_3[LENGTH_802_3]; | |
91980990 | 2048 | |
ec278fa2 BZ |
2049 | /* 1. get 802.3 Header */ |
2050 | /* 2. remove LLC */ | |
2051 | /* a. pointer pRxBlk->pData to payload */ | |
2052 | /* b. modify pRxBlk->DataSize */ | |
5a911fd6 | 2053 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); |
91980990 | 2054 | |
96b3c83d | 2055 | if (pRxBlk->DataSize > MAX_RX_PKT_LEN) { |
91980990 | 2056 | |
ec278fa2 | 2057 | /* release packet */ |
91980990 GKH |
2058 | RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); |
2059 | return; | |
2060 | } | |
2061 | ||
91980990 GKH |
2062 | STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); |
2063 | ||
ca97b838 | 2064 | #ifdef RTMP_MAC_USB |
96b3c83d BZ |
2065 | if (pAd->CommonCfg.bDisableReordering == 0) { |
2066 | PBA_REC_ENTRY pBAEntry; | |
2067 | ULONG Now32; | |
2068 | UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID; | |
2069 | UCHAR TID = pRxBlk->pRxWI->TID; | |
2070 | USHORT Idx; | |
59fe2d89 | 2071 | |
ec278fa2 | 2072 | #define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */ |
59fe2d89 | 2073 | |
96b3c83d | 2074 | if (Wcid < MAX_LEN_OF_MAC_TABLE) { |
59fe2d89 | 2075 | Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; |
96b3c83d | 2076 | if (Idx != 0) { |
59fe2d89 | 2077 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; |
ec278fa2 | 2078 | /* update last rx time */ |
59fe2d89 BZ |
2079 | NdisGetSystemUpTime(&Now32); |
2080 | if ((pBAEntry->list.qlen > 0) && | |
96b3c83d BZ |
2081 | 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); | |
59fe2d89 BZ |
2099 | } |
2100 | } | |
2101 | } | |
2102 | } | |
ec278fa2 | 2103 | #endif /* RTMP_MAC_USB // */ |
91980990 GKH |
2104 | |
2105 | wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); | |
2106 | ||
ec278fa2 BZ |
2107 | /* */ |
2108 | /* pass this 802.3 packet to upper layer or forward this packet to WM directly */ | |
2109 | /* */ | |
5a911fd6 | 2110 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); |
91980990 GKH |
2111 | } |
2112 | ||
ec278fa2 | 2113 | /* Normal, AMPDU or AMSDU */ |
96b3c83d BZ |
2114 | VOID CmmRxnonRalinkFrameIndicate(IN PRTMP_ADAPTER pAd, |
2115 | IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID) | |
91980990 | 2116 | { |
96b3c83d BZ |
2117 | if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) |
2118 | && (pAd->CommonCfg.bDisableReordering == 0)) { | |
91980990 | 2119 | Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); |
96b3c83d BZ |
2120 | } else { |
2121 | if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) { | |
ec278fa2 | 2122 | /* handle A-MSDU */ |
91980990 | 2123 | Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); |
96b3c83d | 2124 | } else { |
91980990 GKH |
2125 | Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); |
2126 | } | |
2127 | } | |
2128 | } | |
2129 | ||
96b3c83d BZ |
2130 | VOID CmmRxRalinkFrameIndicate(IN PRTMP_ADAPTER pAd, |
2131 | IN MAC_TABLE_ENTRY * pEntry, | |
2132 | IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID) | |
91980990 | 2133 | { |
96b3c83d BZ |
2134 | UCHAR Header802_3[LENGTH_802_3]; |
2135 | UINT16 Msdu2Size; | |
2136 | UINT16 Payload1Size, Payload2Size; | |
2137 | PUCHAR pData2; | |
2138 | PNDIS_PACKET pPacket2 = NULL; | |
91980990 | 2139 | |
96b3c83d | 2140 | Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8); |
91980990 | 2141 | |
96b3c83d | 2142 | if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) { |
91980990 GKH |
2143 | /* skip two byte MSDU2 len */ |
2144 | pRxBlk->pData += 2; | |
2145 | pRxBlk->DataSize -= 2; | |
96b3c83d | 2146 | } else { |
ec278fa2 | 2147 | /* release packet */ |
96b3c83d BZ |
2148 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, |
2149 | NDIS_STATUS_FAILURE); | |
91980990 GKH |
2150 | return; |
2151 | } | |
2152 | ||
ec278fa2 | 2153 | /* get 802.3 Header and remove LLC */ |
5a911fd6 | 2154 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); |
91980990 GKH |
2155 | |
2156 | ASSERT(pRxBlk->pRxPacket); | |
2157 | ||
ec278fa2 | 2158 | /* Ralink Aggregation frame */ |
96b3c83d | 2159 | pAd->RalinkCounters.OneSecRxAggregationCount++; |
91980990 GKH |
2160 | Payload1Size = pRxBlk->DataSize - Msdu2Size; |
2161 | Payload2Size = Msdu2Size - LENGTH_802_3; | |
2162 | ||
2163 | pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3; | |
6a28a69a | 2164 | |
96b3c83d BZ |
2165 | pPacket2 = |
2166 | duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2, | |
2167 | Payload2Size, FromWhichBSSID); | |
91980990 | 2168 | |
96b3c83d | 2169 | if (!pPacket2) { |
ec278fa2 | 2170 | /* release packet */ |
96b3c83d BZ |
2171 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, |
2172 | NDIS_STATUS_FAILURE); | |
91980990 GKH |
2173 | return; |
2174 | } | |
ec278fa2 | 2175 | /* update payload size of 1st packet */ |
91980990 GKH |
2176 | pRxBlk->DataSize = Payload1Size; |
2177 | wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); | |
2178 | ||
96b3c83d BZ |
2179 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, |
2180 | FromWhichBSSID); | |
91980990 | 2181 | |
96b3c83d | 2182 | if (pPacket2) { |
5a911fd6 | 2183 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); |
91980990 GKH |
2184 | } |
2185 | } | |
2186 | ||
91980990 GKH |
2187 | #define RESET_FRAGFRAME(_fragFrame) \ |
2188 | { \ | |
2189 | _fragFrame.RxSize = 0; \ | |
2190 | _fragFrame.Sequence = 0; \ | |
2191 | _fragFrame.LastFrag = 0; \ | |
2192 | _fragFrame.Flags = 0; \ | |
2193 | } | |
2194 | ||
96b3c83d | 2195 | PNDIS_PACKET RTMPDeFragmentDataFrame(IN PRTMP_ADAPTER pAd, IN RX_BLK * pRxBlk) |
91980990 | 2196 | { |
96b3c83d BZ |
2197 | PHEADER_802_11 pHeader = pRxBlk->pHeader; |
2198 | PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; | |
2199 | UCHAR *pData = pRxBlk->pData; | |
2200 | USHORT DataSize = pRxBlk->DataSize; | |
2201 | PNDIS_PACKET pRetPacket = NULL; | |
2202 | UCHAR *pFragBuffer = NULL; | |
2203 | BOOLEAN bReassDone = FALSE; | |
2204 | UCHAR HeaderRoom = 0; | |
91980990 GKH |
2205 | |
2206 | ASSERT(pHeader); | |
2207 | ||
96b3c83d | 2208 | HeaderRoom = pData - (UCHAR *) pHeader; |
91980990 | 2209 | |
ec278fa2 BZ |
2210 | /* Re-assemble the fragmented packets */ |
2211 | if (pHeader->Frag == 0) /* Frag. Number is 0 : First frag or only one pkt */ | |
91980990 | 2212 | { |
ec278fa2 | 2213 | /* the first pkt of fragment, record it. */ |
96b3c83d | 2214 | if (pHeader->FC.MoreFrag) { |
91980990 | 2215 | ASSERT(pAd->FragFrame.pFragPacket); |
96b3c83d BZ |
2216 | pFragBuffer = |
2217 | GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); | |
2218 | pAd->FragFrame.RxSize = DataSize + HeaderRoom; | |
2219 | NdisMoveMemory(pFragBuffer, pHeader, | |
2220 | pAd->FragFrame.RxSize); | |
91980990 | 2221 | pAd->FragFrame.Sequence = pHeader->Sequence; |
ec278fa2 | 2222 | pAd->FragFrame.LastFrag = pHeader->Frag; /* Should be 0 */ |
91980990 | 2223 | ASSERT(pAd->FragFrame.LastFrag == 0); |
ec278fa2 | 2224 | goto done; /* end of processing this frame */ |
91980990 | 2225 | } |
ec278fa2 | 2226 | } else /*Middle & End of fragment */ |
91980990 GKH |
2227 | { |
2228 | if ((pHeader->Sequence != pAd->FragFrame.Sequence) || | |
96b3c83d | 2229 | (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) { |
ec278fa2 BZ |
2230 | /* Fragment is not the same sequence or out of fragment number order */ |
2231 | /* Reset Fragment control blk */ | |
91980990 | 2232 | RESET_FRAGFRAME(pAd->FragFrame); |
96b3c83d BZ |
2233 | DBGPRINT(RT_DEBUG_ERROR, |
2234 | ("Fragment is not the same sequence or out of fragment number order.\n")); | |
ec278fa2 | 2235 | goto done; /* give up this frame */ |
96b3c83d | 2236 | } else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) { |
ec278fa2 BZ |
2237 | /* Fragment frame is too large, it exeeds the maximum frame size. */ |
2238 | /* Reset Fragment control blk */ | |
91980990 | 2239 | RESET_FRAGFRAME(pAd->FragFrame); |
96b3c83d BZ |
2240 | DBGPRINT(RT_DEBUG_ERROR, |
2241 | ("Fragment frame is too large, it exeeds the maximum frame size.\n")); | |
ec278fa2 | 2242 | goto done; /* give up this frame */ |
91980990 | 2243 | } |
ec278fa2 BZ |
2244 | /* */ |
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 | /* */ | |
96b3c83d BZ |
2248 | 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)); | |
ec278fa2 | 2252 | goto done; /* give up this frame */ |
91980990 GKH |
2253 | } |
2254 | ||
2255 | pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); | |
2256 | ||
ec278fa2 | 2257 | /* concatenate this fragment into the re-assembly buffer */ |
96b3c83d BZ |
2258 | NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, |
2259 | DataSize); | |
2260 | pAd->FragFrame.RxSize += DataSize; | |
ec278fa2 | 2261 | pAd->FragFrame.LastFrag = pHeader->Frag; /* Update fragment number */ |
91980990 | 2262 | |
ec278fa2 | 2263 | /* Last fragment */ |
96b3c83d | 2264 | if (pHeader->FC.MoreFrag == FALSE) { |
91980990 GKH |
2265 | bReassDone = TRUE; |
2266 | } | |
2267 | } | |
2268 | ||
2269 | done: | |
ec278fa2 | 2270 | /* always release rx fragmented packet */ |
91980990 GKH |
2271 | RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); |
2272 | ||
ec278fa2 BZ |
2273 | /* return defragmented packet if packet is reassembled completely */ |
2274 | /* otherwise return NULL */ | |
96b3c83d | 2275 | if (bReassDone) { |
91980990 GKH |
2276 | PNDIS_PACKET pNewFragPacket; |
2277 | ||
ec278fa2 | 2278 | /* allocate a new packet buffer for fragment */ |
96b3c83d BZ |
2279 | pNewFragPacket = |
2280 | RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); | |
2281 | if (pNewFragPacket) { | |
ec278fa2 | 2282 | /* update RxBlk */ |
91980990 GKH |
2283 | pRetPacket = pAd->FragFrame.pFragPacket; |
2284 | pAd->FragFrame.pFragPacket = pNewFragPacket; | |
96b3c83d BZ |
2285 | pRxBlk->pHeader = |
2286 | (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket); | |
2287 | pRxBlk->pData = (UCHAR *) pRxBlk->pHeader + HeaderRoom; | |
91980990 GKH |
2288 | pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom; |
2289 | pRxBlk->pRxPacket = pRetPacket; | |
96b3c83d | 2290 | } else { |
91980990 GKH |
2291 | RESET_FRAGFRAME(pAd->FragFrame); |
2292 | } | |
2293 | } | |
2294 | ||
2295 | return pRetPacket; | |
2296 | } | |
2297 | ||
96b3c83d BZ |
2298 | VOID Indicate_AMSDU_Packet(IN PRTMP_ADAPTER pAd, |
2299 | IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID) | |
91980990 | 2300 | { |
96b3c83d | 2301 | UINT nMSDU; |
91980990 GKH |
2302 | |
2303 | update_os_packet_info(pAd, pRxBlk, FromWhichBSSID); | |
2304 | RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); | |
96b3c83d BZ |
2305 | nMSDU = |
2306 | deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, | |
2307 | pRxBlk->DataSize); | |
91980990 GKH |
2308 | } |
2309 | ||
96b3c83d BZ |
2310 | VOID Indicate_EAPOL_Packet(IN PRTMP_ADAPTER pAd, |
2311 | IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID) | |
91980990 GKH |
2312 | { |
2313 | MAC_TABLE_ENTRY *pEntry = NULL; | |
2314 | ||
91980990 GKH |
2315 | { |
2316 | pEntry = &pAd->MacTab.Content[BSSID_WCID]; | |
2317 | STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); | |
2318 | return; | |
2319 | } | |
91980990 | 2320 | |
96b3c83d BZ |
2321 | if (pEntry == NULL) { |
2322 | DBGPRINT(RT_DEBUG_WARN, | |
2323 | ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); | |
ec278fa2 | 2324 | /* release packet */ |
96b3c83d BZ |
2325 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, |
2326 | NDIS_STATUS_FAILURE); | |
91980990 GKH |
2327 | return; |
2328 | } | |
2329 | } | |
2330 | ||
ec278fa2 | 2331 | #define BCN_TBTT_OFFSET 64 /*defer 64 us */ |
96b3c83d | 2332 | VOID ReSyncBeaconTime(IN PRTMP_ADAPTER pAd) |
91980990 GKH |
2333 | { |
2334 | ||
96b3c83d | 2335 | UINT32 Offset; |
91980990 GKH |
2336 | |
2337 | Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET); | |
2338 | ||
2339 | pAd->TbttTickCount++; | |
2340 | ||
ec278fa2 BZ |
2341 | /* */ |
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 | /* */ | |
96b3c83d | 2345 | if (Offset == (BCN_TBTT_OFFSET - 2)) { |
91980990 GKH |
2346 | BCN_TIME_CFG_STRUC csr; |
2347 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | |
ec278fa2 | 2348 | csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1; /* ASIC register in units of 1/16 TU = 64us */ |
91980990 | 2349 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); |
96b3c83d BZ |
2350 | } else { |
2351 | if (Offset == (BCN_TBTT_OFFSET - 1)) { | |
91980990 GKH |
2352 | BCN_TIME_CFG_STRUC csr; |
2353 | ||
2354 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | |
ec278fa2 | 2355 | csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; /* ASIC register in units of 1/16 TU */ |
91980990 GKH |
2356 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); |
2357 | } | |
2358 | } | |
2359 | } |