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 | |
51126deb BZ |
30 | u8 SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; |
31 | u8 SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; | |
91980990 | 32 | |
ec278fa2 | 33 | /* Add Cisco Aironet SNAP heade for CCX2 support */ |
51126deb BZ |
34 | u8 SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 }; |
35 | u8 CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 }; | |
36 | u8 EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e }; | |
37 | u8 EAPOL[] = { 0x88, 0x8e }; | |
38 | u8 TPID[] = { 0x81, 0x00 }; /* VLAN related */ | |
96b3c83d | 39 | |
51126deb BZ |
40 | u8 IPX[] = { 0x81, 0x37 }; |
41 | u8 APPLE_TALK[] = { 0x80, 0xf3 }; | |
96b3c83d | 42 | |
51126deb | 43 | u8 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 | 48 | |
51126deb | 49 | u8 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 | ||
51126deb | 56 | u8 OfdmRateToRxwiMCS[12] = { |
96b3c83d | 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 | 61 | |
51126deb | 62 | u8 RxwiMCSToOfdmRate[12] = { |
96b3c83d | 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 | |
51126deb | 74 | u8 default_cwmin[] = |
96b3c83d | 75 | { CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS - 1, CW_MIN_IN_BITS - 2 }; |
51126deb BZ |
76 | /*u8 default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; */ |
77 | u8 default_sta_aifsn[] = { 3, 7, 2, 2 }; | |
91980990 | 78 | |
51126deb | 79 | u8 MapUserPriorityToAccessCategory[8] = |
96b3c83d BZ |
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 | */ | |
62eb734b | 107 | int MiniportMMRequest(struct rt_rtmp_adapter *pAd, |
51126deb | 108 | u8 QueIdx, u8 *pData, u32 Length) |
91980990 | 109 | { |
8a10a546 | 110 | void *pPacket; |
51126deb BZ |
111 | int Status = NDIS_STATUS_SUCCESS; |
112 | unsigned long FreeNum; | |
113 | u8 rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; /*RTMP_HW_HDR_LEN]; */ | |
ca97b838 | 114 | #ifdef RTMP_MAC_PCI |
96b3c83d | 115 | unsigned long IrqFlags = 0; |
51126deb | 116 | u8 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, | |
51126deb | 167 | (u8 *)& rtmpHwHdr, |
96b3c83d BZ |
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 | */ | |
62eb734b | 245 | int MlmeHardTransmit(struct rt_rtmp_adapter *pAd, |
8a10a546 | 246 | u8 QueIdx, void *pPacket) |
91980990 | 247 | { |
62eb734b | 248 | struct rt_packet_info PacketInfo; |
51126deb BZ |
249 | u8 *pSrcBufVA; |
250 | u32 SrcBufLen; | |
62eb734b | 251 | struct rt_header_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 | |
62eb734b | 262 | pHeader_802_11 = (struct rt_header_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 | |
62eb734b | 273 | int MlmeHardTransmitMgmtRing(struct rt_rtmp_adapter *pAd, |
8a10a546 | 274 | u8 QueIdx, void *pPacket) |
91980990 | 275 | { |
62eb734b | 276 | struct rt_packet_info PacketInfo; |
51126deb BZ |
277 | u8 *pSrcBufVA; |
278 | u32 SrcBufLen; | |
62eb734b | 279 | struct rt_header_802_11 * pHeader_802_11; |
96b3c83d | 280 | BOOLEAN bAckRequired, bInsertTimestamp; |
51126deb | 281 | u8 MlmeRate; |
62eb734b BZ |
282 | struct rt_txwi * pFirstTxWI; |
283 | struct rt_mac_table_entry *pMacEntry = NULL; | |
51126deb | 284 | u8 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 | |
62eb734b BZ |
302 | pFirstTxWI = (struct rt_txwi *) (pSrcBufVA + TXINFO_SIZE); |
303 | pHeader_802_11 = (struct rt_header_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 */ | |
25985edc | 340 | /* Data-Null packets also pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */ |
ec278fa2 | 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, | |
06aea994 | 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, | |
51126deb | 424 | (u8)pAd->CommonCfg.MlmeTransmit.field.MCS, |
96b3c83d BZ |
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, | |
51126deb | 433 | (u8)pMacEntry->MaxHTPhyMode.field.MCS, |
96b3c83d | 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 | */ | |
62eb734b | 509 | static u8 TxPktClassification(struct rt_rtmp_adapter *pAd, void *pPacket) |
91980990 | 510 | { |
51126deb BZ |
511 | u8 TxFrameType = TX_UNKOWN_FRAME; |
512 | u8 Wcid; | |
62eb734b | 513 | struct rt_mac_table_entry *pMacEntry = NULL; |
96b3c83d | 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 | ||
62eb734b | 557 | BOOLEAN RTMP_FillTxBlkInfo(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk) |
91980990 | 558 | { |
62eb734b | 559 | struct rt_packet_info PacketInfo; |
8a10a546 | 560 | void *pPacket; |
62eb734b | 561 | struct rt_mac_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 | ||
62eb734b BZ |
665 | BOOLEAN CanDoAggregateTransmit(struct rt_rtmp_adapter *pAd, |
666 | char * pPacket, struct rt_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 | */ | |
62eb734b | 715 | void RTMPDeQueuePacket(struct rt_rtmp_adapter *pAd, IN BOOLEAN bIntContext, u8 QIdx, /* BulkOutPipeId */ |
51126deb | 716 | u8 Max_Tx_Packets) |
91980990 | 717 | { |
62eb734b | 718 | struct rt_queue_entry *pEntry = NULL; |
8a10a546 | 719 | void *pPacket; |
51126deb BZ |
720 | int Status = NDIS_STATUS_SUCCESS; |
721 | u8 Count = 0; | |
62eb734b | 722 | struct rt_queue_header *pQueue; |
51126deb BZ |
723 | unsigned long FreeNumber[NUM_OF_TX_RING]; |
724 | u8 QueIdx, sQIdx, eQIdx; | |
96b3c83d BZ |
725 | unsigned long IrqFlags = 0; |
726 | BOOLEAN hasTxDesc = FALSE; | |
62eb734b BZ |
727 | struct rt_tx_blk TxBlk; |
728 | struct rt_tx_blk *pTxBlk; | |
96b3c83d BZ |
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]; |
6aed5295 JP |
776 | pEntry = pQueue->Head; |
777 | if (pEntry == NULL) { | |
96b3c83d BZ |
778 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, |
779 | IrqFlags); | |
91980990 GKH |
780 | break; |
781 | } | |
782 | ||
783 | pTxBlk = &TxBlk; | |
62eb734b | 784 | NdisZeroMemory((u8 *)pTxBlk, sizeof(struct rt_tx_blk)); |
ec278fa2 | 785 | /*InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it. */ |
91980990 GKH |
786 | pTxBlk->QueIdx = QueIdx; |
787 | ||
ca97b838 BZ |
788 | pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); |
789 | ||
ec278fa2 | 790 | /* Early check to make sure we have enoguh Tx Resource. */ |
96b3c83d BZ |
791 | hasTxDesc = |
792 | RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, | |
793 | FreeNumber[QueIdx], | |
794 | pPacket); | |
795 | if (!hasTxDesc) { | |
91980990 GKH |
796 | pAd->PrivateInfo.TxRingFullCnt++; |
797 | ||
96b3c83d BZ |
798 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, |
799 | IrqFlags); | |
91980990 GKH |
800 | |
801 | break; | |
802 | } | |
803 | ||
804 | pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket); | |
805 | pEntry = RemoveHeadQueue(pQueue); | |
806 | pTxBlk->TotalFrameNum++; | |
ec278fa2 | 807 | pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */ |
91980990 GKH |
808 | pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); |
809 | pTxBlk->pPacket = pPacket; | |
96b3c83d BZ |
810 | InsertTailQueue(&pTxBlk->TxPacketList, |
811 | PACKET_TO_QUEUE_ENTRY(pPacket)); | |
91980990 | 812 | |
96b3c83d BZ |
813 | if (pTxBlk->TxFrameType == TX_RALINK_FRAME |
814 | || pTxBlk->TxFrameType == TX_AMSDU_FRAME) { | |
ec278fa2 | 815 | /* Enhance SW Aggregation Mechanism */ |
96b3c83d BZ |
816 | if (NEED_QUEUE_BACK_FOR_AGG |
817 | (pAd, QueIdx, FreeNumber[QueIdx], | |
818 | pTxBlk->TxFrameType)) { | |
819 | InsertHeadQueue(pQueue, | |
820 | PACKET_TO_QUEUE_ENTRY | |
821 | (pPacket)); | |
822 | DEQUEUE_UNLOCK(&pAd->irq_lock, | |
823 | bIntContext, IrqFlags); | |
91980990 GKH |
824 | break; |
825 | } | |
826 | ||
96b3c83d | 827 | do { |
6aed5295 JP |
828 | pEntry = pQueue->Head; |
829 | if (pEntry == NULL) | |
91980990 GKH |
830 | break; |
831 | ||
ec278fa2 | 832 | /* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. */ |
ca97b838 | 833 | pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); |
96b3c83d BZ |
834 | FreeNumber[QueIdx] = |
835 | GET_TXRING_FREENO(pAd, QueIdx); | |
836 | hasTxDesc = | |
837 | RTMP_HAS_ENOUGH_FREE_DESC(pAd, | |
838 | pTxBlk, | |
839 | FreeNumber | |
840 | [QueIdx], | |
841 | pPacket); | |
842 | if ((hasTxDesc == FALSE) | |
843 | || | |
844 | (CanDoAggregateTransmit | |
845 | (pAd, pPacket, pTxBlk) == FALSE)) | |
91980990 GKH |
846 | break; |
847 | ||
ec278fa2 | 848 | /*Remove the packet from the TxSwQueue and insert into pTxBlk */ |
91980990 GKH |
849 | pEntry = RemoveHeadQueue(pQueue); |
850 | ASSERT(pEntry); | |
ca97b838 | 851 | pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); |
91980990 | 852 | pTxBlk->TotalFrameNum++; |
ec278fa2 | 853 | pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */ |
96b3c83d BZ |
854 | pTxBlk->TotalFrameLen += |
855 | GET_OS_PKT_LEN(pPacket); | |
856 | InsertTailQueue(&pTxBlk->TxPacketList, | |
857 | PACKET_TO_QUEUE_ENTRY | |
858 | (pPacket)); | |
859 | } while (1); | |
91980990 GKH |
860 | |
861 | if (pTxBlk->TxPacketList.Number == 1) | |
862 | pTxBlk->TxFrameType = TX_LEGACY_FRAME; | |
863 | } | |
ca97b838 | 864 | #ifdef RTMP_MAC_USB |
59fe2d89 | 865 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); |
ec278fa2 | 866 | #endif /* RTMP_MAC_USB // */ |
91980990 GKH |
867 | Count += pTxBlk->TxPacketList.Number; |
868 | ||
ec278fa2 | 869 | /* Do HardTransmit now. */ |
5a911fd6 | 870 | Status = STAHardTransmit(pAd, pTxBlk, QueIdx); |
91980990 | 871 | |
ca97b838 | 872 | #ifdef RTMP_MAC_PCI |
91980990 | 873 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); |
ec278fa2 BZ |
874 | /* static rate also need NICUpdateFifoStaCounters() function. */ |
875 | /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ | |
96b3c83d | 876 | NICUpdateFifoStaCounters(pAd); |
ec278fa2 | 877 | #endif /* RTMP_MAC_PCI // */ |
ca97b838 | 878 | |
91980990 GKH |
879 | } |
880 | ||
ca97b838 | 881 | RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); |
59fe2d89 | 882 | |
ca97b838 | 883 | #ifdef RTMP_MAC_USB |
59fe2d89 BZ |
884 | if (!hasTxDesc) |
885 | RTUSBKickBulkOut(pAd); | |
ec278fa2 | 886 | #endif /* RTMP_MAC_USB // */ |
91980990 GKH |
887 | } |
888 | ||
889 | } | |
890 | ||
91980990 GKH |
891 | /* |
892 | ======================================================================== | |
893 | ||
894 | Routine Description: | |
895 | Calculates the duration which is required to transmit out frames | |
896 | with given size and specified rate. | |
897 | ||
898 | Arguments: | |
899 | pAd Pointer to our adapter | |
900 | Rate Transmit rate | |
901 | Size Frame size in units of byte | |
902 | ||
903 | Return Value: | |
904 | Duration number in units of usec | |
905 | ||
906 | IRQL = PASSIVE_LEVEL | |
907 | IRQL = DISPATCH_LEVEL | |
908 | ||
909 | Note: | |
910 | ||
911 | ======================================================================== | |
912 | */ | |
62eb734b | 913 | u16 RTMPCalcDuration(struct rt_rtmp_adapter *pAd, u8 Rate, unsigned long Size) |
91980990 | 914 | { |
51126deb | 915 | unsigned long Duration = 0; |
91980990 | 916 | |
ec278fa2 | 917 | if (Rate < RATE_FIRST_OFDM_RATE) /* CCK */ |
91980990 | 918 | { |
96b3c83d BZ |
919 | if ((Rate > RATE_1) |
920 | && OPSTATUS_TEST_FLAG(pAd, | |
921 | fOP_STATUS_SHORT_PREAMBLE_INUSED)) | |
ec278fa2 | 922 | Duration = 96; /* 72+24 preamble+plcp */ |
91980990 | 923 | else |
ec278fa2 | 924 | Duration = 192; /* 144+48 preamble+plcp */ |
91980990 | 925 | |
51126deb | 926 | Duration += (u16)((Size << 4) / RateIdTo500Kbps[Rate]); |
91980990 | 927 | if ((Size << 4) % RateIdTo500Kbps[Rate]) |
96b3c83d | 928 | Duration++; |
ec278fa2 | 929 | } else if (Rate <= RATE_LAST_OFDM_RATE) /* OFDM rates */ |
91980990 | 930 | { |
ec278fa2 | 931 | Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */ |
96b3c83d | 932 | Duration += |
51126deb | 933 | 4 * (u16)((11 + Size * 4) / RateIdTo500Kbps[Rate]); |
91980990 GKH |
934 | if ((11 + Size * 4) % RateIdTo500Kbps[Rate]) |
935 | Duration += 4; | |
ec278fa2 | 936 | } else /*mimo rate */ |
91980990 | 937 | { |
ec278fa2 | 938 | Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */ |
91980990 GKH |
939 | } |
940 | ||
51126deb | 941 | return (u16)Duration; |
91980990 GKH |
942 | } |
943 | ||
91980990 GKH |
944 | /* |
945 | ======================================================================== | |
946 | ||
947 | Routine Description: | |
948 | Calculates the duration which is required to transmit out frames | |
949 | with given size and specified rate. | |
950 | ||
951 | Arguments: | |
952 | pTxWI Pointer to head of each MPDU to HW. | |
953 | Ack Setting for Ack requirement bit | |
954 | Fragment Setting for Fragment bit | |
955 | RetryMode Setting for retry mode | |
956 | Ifs Setting for IFS gap | |
957 | Rate Setting for transmit rate | |
958 | Service Setting for service | |
959 | Length Frame length | |
960 | TxPreamble Short or Long preamble when using CCK rates | |
961 | QueIdx - 0-3, according to 802.11e/d4.4 June/2003 | |
962 | ||
963 | Return Value: | |
964 | None | |
965 | ||
966 | IRQL = PASSIVE_LEVEL | |
967 | IRQL = DISPATCH_LEVEL | |
968 | ||
06aea994 | 969 | See also : BASmartHardTransmit() ! |
91980990 GKH |
970 | |
971 | ======================================================================== | |
972 | */ | |
62eb734b | 973 | void RTMPWriteTxWI(struct rt_rtmp_adapter *pAd, struct rt_txwi * pOutTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq, /* HW new a sequence. */ |
51126deb BZ |
974 | u8 BASize, |
975 | u8 WCID, | |
976 | unsigned long Length, | |
977 | u8 PID, | |
978 | u8 TID, | |
979 | u8 TxRate, | |
980 | u8 Txopmode, | |
96b3c83d | 981 | IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit) |
91980990 | 982 | { |
62eb734b BZ |
983 | struct rt_mac_table_entry *pMac = NULL; |
984 | struct rt_txwi TxWI; | |
985 | struct rt_txwi * pTxWI; | |
91980990 GKH |
986 | |
987 | if (WCID < MAX_LEN_OF_MAC_TABLE) | |
988 | pMac = &pAd->MacTab.Content[WCID]; | |
989 | ||
ec278fa2 BZ |
990 | /* */ |
991 | /* Always use Long preamble before verifiation short preamble functionality works well. */ | |
992 | /* Todo: remove the following line if short preamble functionality works */ | |
993 | /* */ | |
91980990 GKH |
994 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); |
995 | NdisZeroMemory(&TxWI, TXWI_SIZE); | |
996 | pTxWI = &TxWI; | |
997 | ||
96b3c83d | 998 | pTxWI->FRAG = FRAG; |
91980990 GKH |
999 | |
1000 | pTxWI->CFACK = CFACK; | |
96b3c83d | 1001 | pTxWI->TS = InsTimestamp; |
91980990 GKH |
1002 | pTxWI->AMPDU = AMPDU; |
1003 | pTxWI->ACK = Ack; | |
96b3c83d | 1004 | pTxWI->txop = Txopmode; |
91980990 GKH |
1005 | |
1006 | pTxWI->NSEQ = NSeq; | |
ec278fa2 | 1007 | /* John tune the performace with Intel Client in 20 MHz performance */ |
91980990 | 1008 | BASize = pAd->CommonCfg.TxBASize; |
96b3c83d BZ |
1009 | if (pAd->MACVersion == 0x28720200) { |
1010 | if (BASize > 13) | |
1011 | BASize = 13; | |
1012 | } else { | |
1013 | if (BASize > 7) | |
1014 | BASize = 7; | |
ca97b838 | 1015 | } |
91980990 GKH |
1016 | pTxWI->BAWinSize = BASize; |
1017 | pTxWI->ShortGI = pTransmit->field.ShortGI; | |
1018 | pTxWI->STBC = pTransmit->field.STBC; | |
91980990 GKH |
1019 | |
1020 | pTxWI->WirelessCliID = WCID; | |
1021 | pTxWI->MPDUtotalByteCount = Length; | |
1022 | pTxWI->PacketId = PID; | |
1023 | ||
ec278fa2 | 1024 | /* If CCK or OFDM, BW must be 20 */ |
96b3c83d BZ |
1025 | pTxWI->BW = |
1026 | (pTransmit->field.MODE <= | |
1027 | MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | |
91980990 GKH |
1028 | |
1029 | pTxWI->MCS = pTransmit->field.MCS; | |
1030 | pTxWI->PHYMODE = pTransmit->field.MODE; | |
1031 | pTxWI->CFACK = CfAck; | |
1032 | ||
96b3c83d BZ |
1033 | if (pMac) { |
1034 | if (pAd->CommonCfg.bMIMOPSEnable) { | |
1035 | if ((pMac->MmpsMode == MMPS_DYNAMIC) | |
1036 | && (pTransmit->field.MCS > 7)) { | |
ec278fa2 | 1037 | /* Dynamic MIMO Power Save Mode */ |
91980990 | 1038 | pTxWI->MIMOps = 1; |
96b3c83d | 1039 | } else if (pMac->MmpsMode == MMPS_STATIC) { |
ec278fa2 | 1040 | /* Static MIMO Power Save Mode */ |
96b3c83d BZ |
1041 | if (pTransmit->field.MODE >= MODE_HTMIX |
1042 | && pTransmit->field.MCS > 7) { | |
91980990 GKH |
1043 | pTxWI->MCS = 7; |
1044 | pTxWI->MIMOps = 0; | |
1045 | } | |
1046 | } | |
1047 | } | |
ec278fa2 | 1048 | /*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; */ |
96b3c83d BZ |
1049 | if (pMac->bIAmBadAtheros |
1050 | && (pMac->WepStatus != Ndis802_11WEPDisabled)) { | |
91980990 | 1051 | pTxWI->MpduDensity = 7; |
96b3c83d | 1052 | } else { |
91980990 GKH |
1053 | pTxWI->MpduDensity = pMac->MpduDensity; |
1054 | } | |
1055 | } | |
91980990 GKH |
1056 | |
1057 | pTxWI->PacketId = pTxWI->MCS; | |
62eb734b | 1058 | NdisMoveMemory(pOutTxWI, &TxWI, sizeof(struct rt_txwi)); |
91980990 GKH |
1059 | } |
1060 | ||
62eb734b BZ |
1061 | void RTMPWriteTxWI_Data(struct rt_rtmp_adapter *pAd, |
1062 | struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk) | |
91980990 | 1063 | { |
96b3c83d | 1064 | HTTRANSMIT_SETTING *pTransmit; |
62eb734b | 1065 | struct rt_mac_table_entry *pMacEntry; |
51126deb | 1066 | u8 BASize; |
91980990 GKH |
1067 | |
1068 | ASSERT(pTxWI); | |
1069 | ||
1070 | pTransmit = pTxBlk->pTransmit; | |
1071 | pMacEntry = pTxBlk->pMacEntry; | |
1072 | ||
ec278fa2 BZ |
1073 | /* */ |
1074 | /* Always use Long preamble before verifiation short preamble functionality works well. */ | |
1075 | /* Todo: remove the following line if short preamble functionality works */ | |
1076 | /* */ | |
91980990 GKH |
1077 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); |
1078 | NdisZeroMemory(pTxWI, TXWI_SIZE); | |
1079 | ||
96b3c83d BZ |
1080 | pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); |
1081 | pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); | |
1082 | pTxWI->txop = pTxBlk->FrameGap; | |
91980990 | 1083 | |
96b3c83d | 1084 | pTxWI->WirelessCliID = pTxBlk->Wcid; |
91980990 | 1085 | |
96b3c83d BZ |
1086 | pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; |
1087 | pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); | |
91980990 | 1088 | |
ec278fa2 | 1089 | /* If CCK or OFDM, BW must be 20 */ |
96b3c83d BZ |
1090 | pTxWI->BW = |
1091 | (pTransmit->field.MODE <= | |
1092 | MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | |
1093 | pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); | |
91980990 | 1094 | |
ec278fa2 | 1095 | /* John tune the performace with Intel Client in 20 MHz performance */ |
91980990 | 1096 | BASize = pAd->CommonCfg.TxBASize; |
96b3c83d | 1097 | if ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) { |
51126deb | 1098 | u8 RABAOriIdx = 0; /*The RA's BA Originator table index. */ |
91980990 | 1099 | |
96b3c83d BZ |
1100 | RABAOriIdx = |
1101 | pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; | |
91980990 GKH |
1102 | BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; |
1103 | } | |
1104 | ||
1105 | pTxWI->TxBF = pTransmit->field.TxBF; | |
1106 | pTxWI->BAWinSize = BASize; | |
1107 | pTxWI->ShortGI = pTransmit->field.ShortGI; | |
1108 | pTxWI->STBC = pTransmit->field.STBC; | |
91980990 GKH |
1109 | |
1110 | pTxWI->MCS = pTransmit->field.MCS; | |
1111 | pTxWI->PHYMODE = pTransmit->field.MODE; | |
1112 | ||
96b3c83d BZ |
1113 | if (pMacEntry) { |
1114 | if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) | |
1115 | && (pTransmit->field.MCS > 7)) { | |
ec278fa2 | 1116 | /* Dynamic MIMO Power Save Mode */ |
91980990 | 1117 | pTxWI->MIMOps = 1; |
96b3c83d | 1118 | } else if (pMacEntry->MmpsMode == MMPS_STATIC) { |
ec278fa2 | 1119 | /* Static MIMO Power Save Mode */ |
96b3c83d BZ |
1120 | if (pTransmit->field.MODE >= MODE_HTMIX |
1121 | && pTransmit->field.MCS > 7) { | |
91980990 GKH |
1122 | pTxWI->MCS = 7; |
1123 | pTxWI->MIMOps = 0; | |
1124 | } | |
1125 | } | |
1126 | ||
96b3c83d BZ |
1127 | if (pMacEntry->bIAmBadAtheros |
1128 | && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) { | |
91980990 | 1129 | pTxWI->MpduDensity = 7; |
96b3c83d | 1130 | } else { |
91980990 GKH |
1131 | pTxWI->MpduDensity = pMacEntry->MpduDensity; |
1132 | } | |
1133 | } | |
91980990 | 1134 | |
ec278fa2 | 1135 | /* for rate adapation */ |
91980990 GKH |
1136 | pTxWI->PacketId = pTxWI->MCS; |
1137 | } | |
1138 | ||
62eb734b BZ |
1139 | void RTMPWriteTxWI_Cache(struct rt_rtmp_adapter *pAd, |
1140 | struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk) | |
91980990 | 1141 | { |
96b3c83d | 1142 | PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit; |
62eb734b | 1143 | struct rt_mac_table_entry *pMacEntry; |
91980990 | 1144 | |
ec278fa2 BZ |
1145 | /* */ |
1146 | /* update TXWI */ | |
1147 | /* */ | |
91980990 GKH |
1148 | pMacEntry = pTxBlk->pMacEntry; |
1149 | pTransmit = pTxBlk->pTransmit; | |
1150 | ||
ec278fa2 BZ |
1151 | /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ |
1152 | /*if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) */ | |
1153 | /*if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) */ | |
96b3c83d | 1154 | if (pMacEntry->bAutoTxRateSwitch) { |
91980990 GKH |
1155 | pTxWI->txop = IFS_HTTXOP; |
1156 | ||
ec278fa2 | 1157 | /* If CCK or OFDM, BW must be 20 */ |
96b3c83d BZ |
1158 | pTxWI->BW = |
1159 | (pTransmit->field.MODE <= | |
1160 | MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | |
91980990 GKH |
1161 | pTxWI->ShortGI = pTransmit->field.ShortGI; |
1162 | pTxWI->STBC = pTransmit->field.STBC; | |
1163 | ||
1164 | pTxWI->MCS = pTransmit->field.MCS; | |
1165 | pTxWI->PHYMODE = pTransmit->field.MODE; | |
1166 | ||
ec278fa2 | 1167 | /* set PID for TxRateSwitching */ |
91980990 GKH |
1168 | pTxWI->PacketId = pTransmit->field.MCS; |
1169 | } | |
1170 | ||
96b3c83d | 1171 | pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE : FALSE); |
91980990 GKH |
1172 | pTxWI->MIMOps = 0; |
1173 | ||
96b3c83d | 1174 | if (pAd->CommonCfg.bMIMOPSEnable) { |
ec278fa2 | 1175 | /* MIMO Power Save Mode */ |
96b3c83d BZ |
1176 | if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) |
1177 | && (pTransmit->field.MCS > 7)) { | |
ec278fa2 | 1178 | /* Dynamic MIMO Power Save Mode */ |
91980990 | 1179 | pTxWI->MIMOps = 1; |
96b3c83d | 1180 | } else if (pMacEntry->MmpsMode == MMPS_STATIC) { |
ec278fa2 | 1181 | /* Static MIMO Power Save Mode */ |
96b3c83d BZ |
1182 | if ((pTransmit->field.MODE >= MODE_HTMIX) |
1183 | && (pTransmit->field.MCS > 7)) { | |
91980990 GKH |
1184 | pTxWI->MCS = 7; |
1185 | pTxWI->MIMOps = 0; | |
1186 | } | |
1187 | } | |
1188 | } | |
91980990 | 1189 | |
91980990 GKH |
1190 | pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; |
1191 | ||
1192 | } | |
1193 | ||
ec278fa2 BZ |
1194 | /* should be called only when - */ |
1195 | /* 1. MEADIA_CONNECTED */ | |
1196 | /* 2. AGGREGATION_IN_USED */ | |
1197 | /* 3. Fragmentation not in used */ | |
1198 | /* 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible */ | |
62eb734b | 1199 | BOOLEAN TxFrameIsAggregatible(struct rt_rtmp_adapter *pAd, |
51126deb | 1200 | u8 *pPrevAddr1, u8 *p8023hdr) |
91980990 GKH |
1201 | { |
1202 | ||
ec278fa2 | 1203 | /* can't aggregate EAPOL (802.1x) frame */ |
91980990 GKH |
1204 | if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e)) |
1205 | return FALSE; | |
1206 | ||
ec278fa2 | 1207 | /* can't aggregate multicast/broadcast frame */ |
91980990 GKH |
1208 | if (p8023hdr[0] & 0x01) |
1209 | return FALSE; | |
1210 | ||
ec278fa2 | 1211 | if (INFRA_ON(pAd)) /* must be unicast to AP */ |
91980990 | 1212 | return TRUE; |
ec278fa2 | 1213 | else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) /* unicast to same STA */ |
91980990 GKH |
1214 | return TRUE; |
1215 | else | |
1216 | return FALSE; | |
1217 | } | |
1218 | ||
91980990 GKH |
1219 | /* |
1220 | ======================================================================== | |
1221 | ||
1222 | Routine Description: | |
1223 | Check the MSDU Aggregation policy | |
1224 | 1.HT aggregation is A-MSDU | |
1225 | 2.legaacy rate aggregation is software aggregation by Ralink. | |
1226 | ||
1227 | Arguments: | |
1228 | ||
1229 | Return Value: | |
1230 | ||
1231 | Note: | |
1232 | ||
1233 | ======================================================================== | |
1234 | */ | |
62eb734b BZ |
1235 | BOOLEAN PeerIsAggreOn(struct rt_rtmp_adapter *pAd, |
1236 | unsigned long TxRate, struct rt_mac_table_entry *pMacEntry) | |
91980990 | 1237 | { |
51126deb | 1238 | unsigned long AFlags = |
96b3c83d | 1239 | (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE); |
91980990 | 1240 | |
96b3c83d BZ |
1241 | if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) { |
1242 | if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) { | |
91980990 GKH |
1243 | return TRUE; |
1244 | } | |
91980990 | 1245 | #ifdef AGGREGATION_SUPPORT |
ec278fa2 | 1246 | 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 |
1247 | return TRUE; |
1248 | } | |
ec278fa2 | 1249 | #endif /* AGGREGATION_SUPPORT // */ |
91980990 GKH |
1250 | } |
1251 | ||
1252 | return FALSE; | |
1253 | ||
1254 | } | |
1255 | ||
91980990 GKH |
1256 | /* |
1257 | ======================================================================== | |
1258 | ||
1259 | Routine Description: | |
1260 | Check and fine the packet waiting in SW queue with highest priority | |
1261 | ||
1262 | Arguments: | |
1263 | pAd Pointer to our adapter | |
1264 | ||
1265 | Return Value: | |
1266 | pQueue Pointer to Waiting Queue | |
1267 | ||
1268 | IRQL = DISPATCH_LEVEL | |
1269 | ||
1270 | Note: | |
1271 | ||
1272 | ======================================================================== | |
1273 | */ | |
62eb734b | 1274 | struct rt_queue_header *RTMPCheckTxSwQueue(struct rt_rtmp_adapter *pAd, u8 *pQueIdx) |
91980990 GKH |
1275 | { |
1276 | ||
51126deb | 1277 | unsigned long Number; |
ec278fa2 BZ |
1278 | /* 2004-11-15 to be removed. test aggregation only */ |
1279 | /* if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) */ | |
1280 | /* return NULL; */ | |
91980990 GKH |
1281 | |
1282 | Number = pAd->TxSwQueue[QID_AC_BK].Number | |
96b3c83d BZ |
1283 | + pAd->TxSwQueue[QID_AC_BE].Number |
1284 | + pAd->TxSwQueue[QID_AC_VI].Number | |
1285 | + pAd->TxSwQueue[QID_AC_VO].Number; | |
91980990 | 1286 | |
96b3c83d | 1287 | if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) { |
91980990 GKH |
1288 | *pQueIdx = QID_AC_VO; |
1289 | return (&pAd->TxSwQueue[QID_AC_VO]); | |
96b3c83d | 1290 | } else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) { |
91980990 GKH |
1291 | *pQueIdx = QID_AC_VI; |
1292 | return (&pAd->TxSwQueue[QID_AC_VI]); | |
96b3c83d | 1293 | } else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) { |
91980990 GKH |
1294 | *pQueIdx = QID_AC_BE; |
1295 | return (&pAd->TxSwQueue[QID_AC_BE]); | |
96b3c83d | 1296 | } else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) { |
91980990 GKH |
1297 | *pQueIdx = QID_AC_BK; |
1298 | return (&pAd->TxSwQueue[QID_AC_BK]); | |
1299 | } | |
ec278fa2 | 1300 | /* No packet pending in Tx Sw queue */ |
91980990 GKH |
1301 | *pQueIdx = QID_AC_BK; |
1302 | ||
1303 | return (NULL); | |
1304 | } | |
1305 | ||
91980990 GKH |
1306 | /* |
1307 | ======================================================================== | |
1308 | ||
1309 | Routine Description: | |
1310 | Suspend MSDU transmission | |
1311 | ||
1312 | Arguments: | |
1313 | pAd Pointer to our adapter | |
1314 | ||
1315 | Return Value: | |
1316 | None | |
1317 | ||
1318 | Note: | |
1319 | ||
1320 | ======================================================================== | |
1321 | */ | |
62eb734b | 1322 | void RTMPSuspendMsduTransmission(struct rt_rtmp_adapter *pAd) |
91980990 | 1323 | { |
96b3c83d | 1324 | DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n")); |
91980990 | 1325 | |
ec278fa2 BZ |
1326 | /* */ |
1327 | /* Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and */ | |
1328 | /* use Lowbound as R66 value on ScanNextChannel(...) */ | |
1329 | /* */ | |
96b3c83d BZ |
1330 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, |
1331 | &pAd->BbpTuning.R66CurrentValue); | |
91980990 | 1332 | |
ec278fa2 BZ |
1333 | /* set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) */ |
1334 | /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); */ | |
91980990 GKH |
1335 | RTMPSetAGCInitValue(pAd, BW_20); |
1336 | ||
1337 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | |
ec278fa2 | 1338 | /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings */ |
91980990 GKH |
1339 | } |
1340 | ||
91980990 GKH |
1341 | /* |
1342 | ======================================================================== | |
1343 | ||
1344 | Routine Description: | |
1345 | Resume MSDU transmission | |
1346 | ||
1347 | Arguments: | |
1348 | pAd Pointer to our adapter | |
1349 | ||
1350 | Return Value: | |
1351 | None | |
1352 | ||
1353 | IRQL = DISPATCH_LEVEL | |
1354 | ||
1355 | Note: | |
1356 | ||
1357 | ======================================================================== | |
1358 | */ | |
62eb734b | 1359 | void RTMPResumeMsduTransmission(struct rt_rtmp_adapter *pAd) |
91980990 | 1360 | { |
51126deb | 1361 | /* u8 IrqState; */ |
91980990 | 1362 | |
96b3c83d | 1363 | DBGPRINT(RT_DEBUG_TRACE, ("SCAN done, resume MSDU transmission ...\n")); |
ca97b838 | 1364 | |
ec278fa2 BZ |
1365 | /* After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value */ |
1366 | /* R66 should not be 0 */ | |
96b3c83d | 1367 | if (pAd->BbpTuning.R66CurrentValue == 0) { |
59fe2d89 | 1368 | pAd->BbpTuning.R66CurrentValue = 0x38; |
8c3d9092 | 1369 | DBGPRINT_ERR("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"); |
59fe2d89 | 1370 | } |
7765e89d | 1371 | |
96b3c83d BZ |
1372 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, |
1373 | pAd->BbpTuning.R66CurrentValue); | |
91980990 GKH |
1374 | |
1375 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | |
ec278fa2 BZ |
1376 | /* sample, for IRQ LOCK to SEM LOCK */ |
1377 | /* IrqState = pAd->irq_disabled; */ | |
1378 | /* if (IrqState) */ | |
1379 | /* RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); */ | |
1380 | /* else */ | |
91980990 GKH |
1381 | RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); |
1382 | } | |
1383 | ||
62eb734b | 1384 | u32 deaggregate_AMSDU_announce(struct rt_rtmp_adapter *pAd, |
8a10a546 | 1385 | void *pPacket, |
51126deb | 1386 | u8 *pData, unsigned long DataSize) |
91980990 | 1387 | { |
51126deb BZ |
1388 | u16 PayloadSize; |
1389 | u16 SubFrameSize; | |
62eb734b | 1390 | struct rt_header_802_3 * pAMSDUsubheader; |
51126deb BZ |
1391 | u32 nMSDU; |
1392 | u8 Header802_3[14]; | |
91980990 | 1393 | |
51126deb | 1394 | u8 *pPayload, *pDA, *pSA, *pRemovedLLCSNAP; |
8a10a546 | 1395 | void *pClonePacket; |
91980990 GKH |
1396 | |
1397 | nMSDU = 0; | |
1398 | ||
96b3c83d | 1399 | while (DataSize > LENGTH_802_3) { |
91980990 GKH |
1400 | |
1401 | nMSDU++; | |
1402 | ||
ec278fa2 | 1403 | /*hex_dump("subheader", pData, 64); */ |
62eb734b | 1404 | pAMSDUsubheader = (struct rt_header_802_3 *) pData; |
ec278fa2 | 1405 | /*pData += LENGTH_802_3; */ |
96b3c83d BZ |
1406 | PayloadSize = |
1407 | pAMSDUsubheader->Octet[1] + | |
1408 | (pAMSDUsubheader->Octet[0] << 8); | |
91980990 GKH |
1409 | SubFrameSize = PayloadSize + LENGTH_802_3; |
1410 | ||
96b3c83d | 1411 | if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) { |
91980990 GKH |
1412 | break; |
1413 | } | |
ec278fa2 | 1414 | /*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize)); */ |
ca97b838 | 1415 | |
91980990 GKH |
1416 | pPayload = pData + LENGTH_802_3; |
1417 | pDA = pData; | |
1418 | pSA = pData + MAC_ADDR_LEN; | |
1419 | ||
ec278fa2 | 1420 | /* convert to 802.3 header */ |
96b3c83d BZ |
1421 | CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, |
1422 | pRemovedLLCSNAP); | |
91980990 | 1423 | |
96b3c83d | 1424 | if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) { |
ca97b838 | 1425 | /* avoid local heap overflow, use dyanamic allocation */ |
62eb734b | 1426 | struct rt_mlme_queue_elem *Elem = |
32414878 | 1427 | kmalloc(sizeof(struct rt_mlme_queue_elem), |
96b3c83d BZ |
1428 | MEM_ALLOC_FLAG); |
1429 | if (Elem != NULL) { | |
1430 | memmove(Elem->Msg + | |
1431 | (LENGTH_802_11 + LENGTH_802_1_H), | |
1432 | pPayload, PayloadSize); | |
1433 | Elem->MsgLen = | |
1434 | LENGTH_802_11 + LENGTH_802_1_H + | |
1435 | PayloadSize; | |
ec278fa2 | 1436 | /*WpaEAPOLKeyAction(pAd, Elem); */ |
96b3c83d BZ |
1437 | REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID, |
1438 | Elem->Msg, | |
1439 | Elem->MsgLen, 0, 0, 0, | |
1440 | 0); | |
1441 | kfree(Elem); | |
1442 | } | |
ca97b838 | 1443 | } |
91980990 | 1444 | |
91980990 | 1445 | { |
96b3c83d BZ |
1446 | if (pRemovedLLCSNAP) { |
1447 | pPayload -= LENGTH_802_3; | |
1448 | PayloadSize += LENGTH_802_3; | |
1449 | NdisMoveMemory(pPayload, &Header802_3[0], | |
1450 | LENGTH_802_3); | |
1451 | } | |
91980990 | 1452 | } |
91980990 GKH |
1453 | |
1454 | pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize); | |
96b3c83d BZ |
1455 | if (pClonePacket) { |
1456 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, | |
1457 | RTMP_GET_PACKET_IF | |
1458 | (pPacket)); | |
91980990 GKH |
1459 | } |
1460 | ||
ec278fa2 BZ |
1461 | /* A-MSDU has padding to multiple of 4 including subframe header. */ |
1462 | /* align SubFrameSize up to multiple of 4 */ | |
96b3c83d | 1463 | SubFrameSize = (SubFrameSize + 3) & (~0x3); |
91980990 | 1464 | |
96b3c83d | 1465 | if (SubFrameSize > 1528 || SubFrameSize < 32) { |
91980990 GKH |
1466 | break; |
1467 | } | |
1468 | ||
96b3c83d | 1469 | if (DataSize > SubFrameSize) { |
91980990 GKH |
1470 | pData += SubFrameSize; |
1471 | DataSize -= SubFrameSize; | |
96b3c83d | 1472 | } else { |
ec278fa2 | 1473 | /* end of A-MSDU */ |
91980990 GKH |
1474 | DataSize = 0; |
1475 | } | |
1476 | } | |
1477 | ||
ec278fa2 | 1478 | /* finally release original rx packet */ |
91980990 GKH |
1479 | RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); |
1480 | ||
1481 | return nMSDU; | |
1482 | } | |
1483 | ||
1f2b472c | 1484 | u32 BA_Reorder_AMSDU_Announce(struct rt_rtmp_adapter *pAd, void *pPacket) |
91980990 | 1485 | { |
51126deb BZ |
1486 | u8 *pData; |
1487 | u16 DataSize; | |
1488 | u32 nMSDU = 0; | |
91980990 | 1489 | |
51126deb BZ |
1490 | pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket); |
1491 | DataSize = (u16)GET_OS_PKT_LEN(pPacket); | |
91980990 GKH |
1492 | |
1493 | nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize); | |
1494 | ||
1495 | return nMSDU; | |
1496 | } | |
1497 | ||
91980990 GKH |
1498 | /* |
1499 | ========================================================================== | |
1500 | Description: | |
1501 | Look up the MAC address in the MAC table. Return NULL if not found. | |
1502 | Return: | |
1503 | pEntry - pointer to the MAC entry; NULL is not found | |
1504 | ========================================================================== | |
1505 | */ | |
62eb734b | 1506 | struct rt_mac_table_entry *MacTableLookup(struct rt_rtmp_adapter *pAd, u8 *pAddr) |
91980990 | 1507 | { |
51126deb | 1508 | unsigned long HashIdx; |
62eb734b | 1509 | struct rt_mac_table_entry *pEntry = NULL; |
91980990 GKH |
1510 | |
1511 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | |
1512 | pEntry = pAd->MacTab.Hash[HashIdx]; | |
1513 | ||
96b3c83d BZ |
1514 | while (pEntry |
1515 | && (pEntry->ValidAsCLI || pEntry->ValidAsWDS | |
1516 | || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) { | |
1517 | if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) { | |
91980990 | 1518 | break; |
96b3c83d | 1519 | } else |
91980990 GKH |
1520 | pEntry = pEntry->pNext; |
1521 | } | |
1522 | ||
1523 | return pEntry; | |
1524 | } | |
1525 | ||
62eb734b | 1526 | struct rt_mac_table_entry *MacTableInsertEntry(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
1527 | u8 *pAddr, |
1528 | u8 apidx, IN BOOLEAN CleanAll) | |
91980990 | 1529 | { |
51126deb | 1530 | u8 HashIdx; |
91980990 | 1531 | int i, FirstWcid; |
62eb734b | 1532 | struct rt_mac_table_entry *pEntry = NULL, *pCurrEntry; |
51126deb BZ |
1533 | /* u16 offset; */ |
1534 | /* unsigned long addr; */ | |
91980990 | 1535 | |
ec278fa2 | 1536 | /* if FULL, return */ |
91980990 GKH |
1537 | if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) |
1538 | return NULL; | |
1539 | ||
1540 | FirstWcid = 1; | |
6a28a69a | 1541 | |
91980990 GKH |
1542 | if (pAd->StaCfg.BssType == BSS_INFRA) |
1543 | FirstWcid = 2; | |
91980990 | 1544 | |
ec278fa2 | 1545 | /* allocate one MAC entry */ |
91980990 | 1546 | NdisAcquireSpinLock(&pAd->MacTabLock); |
ec278fa2 | 1547 | for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++) /* skip entry#0 so that "entry index == AID" for fast lookup */ |
91980990 | 1548 | { |
ec278fa2 | 1549 | /* pick up the first available vacancy */ |
91980990 | 1550 | if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) && |
96b3c83d BZ |
1551 | (pAd->MacTab.Content[i].ValidAsWDS == FALSE) && |
1552 | (pAd->MacTab.Content[i].ValidAsApCli == FALSE) && | |
1553 | (pAd->MacTab.Content[i].ValidAsMesh == FALSE) | |
1554 | ) { | |
91980990 | 1555 | pEntry = &pAd->MacTab.Content[i]; |
96b3c83d | 1556 | if (CleanAll == TRUE) { |
91980990 GKH |
1557 | pEntry->MaxSupportedRate = RATE_11; |
1558 | pEntry->CurrTxRate = RATE_11; | |
62eb734b | 1559 | NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry)); |
91980990 GKH |
1560 | pEntry->PairwiseKey.KeyLen = 0; |
1561 | pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; | |
1562 | } | |
91980990 | 1563 | { |
91980990 GKH |
1564 | { |
1565 | pEntry->ValidAsCLI = TRUE; | |
1566 | pEntry->ValidAsWDS = FALSE; | |
1567 | pEntry->ValidAsApCli = FALSE; | |
1568 | pEntry->ValidAsMesh = FALSE; | |
1569 | pEntry->ValidAsDls = FALSE; | |
1570 | } | |
91980990 GKH |
1571 | } |
1572 | ||
1573 | pEntry->bIAmBadAtheros = FALSE; | |
1574 | pEntry->pAd = pAd; | |
1575 | pEntry->CMTimerRunning = FALSE; | |
96b3c83d BZ |
1576 | pEntry->EnqueueEapolStartTimerRunning = |
1577 | EAPOL_START_DISABLE; | |
91980990 | 1578 | pEntry->RSNIE_Len = 0; |
96b3c83d BZ |
1579 | NdisZeroMemory(pEntry->R_Counter, |
1580 | sizeof(pEntry->R_Counter)); | |
91980990 GKH |
1581 | pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; |
1582 | ||
1583 | if (pEntry->ValidAsMesh) | |
96b3c83d BZ |
1584 | pEntry->apidx = |
1585 | (apidx - MIN_NET_DEVICE_FOR_MESH); | |
91980990 | 1586 | else if (pEntry->ValidAsApCli) |
96b3c83d BZ |
1587 | pEntry->apidx = |
1588 | (apidx - MIN_NET_DEVICE_FOR_APCLI); | |
91980990 | 1589 | else if (pEntry->ValidAsWDS) |
96b3c83d BZ |
1590 | pEntry->apidx = |
1591 | (apidx - MIN_NET_DEVICE_FOR_WDS); | |
91980990 GKH |
1592 | else |
1593 | pEntry->apidx = apidx; | |
1594 | ||
1595 | { | |
91980990 GKH |
1596 | { |
1597 | pEntry->AuthMode = pAd->StaCfg.AuthMode; | |
96b3c83d BZ |
1598 | pEntry->WepStatus = |
1599 | pAd->StaCfg.WepStatus; | |
1600 | pEntry->PrivacyFilter = | |
1601 | Ndis802_11PrivFilterAcceptAll; | |
ca97b838 | 1602 | #ifdef RTMP_MAC_PCI |
96b3c83d BZ |
1603 | AsicRemovePairwiseKeyEntry(pAd, |
1604 | pEntry-> | |
1605 | apidx, | |
51126deb | 1606 | (u8)i); |
ec278fa2 | 1607 | #endif /* RTMP_MAC_PCI // */ |
91980990 | 1608 | } |
91980990 GKH |
1609 | } |
1610 | ||
1611 | pEntry->GTKState = REKEY_NEGOTIATING; | |
1612 | pEntry->PairwiseKey.KeyLen = 0; | |
1613 | pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; | |
91980990 | 1614 | pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; |
6a28a69a | 1615 | |
91980990 GKH |
1616 | pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; |
1617 | COPY_MAC_ADDR(pEntry->Addr, pAddr); | |
1618 | pEntry->Sst = SST_NOT_AUTH; | |
1619 | pEntry->AuthState = AS_NOT_AUTH; | |
51126deb | 1620 | pEntry->Aid = (u16)i; /*0; */ |
91980990 GKH |
1621 | pEntry->CapabilityInfo = 0; |
1622 | pEntry->PsMode = PWR_ACTIVE; | |
1623 | pEntry->PsQIdleCount = 0; | |
1624 | pEntry->NoDataIdleCount = 0; | |
ca97b838 | 1625 | pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT; |
91980990 GKH |
1626 | pEntry->ContinueTxFailCnt = 0; |
1627 | InitializeQueueHeader(&pEntry->PsQueue); | |
1628 | ||
96b3c83d | 1629 | pAd->MacTab.Size++; |
ec278fa2 | 1630 | /* Add this entry into ASIC RX WCID search table */ |
ca97b838 | 1631 | RTMP_STA_ENTRY_ADD(pAd, pEntry); |
91980990 | 1632 | |
96b3c83d BZ |
1633 | DBGPRINT(RT_DEBUG_TRACE, |
1634 | ("MacTableInsertEntry - allocate entry #%d, Total= %d\n", | |
1635 | i, pAd->MacTab.Size)); | |
91980990 GKH |
1636 | break; |
1637 | } | |
1638 | } | |
1639 | ||
ec278fa2 | 1640 | /* add this MAC entry into HASH table */ |
96b3c83d | 1641 | if (pEntry) { |
91980990 | 1642 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); |
96b3c83d | 1643 | if (pAd->MacTab.Hash[HashIdx] == NULL) { |
91980990 | 1644 | pAd->MacTab.Hash[HashIdx] = pEntry; |
96b3c83d | 1645 | } else { |
91980990 GKH |
1646 | pCurrEntry = pAd->MacTab.Hash[HashIdx]; |
1647 | while (pCurrEntry->pNext != NULL) | |
1648 | pCurrEntry = pCurrEntry->pNext; | |
1649 | pCurrEntry->pNext = pEntry; | |
1650 | } | |
1651 | } | |
1652 | ||
1653 | NdisReleaseSpinLock(&pAd->MacTabLock); | |
1654 | return pEntry; | |
1655 | } | |
1656 | ||
1657 | /* | |
1658 | ========================================================================== | |
1659 | Description: | |
1660 | Delete a specified client from MAC table | |
1661 | ========================================================================== | |
1662 | */ | |
62eb734b | 1663 | BOOLEAN MacTableDeleteEntry(struct rt_rtmp_adapter *pAd, |
51126deb | 1664 | u16 wcid, u8 *pAddr) |
91980990 | 1665 | { |
51126deb | 1666 | u16 HashIdx; |
62eb734b | 1667 | struct rt_mac_table_entry *pEntry, *pPrevEntry, *pProbeEntry; |
91980990 | 1668 | BOOLEAN Cancelled; |
51126deb BZ |
1669 | /*u16 offset; // unused variable */ |
1670 | /*u8 j; // unused variable */ | |
91980990 GKH |
1671 | |
1672 | if (wcid >= MAX_LEN_OF_MAC_TABLE) | |
1673 | return FALSE; | |
1674 | ||
1675 | NdisAcquireSpinLock(&pAd->MacTabLock); | |
1676 | ||
1677 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | |
ec278fa2 | 1678 | /*pEntry = pAd->MacTab.Hash[HashIdx]; */ |
91980990 GKH |
1679 | pEntry = &pAd->MacTab.Content[wcid]; |
1680 | ||
96b3c83d BZ |
1681 | if (pEntry |
1682 | && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS | |
1683 | || pEntry->ValidAsMesh)) { | |
1684 | if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) { | |
91980990 | 1685 | |
ec278fa2 | 1686 | /* Delete this entry from ASIC on-chip WCID Table */ |
ca97b838 | 1687 | RTMP_STA_ENTRY_MAC_RESET(pAd, wcid); |
91980990 | 1688 | |
ec278fa2 | 1689 | /* free resources of BA */ |
91980990 | 1690 | BASessionTearDownALL(pAd, pEntry->Aid); |
91980990 GKH |
1691 | |
1692 | pPrevEntry = NULL; | |
1693 | pProbeEntry = pAd->MacTab.Hash[HashIdx]; | |
1694 | ASSERT(pProbeEntry); | |
1695 | ||
ec278fa2 | 1696 | /* update Hash list */ |
96b3c83d BZ |
1697 | do { |
1698 | if (pProbeEntry == pEntry) { | |
1699 | if (pPrevEntry == NULL) { | |
1700 | pAd->MacTab.Hash[HashIdx] = | |
1701 | pEntry->pNext; | |
1702 | } else { | |
1703 | pPrevEntry->pNext = | |
1704 | pEntry->pNext; | |
91980990 GKH |
1705 | } |
1706 | break; | |
1707 | } | |
1708 | ||
1709 | pPrevEntry = pProbeEntry; | |
1710 | pProbeEntry = pProbeEntry->pNext; | |
1711 | } while (pProbeEntry); | |
1712 | ||
06aea994 | 1713 | /* not found ! */ |
91980990 GKH |
1714 | ASSERT(pProbeEntry != NULL); |
1715 | ||
ca97b838 | 1716 | RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid); |
91980990 | 1717 | |
96b3c83d BZ |
1718 | if (pEntry->EnqueueEapolStartTimerRunning != |
1719 | EAPOL_START_DISABLE) { | |
1720 | RTMPCancelTimer(&pEntry-> | |
1721 | EnqueueStartForPSKTimer, | |
1722 | &Cancelled); | |
1723 | pEntry->EnqueueEapolStartTimerRunning = | |
1724 | EAPOL_START_DISABLE; | |
1725 | } | |
91980990 | 1726 | |
62eb734b | 1727 | NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry)); |
96b3c83d BZ |
1728 | pAd->MacTab.Size--; |
1729 | DBGPRINT(RT_DEBUG_TRACE, | |
1730 | ("MacTableDeleteEntry1 - Total= %d\n", | |
1731 | pAd->MacTab.Size)); | |
1732 | } else { | |
1733 | DBGPRINT(RT_DEBUG_OFF, | |
06aea994 | 1734 | ("\n%s: Impossible Wcid = %d !\n", |
96b3c83d | 1735 | __func__, wcid)); |
91980990 GKH |
1736 | } |
1737 | } | |
1738 | ||
1739 | NdisReleaseSpinLock(&pAd->MacTabLock); | |
1740 | ||
ec278fa2 | 1741 | /*Reset operating mode when no Sta. */ |
96b3c83d | 1742 | if (pAd->MacTab.Size == 0) { |
91980990 | 1743 | pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; |
ec278fa2 | 1744 | RTMP_UPDATE_PROTECT(pAd); /* edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */ |
91980990 GKH |
1745 | } |
1746 | ||
1747 | return TRUE; | |
1748 | } | |
1749 | ||
91980990 GKH |
1750 | /* |
1751 | ========================================================================== | |
1752 | Description: | |
1753 | This routine reset the entire MAC table. All packets pending in | |
1754 | the power-saving queues are freed here. | |
1755 | ========================================================================== | |
1756 | */ | |
62eb734b | 1757 | void MacTableReset(struct rt_rtmp_adapter *pAd) |
91980990 | 1758 | { |
96b3c83d | 1759 | int i; |
91980990 GKH |
1760 | |
1761 | DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); | |
ec278fa2 | 1762 | /*NdisAcquireSpinLock(&pAd->MacTabLock); */ |
91980990 | 1763 | |
96b3c83d | 1764 | for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { |
ca97b838 BZ |
1765 | #ifdef RTMP_MAC_PCI |
1766 | RTMP_STA_ENTRY_MAC_RESET(pAd, i); | |
ec278fa2 | 1767 | #endif /* RTMP_MAC_PCI // */ |
96b3c83d | 1768 | if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) { |
ca97b838 | 1769 | |
ec278fa2 | 1770 | /* free resources of BA */ |
91980990 | 1771 | BASessionTearDownALL(pAd, i); |
91980990 GKH |
1772 | |
1773 | pAd->MacTab.Content[i].ValidAsCLI = FALSE; | |
1774 | ||
ca97b838 | 1775 | #ifdef RTMP_MAC_USB |
59fe2d89 | 1776 | NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6); |
ca97b838 | 1777 | RTMP_STA_ENTRY_MAC_RESET(pAd, i); |
ec278fa2 | 1778 | #endif /* RTMP_MAC_USB // */ |
91980990 | 1779 | |
ec278fa2 | 1780 | /*AsicDelWcidTab(pAd, i); */ |
91980990 GKH |
1781 | } |
1782 | } | |
1783 | ||
1784 | return; | |
1785 | } | |
1786 | ||
1787 | /* | |
1788 | ========================================================================== | |
1789 | Description: | |
1790 | ||
1791 | IRQL = DISPATCH_LEVEL | |
1792 | ||
1793 | ========================================================================== | |
1794 | */ | |
62eb734b BZ |
1795 | void AssocParmFill(struct rt_rtmp_adapter *pAd, |
1796 | struct rt_mlme_assoc_req *AssocReq, | |
51126deb BZ |
1797 | u8 *pAddr, |
1798 | u16 CapabilityInfo, | |
1799 | unsigned long Timeout, u16 ListenIntv) | |
91980990 GKH |
1800 | { |
1801 | COPY_MAC_ADDR(AssocReq->Addr, pAddr); | |
ec278fa2 BZ |
1802 | /* Add mask to support 802.11b mode only */ |
1803 | AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; /* not cf-pollable, not cf-poll-request */ | |
91980990 GKH |
1804 | AssocReq->Timeout = Timeout; |
1805 | AssocReq->ListenIntv = ListenIntv; | |
1806 | } | |
1807 | ||
91980990 GKH |
1808 | /* |
1809 | ========================================================================== | |
1810 | Description: | |
1811 | ||
1812 | IRQL = DISPATCH_LEVEL | |
1813 | ||
1814 | ========================================================================== | |
1815 | */ | |
62eb734b BZ |
1816 | void DisassocParmFill(struct rt_rtmp_adapter *pAd, |
1817 | struct rt_mlme_disassoc_req *DisassocReq, | |
51126deb | 1818 | u8 *pAddr, u16 Reason) |
91980990 GKH |
1819 | { |
1820 | COPY_MAC_ADDR(DisassocReq->Addr, pAddr); | |
1821 | DisassocReq->Reason = Reason; | |
1822 | } | |
1823 | ||
91980990 GKH |
1824 | /* |
1825 | ======================================================================== | |
1826 | ||
1827 | Routine Description: | |
1828 | Check the out going frame, if this is an DHCP or ARP datagram | |
1829 | will be duplicate another frame at low data rate transmit. | |
1830 | ||
1831 | Arguments: | |
1832 | pAd Pointer to our adapter | |
1833 | pPacket Pointer to outgoing Ndis frame | |
1834 | ||
1835 | Return Value: | |
1836 | TRUE To be duplicate at Low data rate transmit. (1mb) | |
1837 | FALSE Do nothing. | |
1838 | ||
1839 | IRQL = DISPATCH_LEVEL | |
1840 | ||
1841 | Note: | |
1842 | ||
1843 | MAC header + IP Header + UDP Header | |
1844 | 14 Bytes 20 Bytes | |
1845 | ||
1846 | UDP Header | |
1847 | 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| | |
1848 | Source Port | |
1849 | 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31| | |
1850 | Destination Port | |
1851 | ||
1852 | port 0x43 means Bootstrap Protocol, server. | |
1853 | Port 0x44 means Bootstrap Protocol, client. | |
1854 | ||
1855 | ======================================================================== | |
1856 | */ | |
1857 | ||
62eb734b | 1858 | BOOLEAN RTMPCheckDHCPFrame(struct rt_rtmp_adapter *pAd, void *pPacket) |
91980990 | 1859 | { |
62eb734b | 1860 | struct rt_packet_info PacketInfo; |
51126deb BZ |
1861 | unsigned long NumberOfBytesRead = 0; |
1862 | unsigned long CurrentOffset = 0; | |
1863 | void *pVirtualAddress = NULL; | |
1864 | u32 NdisBufferLength; | |
1865 | u8 *pSrc; | |
1866 | u16 Protocol; | |
1867 | u8 ByteOffset36 = 0; | |
1868 | u8 ByteOffset38 = 0; | |
96b3c83d BZ |
1869 | BOOLEAN ReadFirstParm = TRUE; |
1870 | ||
51126deb | 1871 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, (u8 **) & pVirtualAddress, |
96b3c83d | 1872 | &NdisBufferLength); |
91980990 GKH |
1873 | |
1874 | NumberOfBytesRead += NdisBufferLength; | |
51126deb | 1875 | pSrc = (u8 *)pVirtualAddress; |
91980990 GKH |
1876 | Protocol = *(pSrc + 12) * 256 + *(pSrc + 13); |
1877 | ||
ec278fa2 BZ |
1878 | /* */ |
1879 | /* Check DHCP & BOOTP protocol */ | |
1880 | /* */ | |
96b3c83d BZ |
1881 | while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) { |
1882 | if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) { | |
1883 | CurrentOffset = | |
1884 | 35 - (NumberOfBytesRead - NdisBufferLength); | |
91980990 GKH |
1885 | ByteOffset36 = *(pSrc + CurrentOffset); |
1886 | ReadFirstParm = FALSE; | |
1887 | } | |
1888 | ||
96b3c83d BZ |
1889 | if (NumberOfBytesRead >= 37) { |
1890 | CurrentOffset = | |
1891 | 37 - (NumberOfBytesRead - NdisBufferLength); | |
91980990 | 1892 | ByteOffset38 = *(pSrc + CurrentOffset); |
ec278fa2 | 1893 | /*End of Read */ |
91980990 GKH |
1894 | break; |
1895 | } | |
1896 | return FALSE; | |
1897 | } | |
1898 | ||
ec278fa2 | 1899 | /* Check for DHCP & BOOTP protocol */ |
96b3c83d | 1900 | if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) { |
ec278fa2 BZ |
1901 | /* */ |
1902 | /* 2054 (hex 0806) for ARP datagrams */ | |
1903 | /* if this packet is not ARP datagrams, then do nothing */ | |
1904 | /* ARP datagrams will also be duplicate at 1mb broadcast frames */ | |
1905 | /* */ | |
96b3c83d | 1906 | if (Protocol != 0x0806) |
91980990 | 1907 | return FALSE; |
96b3c83d | 1908 | } |
91980990 GKH |
1909 | |
1910 | return TRUE; | |
1911 | } | |
1912 | ||
62eb734b | 1913 | BOOLEAN RTMPCheckEtherType(struct rt_rtmp_adapter *pAd, void *pPacket) |
91980990 | 1914 | { |
51126deb BZ |
1915 | u16 TypeLen; |
1916 | u8 Byte0, Byte1; | |
1917 | u8 *pSrcBuf; | |
1918 | u32 pktLen; | |
1919 | u16 srcPort, dstPort; | |
96b3c83d | 1920 | BOOLEAN status = TRUE; |
91980990 GKH |
1921 | |
1922 | pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); | |
1923 | pktLen = GET_OS_PKT_LEN(pPacket); | |
1924 | ||
1925 | ASSERT(pSrcBuf); | |
1926 | ||
1927 | RTMP_SET_PACKET_SPECIFIC(pPacket, 0); | |
1928 | ||
ec278fa2 | 1929 | /* get Ethernet protocol field */ |
ca97b838 | 1930 | TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13]; |
91980990 | 1931 | |
ec278fa2 | 1932 | pSrcBuf += LENGTH_802_3; /* Skip the Ethernet Header. */ |
91980990 | 1933 | |
ec278fa2 | 1934 | if (TypeLen <= 1500) { /* 802.3, 802.3 LLC */ |
91980990 | 1935 | /* |
25985edc | 1936 | DestMAC(6) + SrcMAC(6) + Length(2) + |
96b3c83d BZ |
1937 | DSAP(1) + SSAP(1) + Control(1) + |
1938 | if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. | |
1939 | => + SNAP (5, OriginationID(3) + etherType(2)) | |
1940 | */ | |
1941 | if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA | |
1942 | && pSrcBuf[2] == 0x03) { | |
8a10a546 | 1943 | Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 6, |
96b3c83d | 1944 | &Byte0, &Byte1); |
91980990 | 1945 | RTMP_SET_PACKET_LLCSNAP(pPacket, 1); |
51126deb | 1946 | TypeLen = (u16)((Byte0 << 8) + Byte1); |
ec278fa2 | 1947 | pSrcBuf += 8; /* Skip this LLC/SNAP header */ |
96b3c83d | 1948 | } else { |
ec278fa2 | 1949 | /*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. */ |
91980990 GKH |
1950 | } |
1951 | } | |
ec278fa2 | 1952 | /* If it's a VLAN packet, get the real Type/Length field. */ |
96b3c83d | 1953 | if (TypeLen == 0x8100) { |
91980990 GKH |
1954 | /* 0x8100 means VLAN packets */ |
1955 | ||
1956 | /* Dest. MAC Address (6-bytes) + | |
1957 | Source MAC Address (6-bytes) + | |
1958 | Length/Type = 802.1Q Tag Type (2-byte) + | |
1959 | Tag Control Information (2-bytes) + | |
1960 | Length / Type (2-bytes) + | |
1961 | data payload (0-n bytes) + | |
1962 | Pad (0-p bytes) + | |
1963 | Frame Check Sequence (4-bytes) */ | |
1964 | ||
1965 | RTMP_SET_PACKET_VLAN(pPacket, 1); | |
8a10a546 | 1966 | Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 2, &Byte0, |
96b3c83d | 1967 | &Byte1); |
51126deb | 1968 | TypeLen = (u16)((Byte0 << 8) + Byte1); |
91980990 | 1969 | |
ec278fa2 | 1970 | pSrcBuf += 4; /* Skip the VLAN Header. */ |
91980990 GKH |
1971 | } |
1972 | ||
96b3c83d BZ |
1973 | switch (TypeLen) { |
1974 | case 0x0800: | |
1975 | { | |
1976 | ASSERT((pktLen > 34)); | |
ec278fa2 BZ |
1977 | if (*(pSrcBuf + 9) == 0x11) { /* udp packet */ |
1978 | ASSERT((pktLen > 34)); /* 14 for ethernet header, 20 for IP header */ | |
96b3c83d | 1979 | |
ec278fa2 | 1980 | pSrcBuf += 20; /* Skip the IP header */ |
96b3c83d BZ |
1981 | srcPort = |
1982 | OS_NTOHS(get_unaligned | |
51126deb | 1983 | ((u16 *)(pSrcBuf))); |
96b3c83d BZ |
1984 | dstPort = |
1985 | OS_NTOHS(get_unaligned | |
51126deb | 1986 | ((u16 *)(pSrcBuf + 2))); |
96b3c83d | 1987 | |
ec278fa2 | 1988 | if ((srcPort == 0x44 && dstPort == 0x43) || (srcPort == 0x43 && dstPort == 0x44)) { /*It's a BOOTP/DHCP packet */ |
96b3c83d | 1989 | RTMP_SET_PACKET_DHCP(pPacket, 1); |
91980990 GKH |
1990 | } |
1991 | } | |
96b3c83d BZ |
1992 | } |
1993 | break; | |
1994 | case 0x0806: | |
1995 | { | |
ec278fa2 | 1996 | /*ARP Packet. */ |
96b3c83d BZ |
1997 | RTMP_SET_PACKET_DHCP(pPacket, 1); |
1998 | } | |
1999 | break; | |
2000 | case 0x888e: | |
2001 | { | |
ec278fa2 | 2002 | /* EAPOL Packet. */ |
96b3c83d BZ |
2003 | RTMP_SET_PACKET_EAPOL(pPacket, 1); |
2004 | } | |
2005 | break; | |
2006 | default: | |
2007 | status = FALSE; | |
2008 | break; | |
91980990 GKH |
2009 | } |
2010 | ||
2011 | return status; | |
2012 | ||
2013 | } | |
2014 | ||
62eb734b BZ |
2015 | void Update_Rssi_Sample(struct rt_rtmp_adapter *pAd, |
2016 | struct rt_rssi_sample *pRssi, struct rt_rxwi * pRxWI) | |
96b3c83d | 2017 | { |
51126deb BZ |
2018 | char rssi0 = pRxWI->RSSI0; |
2019 | char rssi1 = pRxWI->RSSI1; | |
2020 | char rssi2 = pRxWI->RSSI2; | |
91980990 | 2021 | |
96b3c83d | 2022 | if (rssi0 != 0) { |
51126deb | 2023 | pRssi->LastRssi0 = ConvertToRssi(pAd, (char)rssi0, RSSI_0); |
96b3c83d BZ |
2024 | pRssi->AvgRssi0X8 = |
2025 | (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0; | |
2026 | pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3; | |
91980990 GKH |
2027 | } |
2028 | ||
96b3c83d | 2029 | if (rssi1 != 0) { |
51126deb | 2030 | pRssi->LastRssi1 = ConvertToRssi(pAd, (char)rssi1, RSSI_1); |
96b3c83d BZ |
2031 | pRssi->AvgRssi1X8 = |
2032 | (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1; | |
2033 | pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3; | |
91980990 GKH |
2034 | } |
2035 | ||
96b3c83d | 2036 | if (rssi2 != 0) { |
51126deb | 2037 | pRssi->LastRssi2 = ConvertToRssi(pAd, (char)rssi2, RSSI_2); |
96b3c83d BZ |
2038 | pRssi->AvgRssi2X8 = |
2039 | (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2; | |
91980990 GKH |
2040 | pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3; |
2041 | } | |
2042 | } | |
2043 | ||
ec278fa2 | 2044 | /* Normal legacy Rx packet indication */ |
62eb734b BZ |
2045 | void Indicate_Legacy_Packet(struct rt_rtmp_adapter *pAd, |
2046 | struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) | |
91980990 | 2047 | { |
8a10a546 | 2048 | void *pRxPacket = pRxBlk->pRxPacket; |
51126deb | 2049 | u8 Header802_3[LENGTH_802_3]; |
91980990 | 2050 | |
ec278fa2 BZ |
2051 | /* 1. get 802.3 Header */ |
2052 | /* 2. remove LLC */ | |
2053 | /* a. pointer pRxBlk->pData to payload */ | |
2054 | /* b. modify pRxBlk->DataSize */ | |
5a911fd6 | 2055 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); |
91980990 | 2056 | |
96b3c83d | 2057 | if (pRxBlk->DataSize > MAX_RX_PKT_LEN) { |
91980990 | 2058 | |
ec278fa2 | 2059 | /* release packet */ |
91980990 GKH |
2060 | RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); |
2061 | return; | |
2062 | } | |
2063 | ||
91980990 GKH |
2064 | STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); |
2065 | ||
ca97b838 | 2066 | #ifdef RTMP_MAC_USB |
96b3c83d | 2067 | if (pAd->CommonCfg.bDisableReordering == 0) { |
62eb734b | 2068 | struct rt_ba_rec_entry *pBAEntry; |
51126deb BZ |
2069 | unsigned long Now32; |
2070 | u8 Wcid = pRxBlk->pRxWI->WirelessCliID; | |
2071 | u8 TID = pRxBlk->pRxWI->TID; | |
2072 | u16 Idx; | |
59fe2d89 | 2073 | |
ec278fa2 | 2074 | #define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */ |
59fe2d89 | 2075 | |
96b3c83d | 2076 | if (Wcid < MAX_LEN_OF_MAC_TABLE) { |
59fe2d89 | 2077 | Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; |
96b3c83d | 2078 | if (Idx != 0) { |
59fe2d89 | 2079 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; |
ec278fa2 | 2080 | /* update last rx time */ |
59fe2d89 BZ |
2081 | NdisGetSystemUpTime(&Now32); |
2082 | if ((pBAEntry->list.qlen > 0) && | |
96b3c83d BZ |
2083 | RTMP_TIME_AFTER((unsigned long)Now32, |
2084 | (unsigned long)(pBAEntry-> | |
2085 | LastIndSeqAtTimer | |
2086 | + | |
2087 | (REORDERING_PACKET_TIMEOUT))) | |
2088 | ) { | |
2089 | DBGPRINT(RT_DEBUG_OFF, | |
2090 | ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", | |
2091 | pRxBlk->Flags, | |
2092 | pRxBlk->pRxWI->TID, | |
2093 | pRxBlk->RxD.AMPDU)); | |
2094 | hex_dump("Dump the legacy Packet:", | |
2095 | GET_OS_PKT_DATAPTR(pRxBlk-> | |
2096 | pRxPacket), | |
2097 | 64); | |
2098 | ba_flush_reordering_timeout_mpdus(pAd, | |
2099 | pBAEntry, | |
2100 | Now32); | |
59fe2d89 BZ |
2101 | } |
2102 | } | |
2103 | } | |
2104 | } | |
ec278fa2 | 2105 | #endif /* RTMP_MAC_USB // */ |
91980990 GKH |
2106 | |
2107 | wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); | |
2108 | ||
ec278fa2 BZ |
2109 | /* */ |
2110 | /* pass this 802.3 packet to upper layer or forward this packet to WM directly */ | |
2111 | /* */ | |
5a911fd6 | 2112 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); |
91980990 GKH |
2113 | } |
2114 | ||
ec278fa2 | 2115 | /* Normal, AMPDU or AMSDU */ |
62eb734b BZ |
2116 | void CmmRxnonRalinkFrameIndicate(struct rt_rtmp_adapter *pAd, |
2117 | struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) | |
91980990 | 2118 | { |
96b3c83d BZ |
2119 | if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) |
2120 | && (pAd->CommonCfg.bDisableReordering == 0)) { | |
91980990 | 2121 | Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); |
96b3c83d BZ |
2122 | } else { |
2123 | if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) { | |
ec278fa2 | 2124 | /* handle A-MSDU */ |
91980990 | 2125 | Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); |
96b3c83d | 2126 | } else { |
91980990 GKH |
2127 | Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); |
2128 | } | |
2129 | } | |
2130 | } | |
2131 | ||
62eb734b BZ |
2132 | void CmmRxRalinkFrameIndicate(struct rt_rtmp_adapter *pAd, |
2133 | struct rt_mac_table_entry *pEntry, | |
2134 | struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) | |
91980990 | 2135 | { |
51126deb BZ |
2136 | u8 Header802_3[LENGTH_802_3]; |
2137 | u16 Msdu2Size; | |
2138 | u16 Payload1Size, Payload2Size; | |
2139 | u8 *pData2; | |
8a10a546 | 2140 | void *pPacket2 = NULL; |
91980990 | 2141 | |
96b3c83d | 2142 | Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8); |
91980990 | 2143 | |
96b3c83d | 2144 | if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) { |
91980990 GKH |
2145 | /* skip two byte MSDU2 len */ |
2146 | pRxBlk->pData += 2; | |
2147 | pRxBlk->DataSize -= 2; | |
96b3c83d | 2148 | } else { |
ec278fa2 | 2149 | /* release packet */ |
96b3c83d BZ |
2150 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, |
2151 | NDIS_STATUS_FAILURE); | |
91980990 GKH |
2152 | return; |
2153 | } | |
2154 | ||
ec278fa2 | 2155 | /* get 802.3 Header and remove LLC */ |
5a911fd6 | 2156 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); |
91980990 GKH |
2157 | |
2158 | ASSERT(pRxBlk->pRxPacket); | |
2159 | ||
ec278fa2 | 2160 | /* Ralink Aggregation frame */ |
96b3c83d | 2161 | pAd->RalinkCounters.OneSecRxAggregationCount++; |
91980990 GKH |
2162 | Payload1Size = pRxBlk->DataSize - Msdu2Size; |
2163 | Payload2Size = Msdu2Size - LENGTH_802_3; | |
2164 | ||
2165 | pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3; | |
6a28a69a | 2166 | |
96b3c83d BZ |
2167 | pPacket2 = |
2168 | duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2, | |
2169 | Payload2Size, FromWhichBSSID); | |
91980990 | 2170 | |
96b3c83d | 2171 | if (!pPacket2) { |
ec278fa2 | 2172 | /* release packet */ |
96b3c83d BZ |
2173 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, |
2174 | NDIS_STATUS_FAILURE); | |
91980990 GKH |
2175 | return; |
2176 | } | |
ec278fa2 | 2177 | /* update payload size of 1st packet */ |
91980990 GKH |
2178 | pRxBlk->DataSize = Payload1Size; |
2179 | wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); | |
2180 | ||
96b3c83d BZ |
2181 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, |
2182 | FromWhichBSSID); | |
91980990 | 2183 | |
96b3c83d | 2184 | if (pPacket2) { |
5a911fd6 | 2185 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); |
91980990 GKH |
2186 | } |
2187 | } | |
2188 | ||
91980990 GKH |
2189 | #define RESET_FRAGFRAME(_fragFrame) \ |
2190 | { \ | |
2191 | _fragFrame.RxSize = 0; \ | |
2192 | _fragFrame.Sequence = 0; \ | |
2193 | _fragFrame.LastFrag = 0; \ | |
2194 | _fragFrame.Flags = 0; \ | |
2195 | } | |
2196 | ||
62eb734b | 2197 | void *RTMPDeFragmentDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk) |
91980990 | 2198 | { |
62eb734b | 2199 | struct rt_header_802_11 * pHeader = pRxBlk->pHeader; |
8a10a546 | 2200 | void *pRxPacket = pRxBlk->pRxPacket; |
51126deb BZ |
2201 | u8 *pData = pRxBlk->pData; |
2202 | u16 DataSize = pRxBlk->DataSize; | |
8a10a546 | 2203 | void *pRetPacket = NULL; |
51126deb | 2204 | u8 *pFragBuffer = NULL; |
96b3c83d | 2205 | BOOLEAN bReassDone = FALSE; |
51126deb | 2206 | u8 HeaderRoom = 0; |
91980990 GKH |
2207 | |
2208 | ASSERT(pHeader); | |
2209 | ||
51126deb | 2210 | HeaderRoom = pData - (u8 *) pHeader; |
91980990 | 2211 | |
ec278fa2 BZ |
2212 | /* Re-assemble the fragmented packets */ |
2213 | if (pHeader->Frag == 0) /* Frag. Number is 0 : First frag or only one pkt */ | |
91980990 | 2214 | { |
ec278fa2 | 2215 | /* the first pkt of fragment, record it. */ |
96b3c83d | 2216 | if (pHeader->FC.MoreFrag) { |
91980990 | 2217 | ASSERT(pAd->FragFrame.pFragPacket); |
96b3c83d BZ |
2218 | pFragBuffer = |
2219 | GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); | |
2220 | pAd->FragFrame.RxSize = DataSize + HeaderRoom; | |
2221 | NdisMoveMemory(pFragBuffer, pHeader, | |
2222 | pAd->FragFrame.RxSize); | |
91980990 | 2223 | pAd->FragFrame.Sequence = pHeader->Sequence; |
ec278fa2 | 2224 | pAd->FragFrame.LastFrag = pHeader->Frag; /* Should be 0 */ |
91980990 | 2225 | ASSERT(pAd->FragFrame.LastFrag == 0); |
ec278fa2 | 2226 | goto done; /* end of processing this frame */ |
91980990 | 2227 | } |
ec278fa2 | 2228 | } else /*Middle & End of fragment */ |
91980990 GKH |
2229 | { |
2230 | if ((pHeader->Sequence != pAd->FragFrame.Sequence) || | |
96b3c83d | 2231 | (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) { |
ec278fa2 BZ |
2232 | /* Fragment is not the same sequence or out of fragment number order */ |
2233 | /* Reset Fragment control blk */ | |
91980990 | 2234 | RESET_FRAGFRAME(pAd->FragFrame); |
96b3c83d BZ |
2235 | DBGPRINT(RT_DEBUG_ERROR, |
2236 | ("Fragment is not the same sequence or out of fragment number order.\n")); | |
ec278fa2 | 2237 | goto done; /* give up this frame */ |
96b3c83d | 2238 | } else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) { |
ec278fa2 BZ |
2239 | /* Fragment frame is too large, it exeeds the maximum frame size. */ |
2240 | /* Reset Fragment control blk */ | |
91980990 | 2241 | RESET_FRAGFRAME(pAd->FragFrame); |
96b3c83d BZ |
2242 | DBGPRINT(RT_DEBUG_ERROR, |
2243 | ("Fragment frame is too large, it exeeds the maximum frame size.\n")); | |
ec278fa2 | 2244 | goto done; /* give up this frame */ |
91980990 | 2245 | } |
ec278fa2 BZ |
2246 | /* */ |
2247 | /* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. */ | |
2248 | /* In this case, we will dropt it. */ | |
2249 | /* */ | |
96b3c83d BZ |
2250 | if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) { |
2251 | DBGPRINT(RT_DEBUG_ERROR, | |
2252 | ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", | |
2253 | pHeader->Sequence, pHeader->Frag)); | |
ec278fa2 | 2254 | goto done; /* give up this frame */ |
91980990 GKH |
2255 | } |
2256 | ||
2257 | pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); | |
2258 | ||
ec278fa2 | 2259 | /* concatenate this fragment into the re-assembly buffer */ |
96b3c83d BZ |
2260 | NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, |
2261 | DataSize); | |
2262 | pAd->FragFrame.RxSize += DataSize; | |
ec278fa2 | 2263 | pAd->FragFrame.LastFrag = pHeader->Frag; /* Update fragment number */ |
91980990 | 2264 | |
ec278fa2 | 2265 | /* Last fragment */ |
96b3c83d | 2266 | if (pHeader->FC.MoreFrag == FALSE) { |
91980990 GKH |
2267 | bReassDone = TRUE; |
2268 | } | |
2269 | } | |
2270 | ||
2271 | done: | |
ec278fa2 | 2272 | /* always release rx fragmented packet */ |
91980990 GKH |
2273 | RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); |
2274 | ||
ec278fa2 BZ |
2275 | /* return defragmented packet if packet is reassembled completely */ |
2276 | /* otherwise return NULL */ | |
96b3c83d | 2277 | if (bReassDone) { |
8a10a546 | 2278 | void *pNewFragPacket; |
91980990 | 2279 | |
ec278fa2 | 2280 | /* allocate a new packet buffer for fragment */ |
96b3c83d BZ |
2281 | pNewFragPacket = |
2282 | RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); | |
2283 | if (pNewFragPacket) { | |
ec278fa2 | 2284 | /* update RxBlk */ |
91980990 GKH |
2285 | pRetPacket = pAd->FragFrame.pFragPacket; |
2286 | pAd->FragFrame.pFragPacket = pNewFragPacket; | |
96b3c83d | 2287 | pRxBlk->pHeader = |
62eb734b | 2288 | (struct rt_header_802_11 *) GET_OS_PKT_DATAPTR(pRetPacket); |
51126deb | 2289 | pRxBlk->pData = (u8 *) pRxBlk->pHeader + HeaderRoom; |
91980990 GKH |
2290 | pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom; |
2291 | pRxBlk->pRxPacket = pRetPacket; | |
96b3c83d | 2292 | } else { |
91980990 GKH |
2293 | RESET_FRAGFRAME(pAd->FragFrame); |
2294 | } | |
2295 | } | |
2296 | ||
2297 | return pRetPacket; | |
2298 | } | |
2299 | ||
62eb734b BZ |
2300 | void Indicate_AMSDU_Packet(struct rt_rtmp_adapter *pAd, |
2301 | struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) | |
91980990 | 2302 | { |
51126deb | 2303 | u32 nMSDU; |
91980990 GKH |
2304 | |
2305 | update_os_packet_info(pAd, pRxBlk, FromWhichBSSID); | |
2306 | RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); | |
96b3c83d BZ |
2307 | nMSDU = |
2308 | deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, | |
2309 | pRxBlk->DataSize); | |
91980990 GKH |
2310 | } |
2311 | ||
62eb734b BZ |
2312 | void Indicate_EAPOL_Packet(struct rt_rtmp_adapter *pAd, |
2313 | struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) | |
91980990 | 2314 | { |
62eb734b | 2315 | struct rt_mac_table_entry *pEntry = NULL; |
91980990 | 2316 | |
91980990 GKH |
2317 | { |
2318 | pEntry = &pAd->MacTab.Content[BSSID_WCID]; | |
2319 | STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); | |
2320 | return; | |
2321 | } | |
91980990 | 2322 | |
96b3c83d BZ |
2323 | if (pEntry == NULL) { |
2324 | DBGPRINT(RT_DEBUG_WARN, | |
2325 | ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); | |
ec278fa2 | 2326 | /* release packet */ |
96b3c83d BZ |
2327 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, |
2328 | NDIS_STATUS_FAILURE); | |
91980990 GKH |
2329 | return; |
2330 | } | |
2331 | } | |
2332 | ||
ec278fa2 | 2333 | #define BCN_TBTT_OFFSET 64 /*defer 64 us */ |
62eb734b | 2334 | void ReSyncBeaconTime(struct rt_rtmp_adapter *pAd) |
91980990 GKH |
2335 | { |
2336 | ||
51126deb | 2337 | u32 Offset; |
91980990 GKH |
2338 | |
2339 | Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET); | |
2340 | ||
2341 | pAd->TbttTickCount++; | |
2342 | ||
ec278fa2 BZ |
2343 | /* */ |
2344 | /* The updated BeaconInterval Value will affect Beacon Interval after two TBTT */ | |
2345 | /* beacasue the original BeaconInterval had been loaded into next TBTT_TIMER */ | |
2346 | /* */ | |
96b3c83d | 2347 | if (Offset == (BCN_TBTT_OFFSET - 2)) { |
91980990 GKH |
2348 | BCN_TIME_CFG_STRUC csr; |
2349 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | |
ec278fa2 | 2350 | csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1; /* ASIC register in units of 1/16 TU = 64us */ |
91980990 | 2351 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); |
96b3c83d BZ |
2352 | } else { |
2353 | if (Offset == (BCN_TBTT_OFFSET - 1)) { | |
91980990 GKH |
2354 | BCN_TIME_CFG_STRUC csr; |
2355 | ||
2356 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | |
ec278fa2 | 2357 | csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; /* ASIC register in units of 1/16 TU */ |
91980990 GKH |
2358 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); |
2359 | } | |
2360 | } | |
2361 | } |