]>
Commit | Line | Data |
---|---|---|
e642f099 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 | ||
28 | #include "../rt_config.h" | |
29 | ||
30 | #define MAX_TX_IN_TBTT (16) | |
31 | ||
32 | ||
33 | UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | |
34 | UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8}; | |
35 | // Add Cisco Aironet SNAP heade for CCX2 support | |
36 | UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00}; | |
37 | UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02}; | |
38 | UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e}; | |
39 | UCHAR EAPOL[] = {0x88, 0x8e}; | |
40 | UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */ | |
41 | ||
42 | UCHAR IPX[] = {0x81, 0x37}; | |
43 | UCHAR APPLE_TALK[] = {0x80, 0xf3}; | |
44 | UCHAR RateIdToPlcpSignal[12] = { | |
45 | 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec | |
46 | 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14 | |
47 | 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14 | |
48 | ||
49 | UCHAR OfdmSignalToRateId[16] = { | |
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 | |
54 | }; | |
55 | ||
56 | UCHAR OfdmRateToRxwiMCS[12] = { | |
57 | 0, 0, 0, 0, | |
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 | |
60 | }; | |
61 | UCHAR RxwiMCSToOfdmRate[12] = { | |
62 | RATE_6, RATE_9, RATE_12, RATE_18, | |
63 | RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 | |
64 | 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 | |
65 | }; | |
66 | ||
67 | char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"}; | |
68 | ||
69 | UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2}; | |
70 | //UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; | |
71 | UCHAR default_sta_aifsn[]={3,7,2,2}; | |
72 | ||
73 | UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO}; | |
74 | ||
75 | ||
76 | /* | |
77 | ======================================================================== | |
78 | ||
79 | Routine Description: | |
80 | API for MLME to transmit management frame to AP (BSS Mode) | |
81 | or station (IBSS Mode) | |
82 | ||
83 | Arguments: | |
84 | pAd Pointer to our adapter | |
85 | pData Pointer to the outgoing 802.11 frame | |
86 | Length Size of outgoing management frame | |
87 | ||
88 | Return Value: | |
89 | NDIS_STATUS_FAILURE | |
90 | NDIS_STATUS_PENDING | |
91 | NDIS_STATUS_SUCCESS | |
92 | ||
93 | IRQL = PASSIVE_LEVEL | |
94 | IRQL = DISPATCH_LEVEL | |
95 | ||
96 | Note: | |
97 | ||
98 | ======================================================================== | |
99 | */ | |
100 | NDIS_STATUS MiniportMMRequest( | |
101 | IN PRTMP_ADAPTER pAd, | |
102 | IN UCHAR QueIdx, | |
103 | IN PUCHAR pData, | |
104 | IN UINT Length) | |
105 | { | |
106 | PNDIS_PACKET pPacket; | |
107 | NDIS_STATUS Status = NDIS_STATUS_SUCCESS; | |
108 | ULONG FreeNum; | |
109 | UCHAR IrqState; | |
110 | UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN]; | |
111 | ||
112 | ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); | |
113 | ||
114 | QueIdx=3; | |
115 | ||
116 | // 2860C use Tx Ring | |
117 | ||
118 | IrqState = pAd->irq_disabled; | |
119 | ||
120 | do | |
121 | { | |
122 | // Reset is in progress, stop immediately | |
123 | if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || | |
124 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| | |
125 | !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) | |
126 | { | |
127 | Status = NDIS_STATUS_FAILURE; | |
128 | break; | |
129 | } | |
130 | ||
131 | // Check Free priority queue | |
132 | // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. | |
133 | ||
134 | // 2860C use Tx Ring | |
135 | if (pAd->MACVersion == 0x28600100) | |
136 | { | |
137 | FreeNum = GET_TXRING_FREENO(pAd, QueIdx); | |
138 | } | |
139 | else | |
140 | { | |
141 | FreeNum = GET_MGMTRING_FREENO(pAd); | |
142 | } | |
143 | ||
144 | if ((FreeNum > 0)) | |
145 | { | |
146 | // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 | |
147 | NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE)); | |
148 | Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length); | |
149 | if (Status != NDIS_STATUS_SUCCESS) | |
150 | { | |
151 | DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); | |
152 | break; | |
153 | } | |
154 | ||
155 | //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; | |
156 | //pAd->CommonCfg.MlmeRate = RATE_2; | |
157 | ||
158 | ||
159 | Status = MlmeHardTransmit(pAd, QueIdx, pPacket); | |
160 | if (Status != NDIS_STATUS_SUCCESS) | |
161 | RTMPFreeNdisPacket(pAd, pPacket); | |
162 | } | |
163 | else | |
164 | { | |
165 | pAd->RalinkCounters.MgmtRingFullCount++; | |
166 | DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n", | |
167 | QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); | |
168 | } | |
169 | ||
170 | } while (FALSE); | |
171 | ||
172 | ||
173 | return Status; | |
174 | } | |
175 | ||
176 | ||
177 | ||
178 | NDIS_STATUS MlmeDataHardTransmit( | |
179 | IN PRTMP_ADAPTER pAd, | |
180 | IN UCHAR QueIdx, | |
181 | IN PNDIS_PACKET pPacket); | |
182 | ||
183 | #define MAX_DATAMM_RETRY 3 | |
184 | /* | |
185 | ======================================================================== | |
186 | ||
187 | Routine Description: | |
188 | API for MLME to transmit management frame to AP (BSS Mode) | |
189 | or station (IBSS Mode) | |
190 | ||
191 | Arguments: | |
192 | pAd Pointer to our adapter | |
193 | pData Pointer to the outgoing 802.11 frame | |
194 | Length Size of outgoing management frame | |
195 | ||
196 | Return Value: | |
197 | NDIS_STATUS_FAILURE | |
198 | NDIS_STATUS_PENDING | |
199 | NDIS_STATUS_SUCCESS | |
200 | ||
201 | IRQL = PASSIVE_LEVEL | |
202 | IRQL = DISPATCH_LEVEL | |
203 | ||
204 | Note: | |
205 | ||
206 | ======================================================================== | |
207 | */ | |
208 | NDIS_STATUS MiniportDataMMRequest( | |
209 | IN PRTMP_ADAPTER pAd, | |
210 | IN UCHAR QueIdx, | |
211 | IN PUCHAR pData, | |
212 | IN UINT Length) | |
213 | { | |
214 | PNDIS_PACKET pPacket; | |
215 | NDIS_STATUS Status = NDIS_STATUS_SUCCESS; | |
216 | ULONG FreeNum; | |
217 | int retry = 0; | |
218 | UCHAR IrqState; | |
219 | UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN]; | |
220 | ||
221 | ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); | |
222 | ||
223 | // 2860C use Tx Ring | |
224 | IrqState = pAd->irq_disabled; | |
225 | ||
226 | do | |
227 | { | |
228 | // Reset is in progress, stop immediately | |
229 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || | |
230 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| | |
231 | !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) | |
232 | { | |
233 | Status = NDIS_STATUS_FAILURE; | |
234 | break; | |
235 | } | |
236 | ||
237 | // Check Free priority queue | |
238 | // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. | |
239 | ||
240 | // 2860C use Tx Ring | |
241 | ||
242 | // free Tx(QueIdx) resources | |
243 | FreeNum = GET_TXRING_FREENO(pAd, QueIdx); | |
244 | ||
245 | if ((FreeNum > 0)) | |
246 | { | |
247 | // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 | |
248 | NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE)); | |
249 | Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length); | |
250 | if (Status != NDIS_STATUS_SUCCESS) | |
251 | { | |
252 | DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); | |
253 | break; | |
254 | } | |
255 | ||
256 | //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; | |
257 | //pAd->CommonCfg.MlmeRate = RATE_2; | |
258 | ||
259 | ||
260 | Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket); | |
261 | if (Status != NDIS_STATUS_SUCCESS) | |
262 | RTMPFreeNdisPacket(pAd, pPacket); | |
263 | retry = MAX_DATAMM_RETRY; | |
264 | } | |
265 | else | |
266 | { | |
267 | retry ++; | |
268 | ||
269 | printk("retry %d\n", retry); | |
270 | pAd->RalinkCounters.MgmtRingFullCount++; | |
271 | ||
272 | if (retry >= MAX_DATAMM_RETRY) | |
273 | { | |
274 | DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n", | |
275 | QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); | |
276 | } | |
277 | } | |
278 | ||
279 | } while (retry < MAX_DATAMM_RETRY); | |
280 | ||
281 | ||
282 | return Status; | |
283 | } | |
284 | ||
285 | ||
286 | ||
287 | ||
288 | ||
289 | ||
290 | /* | |
291 | ======================================================================== | |
292 | ||
293 | Routine Description: | |
294 | Copy frame from waiting queue into relative ring buffer and set | |
295 | appropriate ASIC register to kick hardware transmit function | |
296 | ||
297 | Arguments: | |
298 | pAd Pointer to our adapter | |
299 | pBuffer Pointer to memory of outgoing frame | |
300 | Length Size of outgoing management frame | |
301 | ||
302 | Return Value: | |
303 | NDIS_STATUS_FAILURE | |
304 | NDIS_STATUS_PENDING | |
305 | NDIS_STATUS_SUCCESS | |
306 | ||
307 | IRQL = PASSIVE_LEVEL | |
308 | IRQL = DISPATCH_LEVEL | |
309 | ||
310 | Note: | |
311 | ||
312 | ======================================================================== | |
313 | */ | |
314 | NDIS_STATUS MlmeHardTransmit( | |
315 | IN PRTMP_ADAPTER pAd, | |
316 | IN UCHAR QueIdx, | |
317 | IN PNDIS_PACKET pPacket) | |
318 | { | |
319 | if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) | |
e642f099 GKH |
320 | ) |
321 | { | |
322 | return NDIS_STATUS_FAILURE; | |
323 | } | |
324 | ||
325 | return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); | |
326 | ||
327 | } | |
328 | ||
329 | NDIS_STATUS MlmeDataHardTransmit( | |
330 | IN PRTMP_ADAPTER pAd, | |
331 | IN UCHAR QueIdx, | |
332 | IN PNDIS_PACKET pPacket) | |
333 | { | |
334 | if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) | |
e642f099 GKH |
335 | ) |
336 | { | |
337 | return NDIS_STATUS_FAILURE; | |
338 | } | |
339 | ||
340 | #ifdef RT2870 | |
341 | return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); | |
342 | #endif // RT2870 // | |
343 | } | |
344 | ||
345 | ||
346 | ||
347 | ||
348 | ||
349 | NDIS_STATUS MlmeHardTransmitMgmtRing( | |
350 | IN PRTMP_ADAPTER pAd, | |
351 | IN UCHAR QueIdx, | |
352 | IN PNDIS_PACKET pPacket) | |
353 | { | |
354 | PACKET_INFO PacketInfo; | |
355 | PUCHAR pSrcBufVA; | |
356 | UINT SrcBufLen; | |
357 | PHEADER_802_11 pHeader_802_11; | |
358 | BOOLEAN bAckRequired, bInsertTimestamp; | |
359 | UCHAR MlmeRate; | |
360 | PTXWI_STRUC pFirstTxWI; | |
361 | MAC_TABLE_ENTRY *pMacEntry = NULL; | |
362 | ||
363 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); | |
364 | ||
365 | // Make sure MGMT ring resource won't be used by other threads | |
366 | // sample, for IRQ LOCK -> SEM LOCK | |
367 | // IrqState = pAd->irq_disabled; | |
368 | // if (!IrqState) | |
369 | RTMP_SEM_LOCK(&pAd->MgmtRingLock); | |
370 | ||
371 | ||
372 | if (pSrcBufVA == NULL) | |
373 | { | |
374 | // The buffer shouldn't be NULL | |
375 | // if (!IrqState) | |
376 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); | |
377 | return NDIS_STATUS_FAILURE; | |
378 | } | |
379 | ||
380 | #ifdef CONFIG_STA_SUPPORT | |
381 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
382 | { | |
383 | // outgoing frame always wakeup PHY to prevent frame lost | |
384 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) | |
385 | AsicForceWakeup(pAd, TRUE); | |
386 | } | |
387 | #endif // CONFIG_STA_SUPPORT // | |
388 | ||
389 | pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE); | |
390 | pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE); | |
391 | ||
392 | if (pHeader_802_11->Addr1[0] & 0x01) | |
393 | { | |
394 | MlmeRate = pAd->CommonCfg.BasicMlmeRate; | |
395 | } | |
396 | else | |
397 | { | |
398 | MlmeRate = pAd->CommonCfg.MlmeRate; | |
399 | } | |
400 | ||
401 | // Verify Mlme rate for a / g bands. | |
402 | if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band | |
403 | MlmeRate = RATE_6; | |
404 | ||
405 | if ((pHeader_802_11->FC.Type == BTYPE_DATA) && | |
406 | (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) | |
407 | { | |
408 | pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); | |
409 | } | |
410 | ||
411 | #ifdef CONFIG_STA_SUPPORT | |
412 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
413 | { | |
414 | // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. | |
415 | if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED | |
416 | #ifdef DOT11_N_SUPPORT | |
417 | || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED | |
418 | #endif // DOT11_N_SUPPORT // | |
419 | ) | |
420 | { | |
421 | if (pAd->LatchRfRegs.Channel > 14) | |
422 | pAd->CommonCfg.MlmeTransmit.field.MODE = 1; | |
423 | else | |
424 | pAd->CommonCfg.MlmeTransmit.field.MODE = 0; | |
425 | } | |
426 | } | |
427 | #endif // CONFIG_STA_SUPPORT // | |
428 | ||
429 | // | |
430 | // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) | |
431 | // Snice it's been set to 0 while on MgtMacHeaderInit | |
432 | // By the way this will cause frame to be send on PWR_SAVE failed. | |
433 | // | |
434 | // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE); | |
435 | // | |
436 | // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame | |
437 | #ifdef CONFIG_STA_SUPPORT | |
438 | // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD | |
439 | if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) | |
440 | { | |
441 | if ((pAd->StaCfg.Psm == PWR_SAVE) && | |
442 | (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) | |
443 | pHeader_802_11->FC.PwrMgmt = PWR_SAVE; | |
444 | else | |
445 | pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; | |
446 | } | |
447 | #endif // CONFIG_STA_SUPPORT // | |
448 | ||
449 | bInsertTimestamp = FALSE; | |
450 | if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL | |
451 | { | |
452 | #ifdef CONFIG_STA_SUPPORT | |
453 | //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. | |
454 | if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) | |
455 | { | |
456 | pHeader_802_11->FC.PwrMgmt = PWR_SAVE; | |
457 | } | |
458 | #endif // CONFIG_STA_SUPPORT // | |
459 | bAckRequired = FALSE; | |
460 | } | |
461 | else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame) | |
462 | { | |
463 | //pAd->Sequence++; | |
464 | //pHeader_802_11->Sequence = pAd->Sequence; | |
465 | ||
466 | if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST | |
467 | { | |
468 | bAckRequired = FALSE; | |
469 | pHeader_802_11->Duration = 0; | |
470 | } | |
471 | else | |
472 | { | |
473 | bAckRequired = TRUE; | |
474 | pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); | |
475 | if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) | |
476 | { | |
477 | bInsertTimestamp = TRUE; | |
478 | } | |
479 | } | |
480 | } | |
481 | ||
482 | pHeader_802_11->Sequence = pAd->Sequence++; | |
483 | if (pAd->Sequence >0xfff) | |
484 | pAd->Sequence = 0; | |
485 | ||
486 | // Before radar detection done, mgmt frame can not be sent but probe req | |
487 | // Because we need to use probe req to trigger driver to send probe req in passive scan | |
488 | if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) | |
489 | && (pAd->CommonCfg.bIEEE80211H == 1) | |
490 | && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) | |
491 | { | |
492 | DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); | |
493 | // if (!IrqState) | |
494 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); | |
495 | return (NDIS_STATUS_FAILURE); | |
496 | } | |
497 | ||
e642f099 GKH |
498 | // |
499 | // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET | |
500 | // should always has only one ohysical buffer, and the whole frame size equals | |
501 | // to the first scatter buffer size | |
502 | // | |
503 | ||
504 | // Initialize TX Descriptor | |
505 | // For inter-frame gap, the number is for this frame and next frame | |
506 | // For MLME rate, we will fix as 2Mb to match other vendor's implement | |
507 | // pAd->CommonCfg.MlmeTransmit.field.MODE = 1; | |
508 | ||
509 | // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. | |
510 | if (pMacEntry == NULL) | |
511 | { | |
512 | RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, | |
513 | 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); | |
514 | } | |
515 | else | |
516 | { | |
517 | RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, | |
518 | bInsertTimestamp, FALSE, bAckRequired, FALSE, | |
519 | 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), | |
520 | pMacEntry->MaxHTPhyMode.field.MCS, 0, | |
521 | (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, | |
522 | IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); | |
523 | } | |
524 | ||
e642f099 GKH |
525 | // Now do hardware-depened kick out. |
526 | HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen); | |
527 | ||
528 | // Make sure to release MGMT ring resource | |
529 | // if (!IrqState) | |
530 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); | |
531 | return NDIS_STATUS_SUCCESS; | |
532 | } | |
533 | ||
534 | ||
535 | /******************************************************************************** | |
536 | ||
537 | New DeQueue Procedures. | |
538 | ||
539 | ********************************************************************************/ | |
540 | ||
541 | #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \ | |
542 | do{ \ | |
543 | if (bIntContext == FALSE) \ | |
544 | RTMP_IRQ_LOCK((lock), IrqFlags); \ | |
545 | }while(0) | |
546 | ||
547 | #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \ | |
548 | do{ \ | |
549 | if (bIntContext == FALSE) \ | |
550 | RTMP_IRQ_UNLOCK((lock), IrqFlags); \ | |
551 | }while(0) | |
552 | ||
553 | ||
554 | /* | |
555 | ======================================================================== | |
556 | Tx Path design algorithm: | |
557 | Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal), | |
558 | Specific Packet Type. Following show the classification rule and policy for each kinds of packets. | |
559 | Classification Rule=> | |
560 | Multicast: (*addr1 & 0x01) == 0x01 | |
561 | Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc. | |
562 | 11N Rate : If peer support HT | |
563 | (1).AMPDU -- If TXBA is negotiated. | |
564 | (2).AMSDU -- If AMSDU is capable for both peer and ourself. | |
565 | *). AMSDU can embedded in a AMPDU, but now we didn't support it. | |
566 | (3).Normal -- Other packets which send as 11n rate. | |
567 | ||
568 | B/G Rate : If peer is b/g only. | |
569 | (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6 | |
570 | (2).Normal -- Other packets which send as b/g rate. | |
571 | Fragment: | |
572 | The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment. | |
573 | ||
574 | Classified Packet Handle Rule=> | |
575 | Multicast: | |
576 | No ACK, //pTxBlk->bAckRequired = FALSE; | |
577 | No WMM, //pTxBlk->bWMM = FALSE; | |
578 | No piggyback, //pTxBlk->bPiggyBack = FALSE; | |
579 | Force LowRate, //pTxBlk->bForceLowRate = TRUE; | |
580 | Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use | |
581 | the same policy to handle it. | |
582 | Force LowRate, //pTxBlk->bForceLowRate = TRUE; | |
583 | ||
584 | 11N Rate : | |
585 | No piggyback, //pTxBlk->bPiggyBack = FALSE; | |
586 | ||
587 | (1).AMSDU | |
588 | pTxBlk->bWMM = TRUE; | |
589 | (2).AMPDU | |
590 | pTxBlk->bWMM = TRUE; | |
591 | (3).Normal | |
592 | ||
593 | B/G Rate : | |
594 | (1).ARALINK | |
595 | ||
596 | (2).Normal | |
597 | ======================================================================== | |
598 | */ | |
599 | static UCHAR TxPktClassification( | |
600 | IN RTMP_ADAPTER *pAd, | |
601 | IN PNDIS_PACKET pPacket) | |
602 | { | |
603 | UCHAR TxFrameType = TX_UNKOWN_FRAME; | |
604 | UCHAR Wcid; | |
605 | MAC_TABLE_ENTRY *pMacEntry = NULL; | |
606 | #ifdef DOT11_N_SUPPORT | |
607 | BOOLEAN bHTRate = FALSE; | |
608 | #endif // DOT11_N_SUPPORT // | |
609 | ||
610 | Wcid = RTMP_GET_PACKET_WCID(pPacket); | |
611 | if (Wcid == MCAST_WCID) | |
612 | { // Handle for RA is Broadcast/Multicast Address. | |
613 | return TX_MCAST_FRAME; | |
614 | } | |
615 | ||
616 | // Handle for unicast packets | |
617 | pMacEntry = &pAd->MacTab.Content[Wcid]; | |
618 | if (RTMP_GET_PACKET_LOWRATE(pPacket)) | |
619 | { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame | |
620 | TxFrameType = TX_LEGACY_FRAME; | |
621 | } | |
622 | #ifdef DOT11_N_SUPPORT | |
623 | else if (IS_HT_RATE(pMacEntry)) | |
624 | { // it's a 11n capable packet | |
625 | ||
626 | // Depends on HTPhyMode to check if the peer support the HTRate transmission. | |
627 | // Currently didn't support A-MSDU embedded in A-MPDU | |
628 | bHTRate = TRUE; | |
629 | if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE)) | |
630 | TxFrameType = TX_LEGACY_FRAME; | |
631 | #ifdef UAPSD_AP_SUPPORT | |
632 | else if (RTMP_GET_PACKET_EOSP(pPacket)) | |
633 | TxFrameType = TX_LEGACY_FRAME; | |
634 | #endif // UAPSD_AP_SUPPORT // | |
635 | else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0) | |
636 | return TX_AMPDU_FRAME; | |
637 | else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)) | |
638 | return TX_AMSDU_FRAME; | |
639 | else | |
640 | TxFrameType = TX_LEGACY_FRAME; | |
641 | } | |
642 | #endif // DOT11_N_SUPPORT // | |
643 | else | |
644 | { // it's a legacy b/g packet. | |
645 | if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && | |
646 | (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && | |
647 | (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) | |
648 | { // if peer support Ralink Aggregation, we use it. | |
649 | TxFrameType = TX_RALINK_FRAME; | |
650 | } | |
651 | else | |
652 | { | |
653 | TxFrameType = TX_LEGACY_FRAME; | |
654 | } | |
655 | } | |
656 | ||
657 | // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. | |
658 | if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME)) | |
659 | TxFrameType = TX_FRAG_FRAME; | |
660 | ||
661 | return TxFrameType; | |
662 | } | |
663 | ||
664 | ||
665 | BOOLEAN RTMP_FillTxBlkInfo( | |
666 | IN RTMP_ADAPTER *pAd, | |
667 | IN TX_BLK *pTxBlk) | |
668 | { | |
669 | PACKET_INFO PacketInfo; | |
670 | PNDIS_PACKET pPacket; | |
671 | PMAC_TABLE_ENTRY pMacEntry = NULL; | |
672 | ||
673 | pPacket = pTxBlk->pPacket; | |
674 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); | |
675 | ||
676 | pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); | |
677 | pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket); | |
678 | pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); | |
679 | pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap | |
680 | ||
681 | if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket)) | |
682 | TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame); | |
683 | else | |
684 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame); | |
685 | ||
686 | // Default to clear this flag | |
687 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS); | |
688 | ||
689 | ||
690 | if (pTxBlk->Wcid == MCAST_WCID) | |
691 | { | |
692 | pTxBlk->pMacEntry = NULL; | |
693 | { | |
694 | #ifdef MCAST_RATE_SPECIFIC | |
695 | PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket); | |
696 | if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff)) | |
697 | pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode; | |
698 | else | |
699 | #endif // MCAST_RATE_SPECIFIC // | |
700 | pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; | |
701 | } | |
702 | ||
703 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode. | |
704 | //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); | |
705 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag); | |
706 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); | |
707 | if (RTMP_GET_PACKET_MOREDATA(pPacket)) | |
708 | { | |
709 | TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); | |
710 | } | |
711 | ||
712 | } | |
713 | else | |
714 | { | |
715 | pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid]; | |
716 | pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode; | |
717 | ||
718 | pMacEntry = pTxBlk->pMacEntry; | |
719 | ||
720 | ||
721 | // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. | |
722 | if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK) | |
723 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); | |
724 | else | |
725 | TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired); | |
726 | ||
727 | { | |
728 | ||
729 | #ifdef CONFIG_STA_SUPPORT | |
730 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
731 | { | |
732 | ||
733 | // If support WMM, enable it. | |
734 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && | |
735 | CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) | |
736 | TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM); | |
737 | ||
738 | // if (pAd->StaCfg.bAutoTxRateSwitch) | |
739 | // TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch); | |
740 | } | |
741 | #endif // CONFIG_STA_SUPPORT // | |
742 | } | |
743 | ||
744 | if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) | |
745 | { | |
746 | if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) || | |
747 | ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) | |
748 | { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate. | |
749 | pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; | |
750 | #ifdef DOT11_N_SUPPORT | |
751 | // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? | |
752 | if (IS_HT_STA(pTxBlk->pMacEntry) && | |
753 | (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) && | |
754 | ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))) | |
755 | { | |
756 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); | |
757 | TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS); | |
758 | } | |
759 | #endif // DOT11_N_SUPPORT // | |
760 | } | |
761 | ||
762 | #ifdef DOT11_N_SUPPORT | |
763 | if ( (IS_HT_RATE(pMacEntry) == FALSE) && | |
764 | (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) | |
765 | { // Currently piggy-back only support when peer is operate in b/g mode. | |
766 | TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack); | |
767 | } | |
768 | #endif // DOT11_N_SUPPORT // | |
769 | ||
770 | if (RTMP_GET_PACKET_MOREDATA(pPacket)) | |
771 | { | |
772 | TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); | |
773 | } | |
774 | #ifdef UAPSD_AP_SUPPORT | |
775 | if (RTMP_GET_PACKET_EOSP(pPacket)) | |
776 | { | |
777 | TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP); | |
778 | } | |
779 | #endif // UAPSD_AP_SUPPORT // | |
780 | } | |
781 | else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) | |
782 | { | |
783 | TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag); | |
784 | } | |
785 | ||
786 | pMacEntry->DebugTxCount++; | |
787 | } | |
788 | ||
789 | return TRUE; | |
790 | ||
791 | FillTxBlkErr: | |
792 | return FALSE; | |
793 | } | |
794 | ||
795 | ||
796 | BOOLEAN CanDoAggregateTransmit( | |
797 | IN RTMP_ADAPTER *pAd, | |
798 | IN NDIS_PACKET *pPacket, | |
799 | IN TX_BLK *pTxBlk) | |
800 | { | |
801 | ||
802 | //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType); | |
803 | ||
804 | if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID) | |
805 | return FALSE; | |
806 | ||
807 | if (RTMP_GET_PACKET_DHCP(pPacket) || | |
808 | RTMP_GET_PACKET_EAPOL(pPacket) || | |
809 | RTMP_GET_PACKET_WAI(pPacket)) | |
810 | return FALSE; | |
811 | ||
812 | if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && | |
813 | ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100))) | |
814 | { // For AMSDU, allow the packets with total length < max-amsdu size | |
815 | return FALSE; | |
816 | } | |
817 | ||
818 | if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && | |
819 | (pTxBlk->TxPacketList.Number == 2)) | |
820 | { // For RALINK-Aggregation, allow two frames in one batch. | |
821 | return FALSE; | |
822 | } | |
823 | ||
824 | #ifdef CONFIG_STA_SUPPORT | |
825 | if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP | |
826 | return TRUE; | |
827 | else | |
828 | #endif // CONFIG_STA_SUPPORT // | |
829 | return FALSE; | |
830 | ||
831 | } | |
832 | ||
833 | ||
834 | /* | |
835 | ======================================================================== | |
836 | ||
837 | Routine Description: | |
838 | To do the enqueue operation and extract the first item of waiting | |
839 | list. If a number of available shared memory segments could meet | |
840 | the request of extracted item, the extracted item will be fragmented | |
841 | into shared memory segments. | |
842 | ||
843 | Arguments: | |
844 | pAd Pointer to our adapter | |
845 | pQueue Pointer to Waiting Queue | |
846 | ||
847 | Return Value: | |
848 | None | |
849 | ||
850 | IRQL = DISPATCH_LEVEL | |
851 | ||
852 | Note: | |
853 | ||
854 | ======================================================================== | |
855 | */ | |
856 | VOID RTMPDeQueuePacket( | |
857 | IN PRTMP_ADAPTER pAd, | |
858 | IN BOOLEAN bIntContext, | |
859 | IN UCHAR QIdx, /* BulkOutPipeId */ | |
860 | IN UCHAR Max_Tx_Packets) | |
861 | { | |
862 | PQUEUE_ENTRY pEntry = NULL; | |
863 | PNDIS_PACKET pPacket; | |
864 | NDIS_STATUS Status = NDIS_STATUS_SUCCESS; | |
865 | UCHAR Count=0; | |
866 | PQUEUE_HEADER pQueue; | |
867 | ULONG FreeNumber[NUM_OF_TX_RING]; | |
868 | UCHAR QueIdx, sQIdx, eQIdx; | |
869 | unsigned long IrqFlags = 0; | |
870 | BOOLEAN hasTxDesc = FALSE; | |
871 | TX_BLK TxBlk; | |
872 | TX_BLK *pTxBlk; | |
873 | ||
874 | #ifdef DBG_DIAGNOSE | |
875 | BOOLEAN firstRound; | |
876 | RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct; | |
877 | #endif | |
878 | ||
879 | ||
880 | if (QIdx == NUM_OF_TX_RING) | |
881 | { | |
882 | sQIdx = 0; | |
883 | //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) | |
884 | #ifdef CONFIG_STA_SUPPORT | |
885 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
886 | eQIdx = 3; // 4 ACs, start from 0. | |
887 | #endif // CONFIG_STA_SUPPORT // | |
888 | } | |
889 | else | |
890 | { | |
891 | sQIdx = eQIdx = QIdx; | |
892 | } | |
893 | ||
894 | for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++) | |
895 | { | |
896 | Count=0; | |
897 | ||
898 | RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags); | |
899 | ||
900 | #ifdef DBG_DIAGNOSE | |
901 | firstRound = ((QueIdx == 0) ? TRUE : FALSE); | |
902 | #endif // DBG_DIAGNOSE // | |
903 | ||
904 | while (1) | |
905 | { | |
906 | if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS | | |
907 | fRTMP_ADAPTER_RADIO_OFF | | |
908 | fRTMP_ADAPTER_RESET_IN_PROGRESS | | |
909 | fRTMP_ADAPTER_HALT_IN_PROGRESS | | |
910 | fRTMP_ADAPTER_NIC_NOT_EXIST)))) | |
911 | { | |
912 | RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); | |
913 | return; | |
914 | } | |
915 | ||
916 | if (Count >= Max_Tx_Packets) | |
917 | break; | |
918 | ||
919 | DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags); | |
920 | if (&pAd->TxSwQueue[QueIdx] == NULL) | |
921 | { | |
922 | #ifdef DBG_DIAGNOSE | |
923 | if (firstRound == TRUE) | |
924 | pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++; | |
925 | #endif // DBG_DIAGNOSE // | |
926 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | |
927 | break; | |
928 | } | |
929 | ||
930 | ||
931 | // probe the Queue Head | |
932 | pQueue = &pAd->TxSwQueue[QueIdx]; | |
933 | if ((pEntry = pQueue->Head) == NULL) | |
934 | { | |
935 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | |
936 | break; | |
937 | } | |
938 | ||
939 | pTxBlk = &TxBlk; | |
940 | NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK)); | |
941 | //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it. | |
942 | pTxBlk->QueIdx = QueIdx; | |
943 | ||
944 | pPacket = QUEUE_ENTRY_TO_PKT(pEntry); | |
945 | ||
946 | // Early check to make sure we have enoguh Tx Resource. | |
947 | hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); | |
948 | if (!hasTxDesc) | |
949 | { | |
950 | pAd->PrivateInfo.TxRingFullCnt++; | |
951 | ||
952 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | |
953 | ||
954 | break; | |
955 | } | |
956 | ||
957 | pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket); | |
958 | pEntry = RemoveHeadQueue(pQueue); | |
959 | pTxBlk->TotalFrameNum++; | |
960 | pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary | |
961 | pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); | |
962 | pTxBlk->pPacket = pPacket; | |
963 | InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); | |
964 | ||
965 | if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME) | |
966 | { | |
967 | // Enhance SW Aggregation Mechanism | |
968 | if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType)) | |
969 | { | |
970 | InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); | |
971 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | |
972 | break; | |
973 | } | |
974 | ||
975 | do{ | |
976 | if((pEntry = pQueue->Head) == NULL) | |
977 | break; | |
978 | ||
979 | // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. | |
980 | pPacket = QUEUE_ENTRY_TO_PKT(pEntry); | |
981 | FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); | |
982 | hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); | |
983 | if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE)) | |
984 | break; | |
985 | ||
986 | //Remove the packet from the TxSwQueue and insert into pTxBlk | |
987 | pEntry = RemoveHeadQueue(pQueue); | |
988 | ASSERT(pEntry); | |
989 | pPacket = QUEUE_ENTRY_TO_PKT(pEntry); | |
990 | pTxBlk->TotalFrameNum++; | |
991 | pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary | |
992 | pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); | |
993 | InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); | |
994 | }while(1); | |
995 | ||
996 | if (pTxBlk->TxPacketList.Number == 1) | |
997 | pTxBlk->TxFrameType = TX_LEGACY_FRAME; | |
998 | } | |
999 | ||
1000 | #ifdef RT2870 | |
1001 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | |
1002 | #endif // RT2870 // | |
1003 | ||
1004 | Count += pTxBlk->TxPacketList.Number; | |
1005 | ||
1006 | // Do HardTransmit now. | |
1007 | #ifdef CONFIG_STA_SUPPORT | |
1008 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1009 | Status = STAHardTransmit(pAd, pTxBlk, QueIdx); | |
1010 | #endif // CONFIG_STA_SUPPORT // | |
1011 | } | |
1012 | ||
1013 | RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); | |
1014 | ||
1015 | #ifdef RT2870 | |
1016 | if (!hasTxDesc) | |
1017 | RTUSBKickBulkOut(pAd); | |
1018 | #endif // RT2870 // | |
e642f099 GKH |
1019 | } |
1020 | ||
1021 | } | |
1022 | ||
1023 | ||
1024 | /* | |
1025 | ======================================================================== | |
1026 | ||
1027 | Routine Description: | |
1028 | Calculates the duration which is required to transmit out frames | |
1029 | with given size and specified rate. | |
1030 | ||
1031 | Arguments: | |
1032 | pAd Pointer to our adapter | |
1033 | Rate Transmit rate | |
1034 | Size Frame size in units of byte | |
1035 | ||
1036 | Return Value: | |
1037 | Duration number in units of usec | |
1038 | ||
1039 | IRQL = PASSIVE_LEVEL | |
1040 | IRQL = DISPATCH_LEVEL | |
1041 | ||
1042 | Note: | |
1043 | ||
1044 | ======================================================================== | |
1045 | */ | |
1046 | USHORT RTMPCalcDuration( | |
1047 | IN PRTMP_ADAPTER pAd, | |
1048 | IN UCHAR Rate, | |
1049 | IN ULONG Size) | |
1050 | { | |
1051 | ULONG Duration = 0; | |
1052 | ||
1053 | if (Rate < RATE_FIRST_OFDM_RATE) // CCK | |
1054 | { | |
1055 | if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) | |
1056 | Duration = 96; // 72+24 preamble+plcp | |
1057 | else | |
1058 | Duration = 192; // 144+48 preamble+plcp | |
1059 | ||
1060 | Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]); | |
1061 | if ((Size << 4) % RateIdTo500Kbps[Rate]) | |
1062 | Duration ++; | |
1063 | } | |
1064 | else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates | |
1065 | { | |
1066 | Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension | |
1067 | Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]); | |
1068 | if ((11 + Size * 4) % RateIdTo500Kbps[Rate]) | |
1069 | Duration += 4; | |
1070 | } | |
1071 | else //mimo rate | |
1072 | { | |
1073 | Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension | |
1074 | } | |
1075 | ||
1076 | return (USHORT)Duration; | |
1077 | } | |
1078 | ||
1079 | ||
1080 | /* | |
1081 | ======================================================================== | |
1082 | ||
1083 | Routine Description: | |
1084 | Calculates the duration which is required to transmit out frames | |
1085 | with given size and specified rate. | |
1086 | ||
1087 | Arguments: | |
1088 | pTxWI Pointer to head of each MPDU to HW. | |
1089 | Ack Setting for Ack requirement bit | |
1090 | Fragment Setting for Fragment bit | |
1091 | RetryMode Setting for retry mode | |
1092 | Ifs Setting for IFS gap | |
1093 | Rate Setting for transmit rate | |
1094 | Service Setting for service | |
1095 | Length Frame length | |
1096 | TxPreamble Short or Long preamble when using CCK rates | |
1097 | QueIdx - 0-3, according to 802.11e/d4.4 June/2003 | |
1098 | ||
1099 | Return Value: | |
1100 | None | |
1101 | ||
1102 | IRQL = PASSIVE_LEVEL | |
1103 | IRQL = DISPATCH_LEVEL | |
1104 | ||
1105 | See also : BASmartHardTransmit() !!! | |
1106 | ||
1107 | ======================================================================== | |
1108 | */ | |
1109 | VOID RTMPWriteTxWI( | |
1110 | IN PRTMP_ADAPTER pAd, | |
1111 | IN PTXWI_STRUC pOutTxWI, | |
1112 | IN BOOLEAN FRAG, | |
1113 | IN BOOLEAN CFACK, | |
1114 | IN BOOLEAN InsTimestamp, | |
1115 | IN BOOLEAN AMPDU, | |
1116 | IN BOOLEAN Ack, | |
1117 | IN BOOLEAN NSeq, // HW new a sequence. | |
1118 | IN UCHAR BASize, | |
1119 | IN UCHAR WCID, | |
1120 | IN ULONG Length, | |
1121 | IN UCHAR PID, | |
1122 | IN UCHAR TID, | |
1123 | IN UCHAR TxRate, | |
1124 | IN UCHAR Txopmode, | |
1125 | IN BOOLEAN CfAck, | |
1126 | IN HTTRANSMIT_SETTING *pTransmit) | |
1127 | { | |
1128 | PMAC_TABLE_ENTRY pMac = NULL; | |
1129 | TXWI_STRUC TxWI; | |
1130 | PTXWI_STRUC pTxWI; | |
1131 | ||
1132 | if (WCID < MAX_LEN_OF_MAC_TABLE) | |
1133 | pMac = &pAd->MacTab.Content[WCID]; | |
1134 | ||
1135 | // | |
1136 | // Always use Long preamble before verifiation short preamble functionality works well. | |
1137 | // Todo: remove the following line if short preamble functionality works | |
1138 | // | |
1139 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | |
1140 | NdisZeroMemory(&TxWI, TXWI_SIZE); | |
1141 | pTxWI = &TxWI; | |
1142 | ||
1143 | pTxWI->FRAG= FRAG; | |
1144 | ||
1145 | pTxWI->CFACK = CFACK; | |
1146 | pTxWI->TS= InsTimestamp; | |
1147 | pTxWI->AMPDU = AMPDU; | |
1148 | pTxWI->ACK = Ack; | |
1149 | pTxWI->txop= Txopmode; | |
1150 | ||
1151 | pTxWI->NSEQ = NSeq; | |
1152 | // John tune the performace with Intel Client in 20 MHz performance | |
1153 | #ifdef DOT11_N_SUPPORT | |
1154 | BASize = pAd->CommonCfg.TxBASize; | |
1155 | ||
1156 | if( BASize >7 ) | |
1157 | BASize =7; | |
1158 | pTxWI->BAWinSize = BASize; | |
1159 | pTxWI->ShortGI = pTransmit->field.ShortGI; | |
1160 | pTxWI->STBC = pTransmit->field.STBC; | |
1161 | #endif // DOT11_N_SUPPORT // | |
1162 | ||
1163 | pTxWI->WirelessCliID = WCID; | |
1164 | pTxWI->MPDUtotalByteCount = Length; | |
1165 | pTxWI->PacketId = PID; | |
1166 | ||
1167 | // If CCK or OFDM, BW must be 20 | |
1168 | pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | |
e642f099 GKH |
1169 | |
1170 | pTxWI->MCS = pTransmit->field.MCS; | |
1171 | pTxWI->PHYMODE = pTransmit->field.MODE; | |
1172 | pTxWI->CFACK = CfAck; | |
1173 | ||
1174 | #ifdef DOT11_N_SUPPORT | |
1175 | if (pMac) | |
1176 | { | |
1177 | if (pAd->CommonCfg.bMIMOPSEnable) | |
1178 | { | |
1179 | if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) | |
1180 | { | |
1181 | // Dynamic MIMO Power Save Mode | |
1182 | pTxWI->MIMOps = 1; | |
1183 | } | |
1184 | else if (pMac->MmpsMode == MMPS_STATIC) | |
1185 | { | |
1186 | // Static MIMO Power Save Mode | |
1187 | if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) | |
1188 | { | |
1189 | pTxWI->MCS = 7; | |
1190 | pTxWI->MIMOps = 0; | |
1191 | } | |
1192 | } | |
1193 | } | |
1194 | //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; | |
1195 | if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled)) | |
1196 | { | |
1197 | pTxWI->MpduDensity = 7; | |
1198 | } | |
1199 | else | |
1200 | { | |
1201 | pTxWI->MpduDensity = pMac->MpduDensity; | |
1202 | } | |
1203 | } | |
1204 | #endif // DOT11_N_SUPPORT // | |
1205 | ||
1206 | pTxWI->PacketId = pTxWI->MCS; | |
1207 | NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC)); | |
1208 | } | |
1209 | ||
1210 | ||
1211 | VOID RTMPWriteTxWI_Data( | |
1212 | IN PRTMP_ADAPTER pAd, | |
1213 | IN OUT PTXWI_STRUC pTxWI, | |
1214 | IN TX_BLK *pTxBlk) | |
1215 | { | |
1216 | HTTRANSMIT_SETTING *pTransmit; | |
1217 | PMAC_TABLE_ENTRY pMacEntry; | |
1218 | #ifdef DOT11_N_SUPPORT | |
1219 | UCHAR BASize; | |
1220 | #endif // DOT11_N_SUPPORT // | |
1221 | ||
1222 | ||
1223 | ASSERT(pTxWI); | |
1224 | ||
1225 | pTransmit = pTxBlk->pTransmit; | |
1226 | pMacEntry = pTxBlk->pMacEntry; | |
1227 | ||
1228 | ||
1229 | // | |
1230 | // Always use Long preamble before verifiation short preamble functionality works well. | |
1231 | // Todo: remove the following line if short preamble functionality works | |
1232 | // | |
1233 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | |
1234 | NdisZeroMemory(pTxWI, TXWI_SIZE); | |
1235 | ||
1236 | pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); | |
1237 | pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); | |
1238 | pTxWI->txop = pTxBlk->FrameGap; | |
1239 | ||
e642f099 GKH |
1240 | pTxWI->WirelessCliID = pTxBlk->Wcid; |
1241 | ||
1242 | pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; | |
1243 | pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); | |
1244 | ||
1245 | // If CCK or OFDM, BW must be 20 | |
1246 | pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | |
1247 | #ifdef DOT11_N_SUPPORT | |
e642f099 GKH |
1248 | pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); |
1249 | ||
1250 | // John tune the performace with Intel Client in 20 MHz performance | |
1251 | BASize = pAd->CommonCfg.TxBASize; | |
1252 | if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) | |
1253 | { | |
1254 | UCHAR RABAOriIdx = 0; //The RA's BA Originator table index. | |
1255 | ||
1256 | RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; | |
1257 | BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; | |
1258 | } | |
1259 | ||
1260 | pTxWI->TxBF = pTransmit->field.TxBF; | |
1261 | pTxWI->BAWinSize = BASize; | |
1262 | pTxWI->ShortGI = pTransmit->field.ShortGI; | |
1263 | pTxWI->STBC = pTransmit->field.STBC; | |
1264 | #endif // DOT11_N_SUPPORT // | |
1265 | ||
1266 | pTxWI->MCS = pTransmit->field.MCS; | |
1267 | pTxWI->PHYMODE = pTransmit->field.MODE; | |
1268 | ||
1269 | #ifdef DOT11_N_SUPPORT | |
1270 | if (pMacEntry) | |
1271 | { | |
1272 | if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) | |
1273 | { | |
1274 | // Dynamic MIMO Power Save Mode | |
1275 | pTxWI->MIMOps = 1; | |
1276 | } | |
1277 | else if (pMacEntry->MmpsMode == MMPS_STATIC) | |
1278 | { | |
1279 | // Static MIMO Power Save Mode | |
1280 | if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) | |
1281 | { | |
1282 | pTxWI->MCS = 7; | |
1283 | pTxWI->MIMOps = 0; | |
1284 | } | |
1285 | } | |
1286 | ||
1287 | if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) | |
1288 | { | |
1289 | pTxWI->MpduDensity = 7; | |
1290 | } | |
1291 | else | |
1292 | { | |
1293 | pTxWI->MpduDensity = pMacEntry->MpduDensity; | |
1294 | } | |
1295 | } | |
1296 | #endif // DOT11_N_SUPPORT // | |
1297 | ||
1298 | #ifdef DBG_DIAGNOSE | |
1299 | if (pTxBlk->QueIdx== 0) | |
1300 | { | |
1301 | pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; | |
1302 | pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; | |
1303 | } | |
1304 | #endif // DBG_DIAGNOSE // | |
1305 | ||
1306 | // for rate adapation | |
1307 | pTxWI->PacketId = pTxWI->MCS; | |
e642f099 GKH |
1308 | } |
1309 | ||
1310 | ||
1311 | VOID RTMPWriteTxWI_Cache( | |
1312 | IN PRTMP_ADAPTER pAd, | |
1313 | IN OUT PTXWI_STRUC pTxWI, | |
1314 | IN TX_BLK *pTxBlk) | |
1315 | { | |
1316 | PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit; | |
1317 | PMAC_TABLE_ENTRY pMacEntry; | |
1318 | ||
1319 | // | |
1320 | // update TXWI | |
1321 | // | |
1322 | pMacEntry = pTxBlk->pMacEntry; | |
1323 | pTransmit = pTxBlk->pTransmit; | |
1324 | ||
1325 | //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) | |
1326 | //if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) | |
1327 | //if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) | |
1328 | if (pMacEntry->bAutoTxRateSwitch) | |
1329 | { | |
1330 | pTxWI->txop = IFS_HTTXOP; | |
1331 | ||
1332 | // If CCK or OFDM, BW must be 20 | |
1333 | pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | |
1334 | pTxWI->ShortGI = pTransmit->field.ShortGI; | |
1335 | pTxWI->STBC = pTransmit->field.STBC; | |
1336 | ||
1337 | pTxWI->MCS = pTransmit->field.MCS; | |
1338 | pTxWI->PHYMODE = pTransmit->field.MODE; | |
1339 | ||
1340 | // set PID for TxRateSwitching | |
1341 | pTxWI->PacketId = pTransmit->field.MCS; | |
1342 | } | |
1343 | ||
1344 | #ifdef DOT11_N_SUPPORT | |
1345 | pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE); | |
1346 | pTxWI->MIMOps = 0; | |
1347 | ||
e642f099 GKH |
1348 | if (pAd->CommonCfg.bMIMOPSEnable) |
1349 | { | |
1350 | // MIMO Power Save Mode | |
1351 | if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) | |
1352 | { | |
1353 | // Dynamic MIMO Power Save Mode | |
1354 | pTxWI->MIMOps = 1; | |
1355 | } | |
1356 | else if (pMacEntry->MmpsMode == MMPS_STATIC) | |
1357 | { | |
1358 | // Static MIMO Power Save Mode | |
1359 | if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7)) | |
1360 | { | |
1361 | pTxWI->MCS = 7; | |
1362 | pTxWI->MIMOps = 0; | |
1363 | } | |
1364 | } | |
1365 | } | |
1366 | #endif // DOT11_N_SUPPORT // | |
1367 | ||
1368 | #ifdef DBG_DIAGNOSE | |
1369 | if (pTxBlk->QueIdx== 0) | |
1370 | { | |
1371 | pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; | |
1372 | pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; | |
1373 | } | |
1374 | #endif // DBG_DIAGNOSE // | |
1375 | ||
1376 | pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; | |
1377 | ||
1378 | } | |
1379 | ||
1380 | ||
1381 | /* | |
1382 | ======================================================================== | |
1383 | ||
1384 | Routine Description: | |
1385 | Calculates the duration which is required to transmit out frames | |
1386 | with given size and specified rate. | |
1387 | ||
1388 | Arguments: | |
1389 | pTxD Pointer to transmit descriptor | |
1390 | Ack Setting for Ack requirement bit | |
1391 | Fragment Setting for Fragment bit | |
1392 | RetryMode Setting for retry mode | |
1393 | Ifs Setting for IFS gap | |
1394 | Rate Setting for transmit rate | |
1395 | Service Setting for service | |
1396 | Length Frame length | |
1397 | TxPreamble Short or Long preamble when using CCK rates | |
1398 | QueIdx - 0-3, according to 802.11e/d4.4 June/2003 | |
1399 | ||
1400 | Return Value: | |
1401 | None | |
1402 | ||
1403 | IRQL = PASSIVE_LEVEL | |
1404 | IRQL = DISPATCH_LEVEL | |
1405 | ||
1406 | ======================================================================== | |
1407 | */ | |
1408 | VOID RTMPWriteTxDescriptor( | |
1409 | IN PRTMP_ADAPTER pAd, | |
1410 | IN PTXD_STRUC pTxD, | |
1411 | IN BOOLEAN bWIV, | |
1412 | IN UCHAR QueueSEL) | |
1413 | { | |
1414 | // | |
1415 | // Always use Long preamble before verifiation short preamble functionality works well. | |
1416 | // Todo: remove the following line if short preamble functionality works | |
1417 | // | |
1418 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | |
1419 | ||
1420 | pTxD->WIV = (bWIV) ? 1: 0; | |
1421 | pTxD->QSEL= (QueueSEL); | |
1422 | if (pAd->bGenOneHCCA == TRUE) | |
1423 | pTxD->QSEL= FIFO_HCCA; | |
1424 | pTxD->DMADONE = 0; | |
1425 | } | |
1426 | ||
1427 | ||
1428 | // should be called only when - | |
1429 | // 1. MEADIA_CONNECTED | |
1430 | // 2. AGGREGATION_IN_USED | |
1431 | // 3. Fragmentation not in used | |
1432 | // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible | |
1433 | BOOLEAN TxFrameIsAggregatible( | |
1434 | IN PRTMP_ADAPTER pAd, | |
1435 | IN PUCHAR pPrevAddr1, | |
1436 | IN PUCHAR p8023hdr) | |
1437 | { | |
1438 | ||
1439 | // can't aggregate EAPOL (802.1x) frame | |
1440 | if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e)) | |
1441 | return FALSE; | |
1442 | ||
1443 | // can't aggregate multicast/broadcast frame | |
1444 | if (p8023hdr[0] & 0x01) | |
1445 | return FALSE; | |
1446 | ||
1447 | if (INFRA_ON(pAd)) // must be unicast to AP | |
1448 | return TRUE; | |
1449 | else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA | |
1450 | return TRUE; | |
1451 | else | |
1452 | return FALSE; | |
1453 | } | |
1454 | ||
1455 | ||
1456 | /* | |
1457 | ======================================================================== | |
1458 | ||
1459 | Routine Description: | |
1460 | Check the MSDU Aggregation policy | |
1461 | 1.HT aggregation is A-MSDU | |
1462 | 2.legaacy rate aggregation is software aggregation by Ralink. | |
1463 | ||
1464 | Arguments: | |
1465 | ||
1466 | Return Value: | |
1467 | ||
1468 | Note: | |
1469 | ||
1470 | ======================================================================== | |
1471 | */ | |
1472 | BOOLEAN PeerIsAggreOn( | |
1473 | IN PRTMP_ADAPTER pAd, | |
1474 | IN ULONG TxRate, | |
1475 | IN PMAC_TABLE_ENTRY pMacEntry) | |
1476 | { | |
1477 | ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE); | |
1478 | ||
1479 | if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) | |
1480 | { | |
1481 | #ifdef DOT11_N_SUPPORT | |
1482 | if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) | |
1483 | { | |
1484 | return TRUE; | |
1485 | } | |
1486 | #endif // DOT11_N_SUPPORT // | |
1487 | ||
1488 | #ifdef AGGREGATION_SUPPORT | |
1489 | if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) | |
1490 | { // legacy Ralink Aggregation support | |
1491 | return TRUE; | |
1492 | } | |
1493 | #endif // AGGREGATION_SUPPORT // | |
1494 | } | |
1495 | ||
1496 | return FALSE; | |
1497 | ||
1498 | } | |
1499 | ||
1500 | ||
1501 | /* | |
1502 | ======================================================================== | |
1503 | ||
1504 | Routine Description: | |
1505 | Check and fine the packet waiting in SW queue with highest priority | |
1506 | ||
1507 | Arguments: | |
1508 | pAd Pointer to our adapter | |
1509 | ||
1510 | Return Value: | |
1511 | pQueue Pointer to Waiting Queue | |
1512 | ||
1513 | IRQL = DISPATCH_LEVEL | |
1514 | ||
1515 | Note: | |
1516 | ||
1517 | ======================================================================== | |
1518 | */ | |
1519 | PQUEUE_HEADER RTMPCheckTxSwQueue( | |
1520 | IN PRTMP_ADAPTER pAd, | |
1521 | OUT PUCHAR pQueIdx) | |
1522 | { | |
1523 | ||
1524 | ULONG Number; | |
1525 | // 2004-11-15 to be removed. test aggregation only | |
1526 | // if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) | |
1527 | // return NULL; | |
1528 | ||
1529 | Number = pAd->TxSwQueue[QID_AC_BK].Number | |
1530 | + pAd->TxSwQueue[QID_AC_BE].Number | |
1531 | + pAd->TxSwQueue[QID_AC_VI].Number | |
1532 | + pAd->TxSwQueue[QID_AC_VO].Number | |
1533 | + pAd->TxSwQueue[QID_HCCA].Number; | |
1534 | ||
1535 | if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) | |
1536 | { | |
1537 | *pQueIdx = QID_AC_VO; | |
1538 | return (&pAd->TxSwQueue[QID_AC_VO]); | |
1539 | } | |
1540 | else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) | |
1541 | { | |
1542 | *pQueIdx = QID_AC_VI; | |
1543 | return (&pAd->TxSwQueue[QID_AC_VI]); | |
1544 | } | |
1545 | else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) | |
1546 | { | |
1547 | *pQueIdx = QID_AC_BE; | |
1548 | return (&pAd->TxSwQueue[QID_AC_BE]); | |
1549 | } | |
1550 | else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) | |
1551 | { | |
1552 | *pQueIdx = QID_AC_BK; | |
1553 | return (&pAd->TxSwQueue[QID_AC_BK]); | |
1554 | } | |
1555 | else if (pAd->TxSwQueue[QID_HCCA].Head != NULL) | |
1556 | { | |
1557 | *pQueIdx = QID_HCCA; | |
1558 | return (&pAd->TxSwQueue[QID_HCCA]); | |
1559 | } | |
1560 | ||
1561 | // No packet pending in Tx Sw queue | |
1562 | *pQueIdx = QID_AC_BK; | |
1563 | ||
1564 | return (NULL); | |
1565 | } | |
1566 | ||
1567 | ||
1568 | ||
1569 | /* | |
1570 | ======================================================================== | |
1571 | ||
1572 | Routine Description: | |
1573 | Suspend MSDU transmission | |
1574 | ||
1575 | Arguments: | |
1576 | pAd Pointer to our adapter | |
1577 | ||
1578 | Return Value: | |
1579 | None | |
1580 | ||
1581 | Note: | |
1582 | ||
1583 | ======================================================================== | |
1584 | */ | |
1585 | VOID RTMPSuspendMsduTransmission( | |
1586 | IN PRTMP_ADAPTER pAd) | |
1587 | { | |
1588 | DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n")); | |
1589 | ||
1590 | ||
1591 | // | |
1592 | // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and | |
1593 | // use Lowbound as R66 value on ScanNextChannel(...) | |
1594 | // | |
1595 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue); | |
1596 | ||
1597 | // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) | |
1598 | //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); | |
1599 | RTMPSetAGCInitValue(pAd, BW_20); | |
1600 | ||
1601 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | |
1602 | //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings | |
1603 | } | |
1604 | ||
1605 | ||
1606 | /* | |
1607 | ======================================================================== | |
1608 | ||
1609 | Routine Description: | |
1610 | Resume MSDU transmission | |
1611 | ||
1612 | Arguments: | |
1613 | pAd Pointer to our adapter | |
1614 | ||
1615 | Return Value: | |
1616 | None | |
1617 | ||
1618 | IRQL = DISPATCH_LEVEL | |
1619 | ||
1620 | Note: | |
1621 | ||
1622 | ======================================================================== | |
1623 | */ | |
1624 | VOID RTMPResumeMsduTransmission( | |
1625 | IN PRTMP_ADAPTER pAd) | |
1626 | { | |
1627 | // UCHAR IrqState; | |
1628 | ||
1629 | DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n")); | |
1630 | ||
1631 | ||
1632 | // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value | |
1633 | // R66 should not be 0 | |
1634 | if (pAd->BbpTuning.R66CurrentValue == 0) | |
1635 | { | |
1636 | pAd->BbpTuning.R66CurrentValue = 0x38; | |
1637 | DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n")); | |
1638 | } | |
1639 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue); | |
1640 | ||
1641 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | |
1642 | // sample, for IRQ LOCK to SEM LOCK | |
1643 | // IrqState = pAd->irq_disabled; | |
1644 | // if (IrqState) | |
1645 | // RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); | |
1646 | // else | |
1647 | RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); | |
1648 | } | |
1649 | ||
1650 | ||
1651 | UINT deaggregate_AMSDU_announce( | |
1652 | IN PRTMP_ADAPTER pAd, | |
1653 | PNDIS_PACKET pPacket, | |
1654 | IN PUCHAR pData, | |
1655 | IN ULONG DataSize) | |
1656 | { | |
1657 | USHORT PayloadSize; | |
1658 | USHORT SubFrameSize; | |
1659 | PHEADER_802_3 pAMSDUsubheader; | |
1660 | UINT nMSDU; | |
1661 | UCHAR Header802_3[14]; | |
1662 | ||
1663 | PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP; | |
1664 | PNDIS_PACKET pClonePacket; | |
1665 | ||
1666 | ||
1667 | ||
1668 | nMSDU = 0; | |
1669 | ||
1670 | while (DataSize > LENGTH_802_3) | |
1671 | { | |
1672 | ||
1673 | nMSDU++; | |
1674 | ||
1675 | //hex_dump("subheader", pData, 64); | |
1676 | pAMSDUsubheader = (PHEADER_802_3)pData; | |
1677 | //pData += LENGTH_802_3; | |
1678 | PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8); | |
1679 | SubFrameSize = PayloadSize + LENGTH_802_3; | |
1680 | ||
1681 | ||
1682 | if ((DataSize < SubFrameSize) || (PayloadSize > 1518 )) | |
1683 | { | |
1684 | break; | |
1685 | } | |
1686 | ||
1687 | //printk("%d subframe: Size = %d\n", nMSDU, PayloadSize); | |
1688 | ||
1689 | pPayload = pData + LENGTH_802_3; | |
1690 | pDA = pData; | |
1691 | pSA = pData + MAC_ADDR_LEN; | |
1692 | ||
1693 | // convert to 802.3 header | |
1694 | CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP); | |
1695 | ||
1696 | #ifdef CONFIG_STA_SUPPORT | |
1697 | if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) ) | |
1698 | { | |
1699 | // avoid local heap overflow, use dyanamic allocation | |
1700 | MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); | |
1701 | memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize); | |
1702 | Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize; | |
1703 | WpaEAPOLKeyAction(pAd, Elem); | |
1704 | kfree(Elem); | |
1705 | } | |
1706 | #endif // CONFIG_STA_SUPPORT // | |
1707 | ||
1708 | #ifdef CONFIG_STA_SUPPORT | |
1709 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1710 | { | |
1711 | if (pRemovedLLCSNAP) | |
1712 | { | |
1713 | pPayload -= LENGTH_802_3; | |
1714 | PayloadSize += LENGTH_802_3; | |
1715 | NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3); | |
1716 | } | |
1717 | } | |
1718 | #endif // CONFIG_STA_SUPPORT // | |
1719 | ||
1720 | pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize); | |
1721 | if (pClonePacket) | |
1722 | { | |
1723 | #ifdef CONFIG_STA_SUPPORT | |
1724 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1725 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket)); | |
1726 | #endif // CONFIG_STA_SUPPORT // | |
1727 | } | |
1728 | ||
1729 | ||
1730 | // A-MSDU has padding to multiple of 4 including subframe header. | |
1731 | // align SubFrameSize up to multiple of 4 | |
1732 | SubFrameSize = (SubFrameSize+3)&(~0x3); | |
1733 | ||
1734 | ||
1735 | if (SubFrameSize > 1528 || SubFrameSize < 32) | |
1736 | { | |
1737 | break; | |
1738 | } | |
1739 | ||
1740 | if (DataSize > SubFrameSize) | |
1741 | { | |
1742 | pData += SubFrameSize; | |
1743 | DataSize -= SubFrameSize; | |
1744 | } | |
1745 | else | |
1746 | { | |
1747 | // end of A-MSDU | |
1748 | DataSize = 0; | |
1749 | } | |
1750 | } | |
1751 | ||
1752 | // finally release original rx packet | |
1753 | RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); | |
1754 | ||
1755 | return nMSDU; | |
1756 | } | |
1757 | ||
1758 | ||
1759 | UINT BA_Reorder_AMSDU_Annnounce( | |
1760 | IN PRTMP_ADAPTER pAd, | |
1761 | IN PNDIS_PACKET pPacket) | |
1762 | { | |
1763 | PUCHAR pData; | |
1764 | USHORT DataSize; | |
1765 | UINT nMSDU = 0; | |
1766 | ||
1767 | pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); | |
1768 | DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); | |
1769 | ||
1770 | nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize); | |
1771 | ||
1772 | return nMSDU; | |
1773 | } | |
1774 | ||
1775 | ||
1776 | /* | |
1777 | ========================================================================== | |
1778 | Description: | |
1779 | Look up the MAC address in the MAC table. Return NULL if not found. | |
1780 | Return: | |
1781 | pEntry - pointer to the MAC entry; NULL is not found | |
1782 | ========================================================================== | |
1783 | */ | |
1784 | MAC_TABLE_ENTRY *MacTableLookup( | |
1785 | IN PRTMP_ADAPTER pAd, | |
1786 | PUCHAR pAddr) | |
1787 | { | |
1788 | ULONG HashIdx; | |
1789 | MAC_TABLE_ENTRY *pEntry = NULL; | |
1790 | ||
1791 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | |
1792 | pEntry = pAd->MacTab.Hash[HashIdx]; | |
1793 | ||
1794 | while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) | |
1795 | { | |
1796 | if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) | |
1797 | { | |
1798 | break; | |
1799 | } | |
1800 | else | |
1801 | pEntry = pEntry->pNext; | |
1802 | } | |
1803 | ||
1804 | return pEntry; | |
1805 | } | |
1806 | ||
1807 | MAC_TABLE_ENTRY *MacTableInsertEntry( | |
1808 | IN PRTMP_ADAPTER pAd, | |
1809 | IN PUCHAR pAddr, | |
1810 | IN UCHAR apidx, | |
1811 | IN BOOLEAN CleanAll) | |
1812 | { | |
1813 | UCHAR HashIdx; | |
1814 | int i, FirstWcid; | |
1815 | MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; | |
1816 | // USHORT offset; | |
1817 | // ULONG addr; | |
1818 | ||
1819 | // if FULL, return | |
1820 | if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) | |
1821 | return NULL; | |
1822 | ||
1823 | FirstWcid = 1; | |
1824 | #ifdef CONFIG_STA_SUPPORT | |
1825 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1826 | if (pAd->StaCfg.BssType == BSS_INFRA) | |
1827 | FirstWcid = 2; | |
1828 | #endif // CONFIG_STA_SUPPORT // | |
1829 | ||
1830 | // allocate one MAC entry | |
1831 | NdisAcquireSpinLock(&pAd->MacTabLock); | |
1832 | for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup | |
1833 | { | |
1834 | // pick up the first available vacancy | |
1835 | if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) && | |
1836 | (pAd->MacTab.Content[i].ValidAsWDS == FALSE) && | |
1837 | (pAd->MacTab.Content[i].ValidAsApCli== FALSE) && | |
1838 | (pAd->MacTab.Content[i].ValidAsMesh == FALSE) | |
e642f099 GKH |
1839 | ) |
1840 | { | |
1841 | pEntry = &pAd->MacTab.Content[i]; | |
1842 | if (CleanAll == TRUE) | |
1843 | { | |
1844 | pEntry->MaxSupportedRate = RATE_11; | |
1845 | pEntry->CurrTxRate = RATE_11; | |
1846 | NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); | |
1847 | pEntry->PairwiseKey.KeyLen = 0; | |
1848 | pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; | |
1849 | } | |
e642f099 GKH |
1850 | { |
1851 | ||
1852 | #ifdef CONFIG_STA_SUPPORT | |
1853 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1854 | { | |
1855 | pEntry->ValidAsCLI = TRUE; | |
1856 | pEntry->ValidAsWDS = FALSE; | |
1857 | pEntry->ValidAsApCli = FALSE; | |
1858 | pEntry->ValidAsMesh = FALSE; | |
1859 | pEntry->ValidAsDls = FALSE; | |
1860 | } | |
1861 | #endif // CONFIG_STA_SUPPORT // | |
1862 | } | |
1863 | ||
1864 | pEntry->bIAmBadAtheros = FALSE; | |
1865 | pEntry->pAd = pAd; | |
1866 | pEntry->CMTimerRunning = FALSE; | |
1867 | pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; | |
1868 | pEntry->RSNIE_Len = 0; | |
1869 | NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); | |
1870 | pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; | |
1871 | ||
1872 | if (pEntry->ValidAsMesh) | |
1873 | pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH); | |
1874 | else if (pEntry->ValidAsApCli) | |
1875 | pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI); | |
1876 | else if (pEntry->ValidAsWDS) | |
1877 | pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS); | |
e642f099 GKH |
1878 | else |
1879 | pEntry->apidx = apidx; | |
1880 | ||
1881 | { | |
1882 | ||
1883 | #ifdef CONFIG_STA_SUPPORT | |
1884 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1885 | { | |
1886 | pEntry->AuthMode = pAd->StaCfg.AuthMode; | |
1887 | pEntry->WepStatus = pAd->StaCfg.WepStatus; | |
1888 | pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; | |
1889 | } | |
1890 | #endif // CONFIG_STA_SUPPORT // | |
1891 | } | |
1892 | ||
1893 | pEntry->GTKState = REKEY_NEGOTIATING; | |
1894 | pEntry->PairwiseKey.KeyLen = 0; | |
1895 | pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; | |
e642f099 GKH |
1896 | pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; |
1897 | pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; | |
1898 | COPY_MAC_ADDR(pEntry->Addr, pAddr); | |
1899 | pEntry->Sst = SST_NOT_AUTH; | |
1900 | pEntry->AuthState = AS_NOT_AUTH; | |
1901 | pEntry->Aid = (USHORT)i; //0; | |
1902 | pEntry->CapabilityInfo = 0; | |
1903 | pEntry->PsMode = PWR_ACTIVE; | |
1904 | pEntry->PsQIdleCount = 0; | |
1905 | pEntry->NoDataIdleCount = 0; | |
1906 | pEntry->ContinueTxFailCnt = 0; | |
1907 | InitializeQueueHeader(&pEntry->PsQueue); | |
1908 | ||
1909 | ||
1910 | pAd->MacTab.Size ++; | |
1911 | ||
1912 | // Add this entry into ASIC RX WCID search table | |
1913 | RT28XX_STA_ENTRY_ADD(pAd, pEntry); | |
1914 | ||
1915 | ||
1916 | ||
1917 | DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size)); | |
1918 | break; | |
1919 | } | |
1920 | } | |
1921 | ||
1922 | // add this MAC entry into HASH table | |
1923 | if (pEntry) | |
1924 | { | |
1925 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | |
1926 | if (pAd->MacTab.Hash[HashIdx] == NULL) | |
1927 | { | |
1928 | pAd->MacTab.Hash[HashIdx] = pEntry; | |
1929 | } | |
1930 | else | |
1931 | { | |
1932 | pCurrEntry = pAd->MacTab.Hash[HashIdx]; | |
1933 | while (pCurrEntry->pNext != NULL) | |
1934 | pCurrEntry = pCurrEntry->pNext; | |
1935 | pCurrEntry->pNext = pEntry; | |
1936 | } | |
1937 | } | |
1938 | ||
1939 | NdisReleaseSpinLock(&pAd->MacTabLock); | |
1940 | return pEntry; | |
1941 | } | |
1942 | ||
1943 | /* | |
1944 | ========================================================================== | |
1945 | Description: | |
1946 | Delete a specified client from MAC table | |
1947 | ========================================================================== | |
1948 | */ | |
1949 | BOOLEAN MacTableDeleteEntry( | |
1950 | IN PRTMP_ADAPTER pAd, | |
1951 | IN USHORT wcid, | |
1952 | IN PUCHAR pAddr) | |
1953 | { | |
1954 | USHORT HashIdx; | |
1955 | MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; | |
1956 | BOOLEAN Cancelled; | |
1957 | //USHORT offset; // unused variable | |
1958 | //UCHAR j; // unused variable | |
1959 | ||
1960 | if (wcid >= MAX_LEN_OF_MAC_TABLE) | |
1961 | return FALSE; | |
1962 | ||
1963 | NdisAcquireSpinLock(&pAd->MacTabLock); | |
1964 | ||
1965 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | |
1966 | //pEntry = pAd->MacTab.Hash[HashIdx]; | |
1967 | pEntry = &pAd->MacTab.Content[wcid]; | |
1968 | ||
1969 | if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh | |
e642f099 GKH |
1970 | )) |
1971 | { | |
1972 | if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) | |
1973 | { | |
1974 | ||
1975 | // Delete this entry from ASIC on-chip WCID Table | |
1976 | RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid); | |
1977 | ||
1978 | #ifdef DOT11_N_SUPPORT | |
1979 | // free resources of BA | |
1980 | BASessionTearDownALL(pAd, pEntry->Aid); | |
1981 | #endif // DOT11_N_SUPPORT // | |
1982 | ||
1983 | ||
1984 | pPrevEntry = NULL; | |
1985 | pProbeEntry = pAd->MacTab.Hash[HashIdx]; | |
1986 | ASSERT(pProbeEntry); | |
1987 | ||
1988 | // update Hash list | |
1989 | do | |
1990 | { | |
1991 | if (pProbeEntry == pEntry) | |
1992 | { | |
1993 | if (pPrevEntry == NULL) | |
1994 | { | |
1995 | pAd->MacTab.Hash[HashIdx] = pEntry->pNext; | |
1996 | } | |
1997 | else | |
1998 | { | |
1999 | pPrevEntry->pNext = pEntry->pNext; | |
2000 | } | |
2001 | break; | |
2002 | } | |
2003 | ||
2004 | pPrevEntry = pProbeEntry; | |
2005 | pProbeEntry = pProbeEntry->pNext; | |
2006 | } while (pProbeEntry); | |
2007 | ||
2008 | // not found !!! | |
2009 | ASSERT(pProbeEntry != NULL); | |
2010 | ||
2011 | RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid); | |
2012 | ||
2013 | ||
2014 | if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) | |
2015 | { | |
2016 | RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); | |
2017 | pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; | |
2018 | } | |
2019 | ||
2020 | ||
2021 | NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); | |
2022 | pAd->MacTab.Size --; | |
2023 | DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size)); | |
2024 | } | |
2025 | else | |
2026 | { | |
d75b81a8 | 2027 | printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid); |
e642f099 GKH |
2028 | } |
2029 | } | |
2030 | ||
2031 | NdisReleaseSpinLock(&pAd->MacTabLock); | |
2032 | ||
2033 | //Reset operating mode when no Sta. | |
2034 | if (pAd->MacTab.Size == 0) | |
2035 | { | |
2036 | #ifdef DOT11_N_SUPPORT | |
2037 | pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; | |
2038 | #endif // DOT11_N_SUPPORT // | |
2039 | //AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/); | |
2040 | RT28XX_UPDATE_PROTECT(pAd); // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet | |
2041 | } | |
2042 | ||
2043 | return TRUE; | |
2044 | } | |
2045 | ||
2046 | ||
2047 | /* | |
2048 | ========================================================================== | |
2049 | Description: | |
2050 | This routine reset the entire MAC table. All packets pending in | |
2051 | the power-saving queues are freed here. | |
2052 | ========================================================================== | |
2053 | */ | |
2054 | VOID MacTableReset( | |
2055 | IN PRTMP_ADAPTER pAd) | |
2056 | { | |
2057 | int i; | |
2058 | ||
2059 | DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); | |
2060 | //NdisAcquireSpinLock(&pAd->MacTabLock); | |
2061 | ||
2062 | for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++) | |
2063 | { | |
2064 | if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) | |
2065 | { | |
2066 | ||
2067 | #ifdef DOT11_N_SUPPORT | |
2068 | // free resources of BA | |
2069 | BASessionTearDownALL(pAd, i); | |
2070 | #endif // DOT11_N_SUPPORT // | |
2071 | ||
2072 | pAd->MacTab.Content[i].ValidAsCLI = FALSE; | |
2073 | ||
2074 | ||
2075 | ||
2076 | #ifdef RT2870 | |
2077 | NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6); | |
2078 | RT28XX_STA_ENTRY_MAC_RESET(pAd, i); | |
2079 | #endif // RT2870 // | |
2080 | ||
2081 | //AsicDelWcidTab(pAd, i); | |
2082 | } | |
2083 | } | |
2084 | ||
2085 | return; | |
2086 | } | |
2087 | ||
2088 | /* | |
2089 | ========================================================================== | |
2090 | Description: | |
2091 | ||
2092 | IRQL = DISPATCH_LEVEL | |
2093 | ||
2094 | ========================================================================== | |
2095 | */ | |
2096 | VOID AssocParmFill( | |
2097 | IN PRTMP_ADAPTER pAd, | |
2098 | IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, | |
2099 | IN PUCHAR pAddr, | |
2100 | IN USHORT CapabilityInfo, | |
2101 | IN ULONG Timeout, | |
2102 | IN USHORT ListenIntv) | |
2103 | { | |
2104 | COPY_MAC_ADDR(AssocReq->Addr, pAddr); | |
2105 | // Add mask to support 802.11b mode only | |
2106 | AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request | |
2107 | AssocReq->Timeout = Timeout; | |
2108 | AssocReq->ListenIntv = ListenIntv; | |
2109 | } | |
2110 | ||
2111 | ||
2112 | /* | |
2113 | ========================================================================== | |
2114 | Description: | |
2115 | ||
2116 | IRQL = DISPATCH_LEVEL | |
2117 | ||
2118 | ========================================================================== | |
2119 | */ | |
2120 | VOID DisassocParmFill( | |
2121 | IN PRTMP_ADAPTER pAd, | |
2122 | IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, | |
2123 | IN PUCHAR pAddr, | |
2124 | IN USHORT Reason) | |
2125 | { | |
2126 | COPY_MAC_ADDR(DisassocReq->Addr, pAddr); | |
2127 | DisassocReq->Reason = Reason; | |
2128 | } | |
2129 | ||
2130 | ||
2131 | /* | |
2132 | ======================================================================== | |
2133 | ||
2134 | Routine Description: | |
2135 | Check the out going frame, if this is an DHCP or ARP datagram | |
2136 | will be duplicate another frame at low data rate transmit. | |
2137 | ||
2138 | Arguments: | |
2139 | pAd Pointer to our adapter | |
2140 | pPacket Pointer to outgoing Ndis frame | |
2141 | ||
2142 | Return Value: | |
2143 | TRUE To be duplicate at Low data rate transmit. (1mb) | |
2144 | FALSE Do nothing. | |
2145 | ||
2146 | IRQL = DISPATCH_LEVEL | |
2147 | ||
2148 | Note: | |
2149 | ||
2150 | MAC header + IP Header + UDP Header | |
2151 | 14 Bytes 20 Bytes | |
2152 | ||
2153 | UDP Header | |
2154 | 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| | |
2155 | Source Port | |
2156 | 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31| | |
2157 | Destination Port | |
2158 | ||
2159 | port 0x43 means Bootstrap Protocol, server. | |
2160 | Port 0x44 means Bootstrap Protocol, client. | |
2161 | ||
2162 | ======================================================================== | |
2163 | */ | |
2164 | ||
2165 | BOOLEAN RTMPCheckDHCPFrame( | |
2166 | IN PRTMP_ADAPTER pAd, | |
2167 | IN PNDIS_PACKET pPacket) | |
2168 | { | |
2169 | PACKET_INFO PacketInfo; | |
2170 | ULONG NumberOfBytesRead = 0; | |
2171 | ULONG CurrentOffset = 0; | |
2172 | PVOID pVirtualAddress = NULL; | |
2173 | UINT NdisBufferLength; | |
2174 | PUCHAR pSrc; | |
2175 | USHORT Protocol; | |
2176 | UCHAR ByteOffset36 = 0; | |
2177 | UCHAR ByteOffset38 = 0; | |
2178 | BOOLEAN ReadFirstParm = TRUE; | |
2179 | ||
2180 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength); | |
2181 | ||
2182 | NumberOfBytesRead += NdisBufferLength; | |
2183 | pSrc = (PUCHAR) pVirtualAddress; | |
2184 | Protocol = *(pSrc + 12) * 256 + *(pSrc + 13); | |
2185 | ||
2186 | // | |
2187 | // Check DHCP & BOOTP protocol | |
2188 | // | |
2189 | while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) | |
2190 | { | |
2191 | if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) | |
2192 | { | |
2193 | CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength); | |
2194 | ByteOffset36 = *(pSrc + CurrentOffset); | |
2195 | ReadFirstParm = FALSE; | |
2196 | } | |
2197 | ||
2198 | if (NumberOfBytesRead >= 37) | |
2199 | { | |
2200 | CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength); | |
2201 | ByteOffset38 = *(pSrc + CurrentOffset); | |
2202 | //End of Read | |
2203 | break; | |
2204 | } | |
2205 | return FALSE; | |
2206 | } | |
2207 | ||
2208 | // Check for DHCP & BOOTP protocol | |
2209 | if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) | |
2210 | { | |
2211 | // | |
2212 | // 2054 (hex 0806) for ARP datagrams | |
2213 | // if this packet is not ARP datagrams, then do nothing | |
2214 | // ARP datagrams will also be duplicate at 1mb broadcast frames | |
2215 | // | |
2216 | if (Protocol != 0x0806 ) | |
2217 | return FALSE; | |
2218 | } | |
2219 | ||
2220 | return TRUE; | |
2221 | } | |
2222 | ||
2223 | ||
2224 | BOOLEAN RTMPCheckEtherType( | |
2225 | IN PRTMP_ADAPTER pAd, | |
2226 | IN PNDIS_PACKET pPacket) | |
2227 | { | |
2228 | USHORT TypeLen; | |
2229 | UCHAR Byte0, Byte1; | |
2230 | PUCHAR pSrcBuf; | |
2231 | UINT32 pktLen; | |
2232 | UINT16 srcPort, dstPort; | |
2233 | BOOLEAN status = TRUE; | |
2234 | ||
2235 | ||
2236 | pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); | |
2237 | pktLen = GET_OS_PKT_LEN(pPacket); | |
2238 | ||
2239 | ASSERT(pSrcBuf); | |
2240 | ||
2241 | RTMP_SET_PACKET_SPECIFIC(pPacket, 0); | |
2242 | ||
2243 | // get Ethernet protocol field | |
2244 | TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13]; | |
2245 | ||
2246 | pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header. | |
2247 | ||
2248 | if (TypeLen <= 1500) | |
2249 | { // 802.3, 802.3 LLC | |
2250 | /* | |
2251 | DestMAC(6) + SrcMAC(6) + Lenght(2) + | |
2252 | DSAP(1) + SSAP(1) + Control(1) + | |
2253 | if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. | |
2254 | => + SNAP (5, OriginationID(3) + etherType(2)) | |
2255 | */ | |
2256 | if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03) | |
2257 | { | |
2258 | Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1); | |
2259 | RTMP_SET_PACKET_LLCSNAP(pPacket, 1); | |
2260 | TypeLen = (USHORT)((Byte0 << 8) + Byte1); | |
2261 | pSrcBuf += 8; // Skip this LLC/SNAP header | |
2262 | } | |
2263 | else | |
2264 | { | |
2265 | //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. | |
2266 | } | |
2267 | } | |
2268 | ||
2269 | // If it's a VLAN packet, get the real Type/Length field. | |
2270 | if (TypeLen == 0x8100) | |
2271 | { | |
2272 | /* 0x8100 means VLAN packets */ | |
2273 | ||
2274 | /* Dest. MAC Address (6-bytes) + | |
2275 | Source MAC Address (6-bytes) + | |
2276 | Length/Type = 802.1Q Tag Type (2-byte) + | |
2277 | Tag Control Information (2-bytes) + | |
2278 | Length / Type (2-bytes) + | |
2279 | data payload (0-n bytes) + | |
2280 | Pad (0-p bytes) + | |
2281 | Frame Check Sequence (4-bytes) */ | |
2282 | ||
2283 | RTMP_SET_PACKET_VLAN(pPacket, 1); | |
2284 | Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1); | |
2285 | TypeLen = (USHORT)((Byte0 << 8) + Byte1); | |
2286 | ||
2287 | pSrcBuf += 4; // Skip the VLAN Header. | |
2288 | } | |
2289 | ||
2290 | switch (TypeLen) | |
2291 | { | |
2292 | case 0x0800: | |
2293 | { | |
2294 | ASSERT((pktLen > 34)); | |
2295 | if (*(pSrcBuf + 9) == 0x11) | |
2296 | { // udp packet | |
2297 | ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header | |
2298 | ||
2299 | pSrcBuf += 20; // Skip the IP header | |
2300 | srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf)); | |
2301 | dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2))); | |
2302 | ||
2303 | if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44)) | |
2304 | { //It's a BOOTP/DHCP packet | |
2305 | RTMP_SET_PACKET_DHCP(pPacket, 1); | |
2306 | } | |
2307 | } | |
2308 | } | |
2309 | break; | |
2310 | case 0x0806: | |
2311 | { | |
2312 | //ARP Packet. | |
2313 | RTMP_SET_PACKET_DHCP(pPacket, 1); | |
2314 | } | |
2315 | break; | |
2316 | case 0x888e: | |
2317 | { | |
2318 | // EAPOL Packet. | |
2319 | RTMP_SET_PACKET_EAPOL(pPacket, 1); | |
2320 | } | |
2321 | break; | |
2322 | default: | |
2323 | status = FALSE; | |
2324 | break; | |
2325 | } | |
2326 | ||
2327 | return status; | |
2328 | ||
2329 | } | |
2330 | ||
2331 | ||
2332 | ||
2333 | VOID Update_Rssi_Sample( | |
2334 | IN PRTMP_ADAPTER pAd, | |
2335 | IN RSSI_SAMPLE *pRssi, | |
2336 | IN PRXWI_STRUC pRxWI) | |
2337 | { | |
2338 | CHAR rssi0 = pRxWI->RSSI0; | |
2339 | CHAR rssi1 = pRxWI->RSSI1; | |
2340 | CHAR rssi2 = pRxWI->RSSI2; | |
2341 | ||
2342 | if (rssi0 != 0) | |
2343 | { | |
2344 | pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0); | |
2345 | pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0; | |
2346 | pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3; | |
2347 | } | |
2348 | ||
2349 | if (rssi1 != 0) | |
2350 | { | |
2351 | pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1); | |
2352 | pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1; | |
2353 | pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3; | |
2354 | } | |
2355 | ||
2356 | if (rssi2 != 0) | |
2357 | { | |
2358 | pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2); | |
2359 | pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2; | |
2360 | pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3; | |
2361 | } | |
2362 | } | |
2363 | ||
2364 | ||
2365 | ||
2366 | // Normal legacy Rx packet indication | |
2367 | VOID Indicate_Legacy_Packet( | |
2368 | IN PRTMP_ADAPTER pAd, | |
2369 | IN RX_BLK *pRxBlk, | |
2370 | IN UCHAR FromWhichBSSID) | |
2371 | { | |
2372 | PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; | |
2373 | UCHAR Header802_3[LENGTH_802_3]; | |
2374 | ||
2375 | // 1. get 802.3 Header | |
2376 | // 2. remove LLC | |
2377 | // a. pointer pRxBlk->pData to payload | |
2378 | // b. modify pRxBlk->DataSize | |
2379 | #ifdef CONFIG_STA_SUPPORT | |
2380 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
2381 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); | |
2382 | #endif // CONFIG_STA_SUPPORT // | |
2383 | ||
2384 | if (pRxBlk->DataSize > MAX_RX_PKT_LEN) | |
2385 | { | |
2386 | // release packet | |
2387 | RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); | |
2388 | return; | |
2389 | } | |
2390 | ||
2391 | ||
2392 | STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); | |
2393 | ||
2394 | #ifdef RT2870 | |
2395 | #ifdef DOT11_N_SUPPORT | |
2396 | if (pAd->CommonCfg.bDisableReordering == 0) | |
2397 | { | |
2398 | PBA_REC_ENTRY pBAEntry; | |
2399 | ULONG Now32; | |
2400 | UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID; | |
2401 | UCHAR TID = pRxBlk->pRxWI->TID; | |
2402 | USHORT Idx; | |
2403 | ||
2404 | #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms | |
2405 | ||
2406 | if (Wcid < MAX_LEN_OF_MAC_TABLE) | |
2407 | { | |
2408 | Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; | |
2409 | if (Idx != 0) | |
2410 | { | |
2411 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | |
2412 | // update last rx time | |
2413 | NdisGetSystemUpTime(&Now32); | |
2414 | if ((pBAEntry->list.qlen > 0) && | |
2415 | RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT))) | |
2416 | ) | |
2417 | { | |
2418 | printk("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU); | |
2419 | hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64); | |
2420 | ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); | |
2421 | } | |
2422 | } | |
2423 | } | |
2424 | } | |
2425 | #endif // DOT11_N_SUPPORT // | |
2426 | #endif // RT2870 // | |
2427 | ||
2428 | wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); | |
2429 | ||
2430 | // | |
2431 | // pass this 802.3 packet to upper layer or forward this packet to WM directly | |
2432 | // | |
2433 | #ifdef CONFIG_STA_SUPPORT | |
2434 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
2435 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); | |
2436 | #endif // CONFIG_STA_SUPPORT // | |
2437 | ||
2438 | } | |
2439 | ||
2440 | ||
2441 | // Normal, AMPDU or AMSDU | |
2442 | VOID CmmRxnonRalinkFrameIndicate( | |
2443 | IN PRTMP_ADAPTER pAd, | |
2444 | IN RX_BLK *pRxBlk, | |
2445 | IN UCHAR FromWhichBSSID) | |
2446 | { | |
2447 | #ifdef DOT11_N_SUPPORT | |
2448 | if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) | |
2449 | { | |
2450 | Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); | |
2451 | } | |
2452 | else | |
2453 | #endif // DOT11_N_SUPPORT // | |
2454 | { | |
2455 | #ifdef DOT11_N_SUPPORT | |
2456 | if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) | |
2457 | { | |
2458 | // handle A-MSDU | |
2459 | Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); | |
2460 | } | |
2461 | else | |
2462 | #endif // DOT11_N_SUPPORT // | |
2463 | { | |
2464 | Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); | |
2465 | } | |
2466 | } | |
2467 | } | |
2468 | ||
2469 | ||
2470 | VOID CmmRxRalinkFrameIndicate( | |
2471 | IN PRTMP_ADAPTER pAd, | |
2472 | IN MAC_TABLE_ENTRY *pEntry, | |
2473 | IN RX_BLK *pRxBlk, | |
2474 | IN UCHAR FromWhichBSSID) | |
2475 | { | |
2476 | UCHAR Header802_3[LENGTH_802_3]; | |
2477 | UINT16 Msdu2Size; | |
2478 | UINT16 Payload1Size, Payload2Size; | |
2479 | PUCHAR pData2; | |
2480 | PNDIS_PACKET pPacket2 = NULL; | |
2481 | ||
2482 | ||
2483 | ||
2484 | Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8); | |
2485 | ||
2486 | if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) | |
2487 | { | |
2488 | /* skip two byte MSDU2 len */ | |
2489 | pRxBlk->pData += 2; | |
2490 | pRxBlk->DataSize -= 2; | |
2491 | } | |
2492 | else | |
2493 | { | |
2494 | // release packet | |
2495 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); | |
2496 | return; | |
2497 | } | |
2498 | ||
2499 | // get 802.3 Header and remove LLC | |
2500 | #ifdef CONFIG_STA_SUPPORT | |
2501 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
2502 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); | |
2503 | #endif // CONFIG_STA_SUPPORT // | |
2504 | ||
2505 | ||
2506 | ASSERT(pRxBlk->pRxPacket); | |
2507 | ||
2508 | // Ralink Aggregation frame | |
2509 | pAd->RalinkCounters.OneSecRxAggregationCount ++; | |
2510 | Payload1Size = pRxBlk->DataSize - Msdu2Size; | |
2511 | Payload2Size = Msdu2Size - LENGTH_802_3; | |
2512 | ||
2513 | pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3; | |
2514 | #ifdef CONFIG_STA_SUPPORT | |
2515 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
2516 | pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID); | |
2517 | #endif // CONFIG_STA_SUPPORT // | |
2518 | ||
2519 | if (!pPacket2) | |
2520 | { | |
2521 | // release packet | |
2522 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); | |
2523 | return; | |
2524 | } | |
2525 | ||
2526 | // update payload size of 1st packet | |
2527 | pRxBlk->DataSize = Payload1Size; | |
2528 | wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); | |
2529 | ||
2530 | #ifdef CONFIG_STA_SUPPORT | |
2531 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
2532 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); | |
2533 | #endif // CONFIG_STA_SUPPORT // | |
2534 | ||
2535 | if (pPacket2) | |
2536 | { | |
2537 | #ifdef CONFIG_STA_SUPPORT | |
2538 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
2539 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); | |
2540 | #endif // CONFIG_STA_SUPPORT // | |
2541 | } | |
2542 | } | |
2543 | ||
2544 | ||
2545 | #define RESET_FRAGFRAME(_fragFrame) \ | |
2546 | { \ | |
2547 | _fragFrame.RxSize = 0; \ | |
2548 | _fragFrame.Sequence = 0; \ | |
2549 | _fragFrame.LastFrag = 0; \ | |
2550 | _fragFrame.Flags = 0; \ | |
2551 | } | |
2552 | ||
2553 | ||
2554 | PNDIS_PACKET RTMPDeFragmentDataFrame( | |
2555 | IN PRTMP_ADAPTER pAd, | |
2556 | IN RX_BLK *pRxBlk) | |
2557 | { | |
2558 | PHEADER_802_11 pHeader = pRxBlk->pHeader; | |
2559 | PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; | |
2560 | UCHAR *pData = pRxBlk->pData; | |
2561 | USHORT DataSize = pRxBlk->DataSize; | |
2562 | PNDIS_PACKET pRetPacket = NULL; | |
2563 | UCHAR *pFragBuffer = NULL; | |
2564 | BOOLEAN bReassDone = FALSE; | |
2565 | UCHAR HeaderRoom = 0; | |
2566 | ||
2567 | ||
2568 | ASSERT(pHeader); | |
2569 | ||
2570 | HeaderRoom = pData - (UCHAR *)pHeader; | |
2571 | ||
2572 | // Re-assemble the fragmented packets | |
2573 | if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt | |
2574 | { | |
2575 | // the first pkt of fragment, record it. | |
2576 | if (pHeader->FC.MoreFrag) | |
2577 | { | |
2578 | ASSERT(pAd->FragFrame.pFragPacket); | |
2579 | pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); | |
2580 | pAd->FragFrame.RxSize = DataSize + HeaderRoom; | |
2581 | NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize); | |
2582 | pAd->FragFrame.Sequence = pHeader->Sequence; | |
2583 | pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0 | |
2584 | ASSERT(pAd->FragFrame.LastFrag == 0); | |
2585 | goto done; // end of processing this frame | |
2586 | } | |
2587 | } | |
2588 | else //Middle & End of fragment | |
2589 | { | |
2590 | if ((pHeader->Sequence != pAd->FragFrame.Sequence) || | |
2591 | (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) | |
2592 | { | |
2593 | // Fragment is not the same sequence or out of fragment number order | |
2594 | // Reset Fragment control blk | |
2595 | RESET_FRAGFRAME(pAd->FragFrame); | |
2596 | DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n")); | |
2597 | goto done; // give up this frame | |
2598 | } | |
2599 | else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) | |
2600 | { | |
2601 | // Fragment frame is too large, it exeeds the maximum frame size. | |
2602 | // Reset Fragment control blk | |
2603 | RESET_FRAGFRAME(pAd->FragFrame); | |
2604 | DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n")); | |
2605 | goto done; // give up this frame | |
2606 | } | |
2607 | ||
2608 | // | |
2609 | // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. | |
2610 | // In this case, we will dropt it. | |
2611 | // | |
2612 | if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) | |
2613 | { | |
2614 | DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag)); | |
2615 | goto done; // give up this frame | |
2616 | } | |
2617 | ||
2618 | pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); | |
2619 | ||
2620 | // concatenate this fragment into the re-assembly buffer | |
2621 | NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize); | |
2622 | pAd->FragFrame.RxSize += DataSize; | |
2623 | pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number | |
2624 | ||
2625 | // Last fragment | |
2626 | if (pHeader->FC.MoreFrag == FALSE) | |
2627 | { | |
2628 | bReassDone = TRUE; | |
2629 | } | |
2630 | } | |
2631 | ||
2632 | done: | |
2633 | // always release rx fragmented packet | |
2634 | RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); | |
2635 | ||
2636 | // return defragmented packet if packet is reassembled completely | |
2637 | // otherwise return NULL | |
2638 | if (bReassDone) | |
2639 | { | |
2640 | PNDIS_PACKET pNewFragPacket; | |
2641 | ||
2642 | // allocate a new packet buffer for fragment | |
2643 | pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); | |
2644 | if (pNewFragPacket) | |
2645 | { | |
2646 | // update RxBlk | |
2647 | pRetPacket = pAd->FragFrame.pFragPacket; | |
2648 | pAd->FragFrame.pFragPacket = pNewFragPacket; | |
2649 | pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket); | |
2650 | pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom; | |
2651 | pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom; | |
2652 | pRxBlk->pRxPacket = pRetPacket; | |
2653 | } | |
2654 | else | |
2655 | { | |
2656 | RESET_FRAGFRAME(pAd->FragFrame); | |
2657 | } | |
2658 | } | |
2659 | ||
2660 | return pRetPacket; | |
2661 | } | |
2662 | ||
2663 | ||
2664 | VOID Indicate_AMSDU_Packet( | |
2665 | IN PRTMP_ADAPTER pAd, | |
2666 | IN RX_BLK *pRxBlk, | |
2667 | IN UCHAR FromWhichBSSID) | |
2668 | { | |
2669 | UINT nMSDU; | |
2670 | ||
2671 | update_os_packet_info(pAd, pRxBlk, FromWhichBSSID); | |
2672 | RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); | |
2673 | nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize); | |
2674 | } | |
2675 | ||
2676 | VOID Indicate_EAPOL_Packet( | |
2677 | IN PRTMP_ADAPTER pAd, | |
2678 | IN RX_BLK *pRxBlk, | |
2679 | IN UCHAR FromWhichBSSID) | |
2680 | { | |
2681 | MAC_TABLE_ENTRY *pEntry = NULL; | |
2682 | ||
2683 | ||
2684 | #ifdef CONFIG_STA_SUPPORT | |
2685 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
2686 | { | |
2687 | pEntry = &pAd->MacTab.Content[BSSID_WCID]; | |
2688 | STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); | |
2689 | return; | |
2690 | } | |
2691 | #endif // CONFIG_STA_SUPPORT // | |
2692 | ||
2693 | if (pEntry == NULL) | |
2694 | { | |
2695 | DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); | |
2696 | // release packet | |
2697 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); | |
2698 | return; | |
2699 | } | |
2700 | } | |
2701 | ||
2702 | #define BCN_TBTT_OFFSET 64 //defer 64 us | |
2703 | VOID ReSyncBeaconTime( | |
2704 | IN PRTMP_ADAPTER pAd) | |
2705 | { | |
2706 | ||
2707 | UINT32 Offset; | |
2708 | ||
2709 | ||
2710 | Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET); | |
2711 | ||
2712 | pAd->TbttTickCount++; | |
2713 | ||
2714 | // | |
2715 | // The updated BeaconInterval Value will affect Beacon Interval after two TBTT | |
2716 | // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER | |
2717 | // | |
2718 | if (Offset == (BCN_TBTT_OFFSET-2)) | |
2719 | { | |
2720 | BCN_TIME_CFG_STRUC csr; | |
2721 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | |
2722 | csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us | |
2723 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); | |
2724 | } | |
2725 | else | |
2726 | { | |
2727 | if (Offset == (BCN_TBTT_OFFSET-1)) | |
2728 | { | |
2729 | BCN_TIME_CFG_STRUC csr; | |
2730 | ||
2731 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | |
2732 | csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU | |
2733 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); | |
2734 | } | |
2735 | } | |
2736 | } | |
2737 |