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 Module Name:
28 rtmp_data.c
29
30 Abstract:
31 Data path subroutines
32
33 Revision History:
34 Who When What
35 -------- ---------- ----------------------------------------------
36 John Aug/17/04 major modification for RT2561/2661
37 Jan Lee Mar/17/06 major modification for RT2860 New Ring Design
38 */
39 #include "../rt_config.h"
40
41
STARxEAPOLFrameIndicate(IN PRTMP_ADAPTER pAd,IN MAC_TABLE_ENTRY * pEntry,IN RX_BLK * pRxBlk,IN UCHAR FromWhichBSSID)42 VOID STARxEAPOLFrameIndicate(
43 IN PRTMP_ADAPTER pAd,
44 IN MAC_TABLE_ENTRY *pEntry,
45 IN RX_BLK *pRxBlk,
46 IN UCHAR FromWhichBSSID)
47 {
48 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
49 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
50 UCHAR *pTmpBuf;
51
52 #ifdef WPA_SUPPLICANT_SUPPORT
53 if (pAd->StaCfg.WpaSupplicantUP)
54 {
55 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
56 // TBD : process fragmented EAPol frames
57 {
58 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
59 if ( pAd->StaCfg.IEEE8021X == TRUE &&
60 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
61 {
62 PUCHAR Key;
63 UCHAR CipherAlg;
64 int idx = 0;
65
66 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
67 //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
68 STA_PORT_SECURED(pAd);
69
70 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
71 {
72 idx = pAd->StaCfg.DesireSharedKeyId;
73 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
74 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
75
76 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
77 {
78 #ifdef RT2870
79 union
80 {
81 char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
82 NDIS_802_11_WEP keyinfo;
83 } WepKey;
84 int len;
85
86
87 NdisZeroMemory(&WepKey, sizeof(WepKey));
88 len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
89
90 NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
91 pAd->StaCfg.DesireSharedKey[idx].Key,
92 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
93
94 WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
95 WepKey.keyinfo.KeyLength = len;
96 pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
97
98 pAd->IndicateMediaState = NdisMediaStateConnected;
99 pAd->ExtraInfo = GENERAL_LINK_UP;
100 // need to enqueue cmd to thread
101 RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
102 #endif // RT2870 //
103 // For Preventing ShardKey Table is cleared by remove key procedure.
104 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
105 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
106 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
107 pAd->StaCfg.DesireSharedKey[idx].Key,
108 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
109 }
110 }
111 }
112
113 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
114 return;
115 }
116 }
117 else
118 #endif // WPA_SUPPLICANT_SUPPORT //
119 {
120 // Special DATA frame that has to pass to MLME
121 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
122 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
123 {
124 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
125 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
126 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
127 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
128 }
129 }
130
131 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
132 return;
133
134 }
135
STARxDataFrameAnnounce(IN PRTMP_ADAPTER pAd,IN MAC_TABLE_ENTRY * pEntry,IN RX_BLK * pRxBlk,IN UCHAR FromWhichBSSID)136 VOID STARxDataFrameAnnounce(
137 IN PRTMP_ADAPTER pAd,
138 IN MAC_TABLE_ENTRY *pEntry,
139 IN RX_BLK *pRxBlk,
140 IN UCHAR FromWhichBSSID)
141 {
142
143 // non-EAP frame
144 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
145 {
146 {
147 // drop all non-EAP DATA frame before
148 // this client's Port-Access-Control is secured
149 if (pRxBlk->pHeader->FC.Wep)
150 {
151 // unsupported cipher suite
152 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
153 {
154 // release packet
155 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
156 return;
157 }
158 }
159 else
160 {
161 // encryption in-use but receive a non-EAPOL clear text frame, drop it
162 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
163 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
164 {
165 // release packet
166 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
167 return;
168 }
169 }
170 }
171 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
172 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
173 {
174 // Normal legacy, AMPDU or AMSDU
175 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
176
177 }
178 else
179 {
180 // ARALINK
181 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
182 }
183 #ifdef QOS_DLS_SUPPORT
184 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS);
185 #endif // QOS_DLS_SUPPORT //
186 }
187 else
188 {
189 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
190 #ifdef DOT11_N_SUPPORT
191 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
192 {
193 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
194 }
195 else
196 #endif // DOT11_N_SUPPORT //
197 {
198 // Determin the destination of the EAP frame
199 // to WPA state machine or upper layer
200 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
201 }
202 }
203 }
204
205
206 // For TKIP frame, calculate the MIC value
STACheckTkipMICValue(IN PRTMP_ADAPTER pAd,IN MAC_TABLE_ENTRY * pEntry,IN RX_BLK * pRxBlk)207 BOOLEAN STACheckTkipMICValue(
208 IN PRTMP_ADAPTER pAd,
209 IN MAC_TABLE_ENTRY *pEntry,
210 IN RX_BLK *pRxBlk)
211 {
212 PHEADER_802_11 pHeader = pRxBlk->pHeader;
213 UCHAR *pData = pRxBlk->pData;
214 USHORT DataSize = pRxBlk->DataSize;
215 UCHAR UserPriority = pRxBlk->UserPriority;
216 PCIPHER_KEY pWpaKey;
217 UCHAR *pDA, *pSA;
218
219 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
220
221 pDA = pHeader->Addr1;
222 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
223 {
224 pSA = pHeader->Addr3;
225 }
226 else
227 {
228 pSA = pHeader->Addr2;
229 }
230
231 if (RTMPTkipCompareMICValue(pAd,
232 pData,
233 pDA,
234 pSA,
235 pWpaKey->RxMic,
236 UserPriority,
237 DataSize) == FALSE)
238 {
239 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
240
241 #ifdef WPA_SUPPLICANT_SUPPORT
242 if (pAd->StaCfg.WpaSupplicantUP)
243 {
244 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
245 }
246 else
247 #endif // WPA_SUPPLICANT_SUPPORT //
248 {
249 RTMPReportMicError(pAd, pWpaKey);
250 }
251
252 // release packet
253 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
254 return FALSE;
255 }
256
257 return TRUE;
258 }
259
260
261 //
262 // All Rx routines use RX_BLK structure to hande rx events
263 // It is very important to build pRxBlk attributes
264 // 1. pHeader pointer to 802.11 Header
265 // 2. pData pointer to payload including LLC (just skip Header)
266 // 3. set payload size including LLC to DataSize
267 // 4. set some flags with RX_BLK_SET_FLAG()
268 //
STAHandleRxDataFrame(IN PRTMP_ADAPTER pAd,IN RX_BLK * pRxBlk)269 VOID STAHandleRxDataFrame(
270 IN PRTMP_ADAPTER pAd,
271 IN RX_BLK *pRxBlk)
272 {
273 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
274 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
275 PHEADER_802_11 pHeader = pRxBlk->pHeader;
276 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
277 BOOLEAN bFragment = FALSE;
278 MAC_TABLE_ENTRY *pEntry = NULL;
279 UCHAR FromWhichBSSID = BSS0;
280 UCHAR UserPriority = 0;
281
282 {
283 // before LINK UP, all DATA frames are rejected
284 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
285 {
286 // release packet
287 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
288 return;
289 }
290
291 #ifdef QOS_DLS_SUPPORT
292 //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
293 if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD))
294 {
295 return;
296 }
297 #endif // QOS_DLS_SUPPORT //
298
299 // Drop not my BSS frames
300 if (pRxD->MyBss == 0)
301 {
302 {
303 // release packet
304 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
305 return;
306 }
307 }
308
309 pAd->RalinkCounters.RxCountSinceLastNULL++;
310 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
311 {
312 UCHAR *pData;
313 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
314
315 // Qos bit 4
316 pData = (PUCHAR)pHeader + LENGTH_802_11;
317 if ((*pData >> 4) & 0x01)
318 {
319 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
320 pAd->CommonCfg.bInServicePeriod = FALSE;
321
322 // Force driver to fall into sleep mode when rcv EOSP frame
323 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
324 {
325 USHORT TbttNumToNextWakeUp;
326 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
327 ULONG Now;
328
329 NdisGetSystemUpTime(&Now);
330 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
331
332 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
333 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
334 TbttNumToNextWakeUp = NextDtim;
335
336 MlmeSetPsmBit(pAd, PWR_SAVE);
337 // if WMM-APSD is failed, try to disable following line
338 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
339 }
340 }
341
342 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
343 {
344 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
345 }
346 }
347
348 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
349 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
350 {
351 // release packet
352 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
353 return;
354 }
355
356 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
357 #ifdef QOS_DLS_SUPPORT
358 if (!pAd->CommonCfg.bDLSCapable)
359 {
360 #endif // QOS_DLS_SUPPORT //
361 if (INFRA_ON(pAd))
362 {
363 // Infrastructure mode, check address 2 for BSSID
364 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
365 {
366 // Receive frame not my BSSID
367 // release packet
368 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
369 return;
370 }
371 }
372 else // Ad-Hoc mode or Not associated
373 {
374 // Ad-Hoc mode, check address 3 for BSSID
375 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
376 {
377 // Receive frame not my BSSID
378 // release packet
379 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
380 return;
381 }
382 }
383 #ifdef QOS_DLS_SUPPORT
384 }
385 #endif // QOS_DLS_SUPPORT //
386
387 //
388 // find pEntry
389 //
390 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
391 {
392 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
393 }
394 else
395 {
396 // 1. release packet if infra mode
397 // 2. new a pEntry if ad-hoc mode
398 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
399 return;
400 }
401
402 // infra or ad-hoc
403 if (INFRA_ON(pAd))
404 {
405 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
406 #ifdef QOS_DLS_SUPPORT
407 if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
408 RX_BLK_SET_FLAG(pRxBlk, fRX_DLS);
409 else
410 #endif // QOS_DLS_SUPPORT //
411 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
412 }
413
414 // check Atheros Client
415 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
416 {
417 pEntry->bIAmBadAtheros = TRUE;
418 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
419 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
420 if (!STA_AES_ON(pAd))
421 {
422 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
423 }
424 }
425 }
426
427 pRxBlk->pData = (UCHAR *)pHeader;
428
429 //
430 // update RxBlk->pData, DataSize
431 // 802.11 Header, QOS, HTC, Hw Padding
432 //
433
434 // 1. skip 802.11 HEADER
435 {
436 pRxBlk->pData += LENGTH_802_11;
437 pRxBlk->DataSize -= LENGTH_802_11;
438 }
439
440 // 2. QOS
441 if (pHeader->FC.SubType & 0x08)
442 {
443 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
444 UserPriority = *(pRxBlk->pData) & 0x0f;
445 // bit 7 in QoS Control field signals the HT A-MSDU format
446 if ((*pRxBlk->pData) & 0x80)
447 {
448 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
449 }
450
451 // skip QOS contorl field
452 pRxBlk->pData += 2;
453 pRxBlk->DataSize -=2;
454 }
455 pRxBlk->UserPriority = UserPriority;
456
457 // 3. Order bit: A-Ralink or HTC+
458 if (pHeader->FC.Order)
459 {
460 #ifdef AGGREGATION_SUPPORT
461 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
462 {
463 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
464 }
465 else
466 #endif
467 {
468 #ifdef DOT11_N_SUPPORT
469 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
470 // skip HTC contorl field
471 pRxBlk->pData += 4;
472 pRxBlk->DataSize -= 4;
473 #endif // DOT11_N_SUPPORT //
474 }
475 }
476
477 // 4. skip HW padding
478 if (pRxD->L2PAD)
479 {
480 // just move pData pointer
481 // because DataSize excluding HW padding
482 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
483 pRxBlk->pData += 2;
484 }
485
486 #ifdef DOT11_N_SUPPORT
487 if (pRxD->BA)
488 {
489 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
490 }
491 #endif // DOT11_N_SUPPORT //
492
493
494 //
495 // Case I Process Broadcast & Multicast data frame
496 //
497 if (pRxD->Bcast || pRxD->Mcast)
498 {
499 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
500
501 // Drop Mcast/Bcast frame with fragment bit on
502 if (pHeader->FC.MoreFrag)
503 {
504 // release packet
505 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
506 return;
507 }
508
509 // Filter out Bcast frame which AP relayed for us
510 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
511 {
512 // release packet
513 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
514 return;
515 }
516
517 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
518 return;
519 }
520 else if (pRxD->U2M)
521 {
522 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
523
524
525 #ifdef QOS_DLS_SUPPORT
526 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS))
527 {
528 MAC_TABLE_ENTRY *pDlsEntry = NULL;
529
530 pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE);
531 if(pDlsEntry)
532 Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI);
533 }
534 else
535 #endif // QOS_DLS_SUPPORT //
536 if (ADHOC_ON(pAd))
537 {
538 pEntry = MacTableLookup(pAd, pHeader->Addr2);
539 if (pEntry)
540 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
541 }
542
543
544 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
545
546 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
547 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
548
549 pAd->RalinkCounters.OneSecRxOkDataCnt++;
550
551
552 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
553 {
554 // re-assemble the fragmented packets
555 // return complete frame (pRxPacket) or NULL
556 bFragment = TRUE;
557 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
558 }
559
560 if (pRxPacket)
561 {
562 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
563
564 // process complete frame
565 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
566 {
567 // Minus MIC length
568 pRxBlk->DataSize -= 8;
569
570 // For TKIP frame, calculate the MIC value
571 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
572 {
573 return;
574 }
575 }
576
577 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
578 return;
579 }
580 else
581 {
582 // just return
583 // because RTMPDeFragmentDataFrame() will release rx packet,
584 // if packet is fragmented
585 return;
586 }
587 }
588
589 ASSERT(0);
590 // release packet
591 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
592 }
593
STAHandleRxMgmtFrame(IN PRTMP_ADAPTER pAd,IN RX_BLK * pRxBlk)594 VOID STAHandleRxMgmtFrame(
595 IN PRTMP_ADAPTER pAd,
596 IN RX_BLK *pRxBlk)
597 {
598 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
599 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
600 PHEADER_802_11 pHeader = pRxBlk->pHeader;
601 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
602
603 do
604 {
605
606 // We should collect RSSI not only U2M data but also my beacon
607 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
608 {
609 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
610
611 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
612 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
613 }
614
615 // First check the size, it MUST not exceed the mlme queue size
616 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
617 {
618 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
619 break;
620 }
621
622 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
623 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
624 } while (FALSE);
625
626 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
627 }
628
STAHandleRxControlFrame(IN PRTMP_ADAPTER pAd,IN RX_BLK * pRxBlk)629 VOID STAHandleRxControlFrame(
630 IN PRTMP_ADAPTER pAd,
631 IN RX_BLK *pRxBlk)
632 {
633 #ifdef DOT11_N_SUPPORT
634 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
635 #endif // DOT11_N_SUPPORT //
636 PHEADER_802_11 pHeader = pRxBlk->pHeader;
637 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
638
639 switch (pHeader->FC.SubType)
640 {
641 case SUBTYPE_BLOCK_ACK_REQ:
642 #ifdef DOT11_N_SUPPORT
643 {
644 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
645 }
646 break;
647 #endif // DOT11_N_SUPPORT //
648 case SUBTYPE_BLOCK_ACK:
649 case SUBTYPE_ACK:
650 default:
651 break;
652 }
653
654 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
655 }
656
657
658 /*
659 ========================================================================
660
661 Routine Description:
662 Process RxDone interrupt, running in DPC level
663
664 Arguments:
665 pAd Pointer to our adapter
666
667 Return Value:
668 None
669
670 IRQL = DISPATCH_LEVEL
671
672 Note:
673 This routine has to maintain Rx ring read pointer.
674 Need to consider QOS DATA format when converting to 802.3
675 ========================================================================
676 */
STARxDoneInterruptHandle(IN PRTMP_ADAPTER pAd,IN BOOLEAN argc)677 BOOLEAN STARxDoneInterruptHandle(
678 IN PRTMP_ADAPTER pAd,
679 IN BOOLEAN argc)
680 {
681 NDIS_STATUS Status;
682 UINT32 RxProcessed, RxPending;
683 BOOLEAN bReschedule = FALSE;
684 RT28XX_RXD_STRUC *pRxD;
685 UCHAR *pData;
686 PRXWI_STRUC pRxWI;
687 PNDIS_PACKET pRxPacket;
688 PHEADER_802_11 pHeader;
689 RX_BLK RxCell;
690
691 RxProcessed = RxPending = 0;
692
693 // process whole rx ring
694 while (1)
695 {
696
697 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
698 fRTMP_ADAPTER_RESET_IN_PROGRESS |
699 fRTMP_ADAPTER_HALT_IN_PROGRESS |
700 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
701 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
702 {
703 break;
704 }
705
706
707 RxProcessed ++; // test
708
709 // 1. allocate a new data packet into rx ring to replace received packet
710 // then processing the received packet
711 // 2. the callee must take charge of release of packet
712 // 3. As far as driver is concerned ,
713 // the rx packet must
714 // a. be indicated to upper layer or
715 // b. be released if it is discarded
716 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
717 if (pRxPacket == NULL)
718 {
719 // no more packet to process
720 break;
721 }
722
723 // get rx ring descriptor
724 pRxD = &(RxCell.RxD);
725 // get rx data buffer
726 pData = GET_OS_PKT_DATAPTR(pRxPacket);
727 pRxWI = (PRXWI_STRUC) pData;
728 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
729
730 #ifdef RT_BIG_ENDIAN
731 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE);
732 RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI);
733 #endif
734
735 // build RxCell
736 RxCell.pRxWI = pRxWI;
737 RxCell.pHeader = pHeader;
738 RxCell.pRxPacket = pRxPacket;
739 RxCell.pData = (UCHAR *) pHeader;
740 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
741 RxCell.Flags = 0;
742
743 // Increase Total receive byte counter after real data received no mater any error or not
744 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
745 pAd->RalinkCounters.RxCount ++;
746
747 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
748
749 if (pRxWI->MPDUtotalByteCount < 14)
750 Status = NDIS_STATUS_FAILURE;
751
752 if (MONITOR_ON(pAd))
753 {
754 send_monitor_packets(pAd, &RxCell);
755 break;
756 }
757 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
758 #ifdef RALINK_ATE
759 if (ATE_ON(pAd))
760 {
761 pAd->ate.RxCntPerSec++;
762 ATESampleRssi(pAd, pRxWI);
763 #ifdef RALINK_28xx_QA
764 if (pAd->ate.bQARxStart == TRUE)
765 {
766 /* (*pRxD) has been swapped in GetPacketFromRxRing() */
767 ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader);
768 }
769 #endif // RALINK_28xx_QA //
770 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
771 continue;
772 }
773 #endif // RALINK_ATE //
774
775 // Check for all RxD errors
776 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
777
778 // Handle the received frame
779 if (Status == NDIS_STATUS_SUCCESS)
780 {
781 switch (pHeader->FC.Type)
782 {
783 // CASE I, receive a DATA frame
784 case BTYPE_DATA:
785 {
786 // process DATA frame
787 STAHandleRxDataFrame(pAd, &RxCell);
788 }
789 break;
790 // CASE II, receive a MGMT frame
791 case BTYPE_MGMT:
792 {
793 STAHandleRxMgmtFrame(pAd, &RxCell);
794 }
795 break;
796 // CASE III. receive a CNTL frame
797 case BTYPE_CNTL:
798 {
799 STAHandleRxControlFrame(pAd, &RxCell);
800 }
801 break;
802 // discard other type
803 default:
804 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
805 break;
806 }
807 }
808 else
809 {
810 pAd->Counters8023.RxErrors++;
811 // discard this frame
812 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
813 }
814 }
815
816 return bReschedule;
817 }
818
819 /*
820 ========================================================================
821
822 Routine Description:
823 Arguments:
824 pAd Pointer to our adapter
825
826 IRQL = DISPATCH_LEVEL
827
828 ========================================================================
829 */
RTMPHandleTwakeupInterrupt(IN PRTMP_ADAPTER pAd)830 VOID RTMPHandleTwakeupInterrupt(
831 IN PRTMP_ADAPTER pAd)
832 {
833 AsicForceWakeup(pAd, FALSE);
834 }
835
836 /*
837 ========================================================================
838 Routine Description:
839 Early checking and OS-depened parsing for Tx packet send to our STA driver.
840
841 Arguments:
842 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
843 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
844 UINT NumberOfPackets Number of packet in packet array.
845
846 Return Value:
847 NONE
848
849 Note:
850 This function do early checking and classification for send-out packet.
851 You only can put OS-depened & STA related code in here.
852 ========================================================================
853 */
STASendPackets(IN NDIS_HANDLE MiniportAdapterContext,IN PPNDIS_PACKET ppPacketArray,IN UINT NumberOfPackets)854 VOID STASendPackets(
855 IN NDIS_HANDLE MiniportAdapterContext,
856 IN PPNDIS_PACKET ppPacketArray,
857 IN UINT NumberOfPackets)
858 {
859 UINT Index;
860 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
861 PNDIS_PACKET pPacket;
862 BOOLEAN allowToSend = FALSE;
863
864
865 for (Index = 0; Index < NumberOfPackets; Index++)
866 {
867 pPacket = ppPacketArray[Index];
868
869 do
870 {
871 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
872 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
873 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
874 {
875 // Drop send request since hardware is in reset state
876 break;
877 }
878 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
879 {
880 // Drop send request since there are no physical connection yet
881 break;
882 }
883 else
884 {
885 // Record that orignal packet source is from NDIS layer,so that
886 // later on driver knows how to release this NDIS PACKET
887 #ifdef QOS_DLS_SUPPORT
888 MAC_TABLE_ENTRY *pEntry;
889 PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
890
891 pEntry = MacTableLookup(pAd, pSrcBufVA);
892 if (pEntry && (pEntry->ValidAsDls == TRUE))
893 {
894 RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
895 }
896 else
897 #endif // QOS_DLS_SUPPORT //
898 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
899 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
900 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
901 pAd->RalinkCounters.PendingNdisPacketCount++;
902
903 allowToSend = TRUE;
904 }
905 } while(FALSE);
906
907 if (allowToSend == TRUE)
908 STASendPacket(pAd, pPacket);
909 else
910 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
911 }
912
913 // Dequeue outgoing frames from TxSwQueue[] and process it
914 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
915
916 }
917
918
919 /*
920 ========================================================================
921 Routine Description:
922 This routine is used to do packet parsing and classification for Tx packet
923 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
924 class.
925
926 Arguments:
927 pAd Pointer to our adapter
928 pPacket Pointer to send packet
929
930 Return Value:
931 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
932 NDIS_STATUS_FAILURE If failed to do en-queue.
933
934 Note:
935 You only can put OS-indepened & STA related code in here.
936 ========================================================================
937 */
STASendPacket(IN PRTMP_ADAPTER pAd,IN PNDIS_PACKET pPacket)938 NDIS_STATUS STASendPacket(
939 IN PRTMP_ADAPTER pAd,
940 IN PNDIS_PACKET pPacket)
941 {
942 PACKET_INFO PacketInfo;
943 PUCHAR pSrcBufVA;
944 UINT SrcBufLen;
945 UINT AllowFragSize;
946 UCHAR NumberOfFrag;
947 // UCHAR RTSRequired;
948 UCHAR QueIdx, UserPriority;
949 MAC_TABLE_ENTRY *pEntry = NULL;
950 unsigned int IrqFlags;
951 UCHAR FlgIsIP = 0;
952 UCHAR Rate;
953
954 // Prepare packet information structure for buffer descriptor
955 // chained within a single NDIS packet.
956 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
957
958 if (pSrcBufVA == NULL)
959 {
960 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
961 // Resourece is low, system did not allocate virtual address
962 // return NDIS_STATUS_FAILURE directly to upper layer
963 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
964 return NDIS_STATUS_FAILURE;
965 }
966
967
968 if (SrcBufLen < 14)
969 {
970 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
971 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
972 return (NDIS_STATUS_FAILURE);
973 }
974
975 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
976 // Note multicast packets in adhoc also use BSSID_WCID index.
977 {
978 if(INFRA_ON(pAd))
979 {
980 #ifdef QOS_DLS_SUPPORT
981 USHORT tmpWcid;
982
983 tmpWcid = RTMP_GET_PACKET_WCID(pPacket);
984 if (VALID_WCID(tmpWcid) &&
985 (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE))
986 {
987 pEntry = &pAd->MacTab.Content[tmpWcid];
988 Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate;
989 }
990 else
991 #endif // QOS_DLS_SUPPORT //
992 {
993 pEntry = &pAd->MacTab.Content[BSSID_WCID];
994 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
995 Rate = pAd->CommonCfg.TxRate;
996 }
997 }
998 else if (ADHOC_ON(pAd))
999 {
1000 if (*pSrcBufVA & 0x01)
1001 {
1002 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
1003 pEntry = &pAd->MacTab.Content[MCAST_WCID];
1004 }
1005 else
1006 {
1007 pEntry = MacTableLookup(pAd, pSrcBufVA);
1008 }
1009 Rate = pAd->CommonCfg.TxRate;
1010 }
1011 }
1012
1013 if (!pEntry)
1014 {
1015 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
1016 // Resourece is low, system did not allocate virtual address
1017 // return NDIS_STATUS_FAILURE directly to upper layer
1018 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1019 return NDIS_STATUS_FAILURE;
1020 }
1021
1022 if (ADHOC_ON(pAd)
1023 )
1024 {
1025 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
1026 }
1027
1028 //
1029 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
1030 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
1031 RTMPCheckEtherType(pAd, pPacket);
1032
1033
1034
1035 //
1036 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
1037 //
1038 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1039 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1040 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1041 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1042 #ifdef WPA_SUPPLICANT_SUPPORT
1043 || (pAd->StaCfg.IEEE8021X == TRUE)
1044 #endif // WPA_SUPPLICANT_SUPPORT //
1045 #ifdef LEAP_SUPPORT
1046 || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
1047 #endif // LEAP_SUPPORT //
1048 )
1049 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1050 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1051 )
1052 {
1053 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1054 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1055
1056 return (NDIS_STATUS_FAILURE);
1057 }
1058
1059
1060 // STEP 1. Decide number of fragments required to deliver this MSDU.
1061 // The estimation here is not very accurate because difficult to
1062 // take encryption overhead into consideration here. The result
1063 // "NumberOfFrag" is then just used to pre-check if enough free
1064 // TXD are available to hold this MSDU.
1065
1066
1067 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1068 NumberOfFrag = 1;
1069 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1070 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1071 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1072 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1073 #ifdef DOT11_N_SUPPORT
1074 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1075 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1076 #endif // DOT11_N_SUPPORT //
1077 else
1078 {
1079 // The calculated "NumberOfFrag" is a rough estimation because of various
1080 // encryption/encapsulation overhead not taken into consideration. This number is just
1081 // used to make sure enough free TXD are available before fragmentation takes place.
1082 // In case the actual required number of fragments of an NDIS packet
1083 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1084 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1085 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1086 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1087
1088 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1089 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1090 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1091 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1092 {
1093 NumberOfFrag--;
1094 }
1095 }
1096
1097 // Save fragment number to Ndis packet reserved field
1098 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1099
1100
1101 // STEP 2. Check the requirement of RTS:
1102 // If multiple fragment required, RTS is required only for the first fragment
1103 // if the fragment size large than RTS threshold
1104 // For RT28xx, Let ASIC send RTS/CTS
1105 RTMP_SET_PACKET_RTS(pPacket, 0);
1106 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1107
1108 //
1109 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1110 //
1111 UserPriority = 0;
1112 QueIdx = QID_AC_BE;
1113 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1114 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1115 {
1116 USHORT Protocol;
1117 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1118 do
1119 {
1120 // get Ethernet protocol field
1121 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1122 if (Protocol <= 1500)
1123 {
1124 // get Ethernet protocol field from LLC/SNAP
1125 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1126 break;
1127
1128 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1129 LlcSnapLen = 8;
1130 }
1131
1132 // always AC_BE for non-IP packet
1133 if (Protocol != 0x0800)
1134 break;
1135
1136 // get IP header
1137 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1138 break;
1139
1140 // return AC_BE if packet is not IPv4
1141 if ((Byte0 & 0xf0) != 0x40)
1142 break;
1143
1144 FlgIsIP = 1;
1145 UserPriority = (Byte1 & 0xe0) >> 5;
1146 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1147
1148 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1149 // TODO: downgrade UP & QueIdx before passing ACM
1150 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1151 {
1152 UserPriority = 0;
1153 QueIdx = QID_AC_BE;
1154 }
1155 } while (FALSE);
1156 }
1157
1158 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1159
1160
1161
1162 // Make sure SendTxWait queue resource won't be used by other threads
1163 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1164 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1165 {
1166 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1167 #ifdef BLOCK_NET_IF
1168 StopNetIfQueue(pAd, QueIdx, pPacket);
1169 #endif // BLOCK_NET_IF //
1170 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1171
1172 return NDIS_STATUS_FAILURE;
1173 }
1174 else
1175 {
1176 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1177 }
1178 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1179
1180 #ifdef DOT11_N_SUPPORT
1181 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1182 IS_HT_STA(pEntry))
1183 {
1184 //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID];
1185 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1186 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1187 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1188 // For IOT compatibility, if
1189 // 1. It is Ralink chip or
1190 // 2. It is OPEN or AES mode,
1191 // then BA session can be bulit.
1192 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1193 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1194 )
1195 {
1196 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1197 }
1198 }
1199 #endif // DOT11_N_SUPPORT //
1200
1201 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1202 return NDIS_STATUS_SUCCESS;
1203 }
1204
1205
1206 /*
1207 ========================================================================
1208
1209 Routine Description:
1210 This subroutine will scan through releative ring descriptor to find
1211 out avaliable free ring descriptor and compare with request size.
1212
1213 Arguments:
1214 pAd Pointer to our adapter
1215 QueIdx Selected TX Ring
1216
1217 Return Value:
1218 NDIS_STATUS_FAILURE Not enough free descriptor
1219 NDIS_STATUS_SUCCESS Enough free descriptor
1220
1221 IRQL = PASSIVE_LEVEL
1222 IRQL = DISPATCH_LEVEL
1223
1224 Note:
1225
1226 ========================================================================
1227 */
1228
1229 #ifdef RT2870
1230 /*
1231 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1232 If no frame need to send, go to sleep, else, still wake up.
1233 */
RTMPFreeTXDRequest(IN PRTMP_ADAPTER pAd,IN UCHAR QueIdx,IN UCHAR NumberRequired,IN PUCHAR FreeNumberIs)1234 NDIS_STATUS RTMPFreeTXDRequest(
1235 IN PRTMP_ADAPTER pAd,
1236 IN UCHAR QueIdx,
1237 IN UCHAR NumberRequired,
1238 IN PUCHAR FreeNumberIs)
1239 {
1240 //ULONG FreeNumber = 0;
1241 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1242 unsigned long IrqFlags;
1243 HT_TX_CONTEXT *pHTTXContext;
1244
1245 switch (QueIdx)
1246 {
1247 case QID_AC_BK:
1248 case QID_AC_BE:
1249 case QID_AC_VI:
1250 case QID_AC_VO:
1251 case QID_HCCA:
1252 {
1253 pHTTXContext = &pAd->TxContext[QueIdx];
1254 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1255 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1256 (pHTTXContext->IRPPending == TRUE))
1257 {
1258 Status = NDIS_STATUS_FAILURE;
1259 }
1260 else
1261 {
1262 Status = NDIS_STATUS_SUCCESS;
1263 }
1264 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1265 }
1266 break;
1267
1268 case QID_MGMT:
1269 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1270 Status = NDIS_STATUS_FAILURE;
1271 else
1272 Status = NDIS_STATUS_SUCCESS;
1273 break;
1274
1275 default:
1276 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1277 break;
1278 }
1279
1280 return (Status);
1281
1282 }
1283 #endif // RT2870 //
1284
1285
RTMPSendDisassociationFrame(IN PRTMP_ADAPTER pAd)1286 VOID RTMPSendDisassociationFrame(
1287 IN PRTMP_ADAPTER pAd)
1288 {
1289 }
1290
RTMPSendNullFrame(IN PRTMP_ADAPTER pAd,IN UCHAR TxRate,IN BOOLEAN bQosNull)1291 VOID RTMPSendNullFrame(
1292 IN PRTMP_ADAPTER pAd,
1293 IN UCHAR TxRate,
1294 IN BOOLEAN bQosNull)
1295 {
1296 UCHAR NullFrame[48];
1297 ULONG Length;
1298 PHEADER_802_11 pHeader_802_11;
1299
1300
1301 #ifdef RALINK_ATE
1302 if(ATE_ON(pAd))
1303 {
1304 return;
1305 }
1306 #endif // RALINK_ATE //
1307
1308 // WPA 802.1x secured port control
1309 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1310 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1311 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1312 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1313 #ifdef WPA_SUPPLICANT_SUPPORT
1314 || (pAd->StaCfg.IEEE8021X == TRUE)
1315 #endif
1316 ) &&
1317 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1318 {
1319 return;
1320 }
1321
1322 NdisZeroMemory(NullFrame, 48);
1323 Length = sizeof(HEADER_802_11);
1324
1325 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1326
1327 pHeader_802_11->FC.Type = BTYPE_DATA;
1328 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1329 pHeader_802_11->FC.ToDs = 1;
1330 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1331 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1332 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1333
1334 if (pAd->CommonCfg.bAPSDForcePowerSave)
1335 {
1336 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1337 }
1338 else
1339 {
1340 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1341 }
1342 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1343
1344 pAd->Sequence++;
1345 pHeader_802_11->Sequence = pAd->Sequence;
1346
1347 // Prepare QosNull function frame
1348 if (bQosNull)
1349 {
1350 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1351
1352 // copy QOS control bytes
1353 NullFrame[Length] = 0;
1354 NullFrame[Length+1] = 0;
1355 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1356 }
1357
1358 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1359
1360 }
1361
1362 // IRQL = DISPATCH_LEVEL
RTMPSendRTSFrame(IN PRTMP_ADAPTER pAd,IN PUCHAR pDA,IN unsigned int NextMpduSize,IN UCHAR TxRate,IN UCHAR RTSRate,IN USHORT AckDuration,IN UCHAR QueIdx,IN UCHAR FrameGap)1363 VOID RTMPSendRTSFrame(
1364 IN PRTMP_ADAPTER pAd,
1365 IN PUCHAR pDA,
1366 IN unsigned int NextMpduSize,
1367 IN UCHAR TxRate,
1368 IN UCHAR RTSRate,
1369 IN USHORT AckDuration,
1370 IN UCHAR QueIdx,
1371 IN UCHAR FrameGap)
1372 {
1373 }
1374
1375
1376
1377 // --------------------------------------------------------
1378 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1379 // Find the WPA key, either Group or Pairwise Key
1380 // LEAP + TKIP also use WPA key.
1381 // --------------------------------------------------------
1382 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1383 // In Cisco CCX 2.0 Leap Authentication
1384 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1385 // Instead of the SharedKey, SharedKey Length may be Zero.
STAFindCipherAlgorithm(IN PRTMP_ADAPTER pAd,IN TX_BLK * pTxBlk)1386 VOID STAFindCipherAlgorithm(
1387 IN PRTMP_ADAPTER pAd,
1388 IN TX_BLK *pTxBlk)
1389 {
1390 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1391 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1392 UCHAR KeyIdx = 0xff;
1393 PUCHAR pSrcBufVA;
1394 PCIPHER_KEY pKey = NULL;
1395
1396 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1397
1398 {
1399 // Select Cipher
1400 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1401 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1402 else
1403 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1404
1405 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1406 {
1407 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1408
1409 // 4-way handshaking frame must be clear
1410 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1411 (pAd->SharedKey[BSS0][0].KeyLen))
1412 {
1413 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1414 KeyIdx = 0;
1415 }
1416 }
1417 else if (Cipher == Ndis802_11Encryption1Enabled)
1418 {
1419 #ifdef LEAP_SUPPORT
1420 if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1421 {
1422 if (LEAP_CCKM_ON(pAd))
1423 {
1424 if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1425 KeyIdx = 1;
1426 else
1427 KeyIdx = 0;
1428 }
1429 else
1430 KeyIdx = pAd->StaCfg.DefaultKeyId;
1431 }
1432 else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1433 KeyIdx = pAd->StaCfg.DefaultKeyId;
1434 else if (LEAP_CCKM_ON(pAd))
1435 {
1436 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1437 KeyIdx = 1;
1438 else
1439 KeyIdx = 0;
1440 }
1441 else // standard WEP64 or WEP128
1442 #endif // LEAP_SUPPORT //
1443 KeyIdx = pAd->StaCfg.DefaultKeyId;
1444 }
1445 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1446 (Cipher == Ndis802_11Encryption3Enabled))
1447 {
1448 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1449 KeyIdx = pAd->StaCfg.DefaultKeyId;
1450 else if (pAd->SharedKey[BSS0][0].KeyLen)
1451 KeyIdx = 0;
1452 else
1453 KeyIdx = pAd->StaCfg.DefaultKeyId;
1454 }
1455
1456 if (KeyIdx == 0xff)
1457 CipherAlg = CIPHER_NONE;
1458 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1459 CipherAlg = CIPHER_NONE;
1460 #ifdef WPA_SUPPLICANT_SUPPORT
1461 else if ( pAd->StaCfg.WpaSupplicantUP &&
1462 (Cipher == Ndis802_11Encryption1Enabled) &&
1463 (pAd->StaCfg.IEEE8021X == TRUE) &&
1464 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1465 CipherAlg = CIPHER_NONE;
1466 #endif // WPA_SUPPLICANT_SUPPORT //
1467 else
1468 {
1469 //Header_802_11.FC.Wep = 1;
1470 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1471 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1472 }
1473 }
1474
1475 pTxBlk->CipherAlg = CipherAlg;
1476 pTxBlk->pKey = pKey;
1477 }
1478
1479
STABuildCommon802_11Header(IN PRTMP_ADAPTER pAd,IN TX_BLK * pTxBlk)1480 VOID STABuildCommon802_11Header(
1481 IN PRTMP_ADAPTER pAd,
1482 IN TX_BLK *pTxBlk)
1483 {
1484
1485 HEADER_802_11 *pHeader_802_11;
1486 #ifdef QOS_DLS_SUPPORT
1487 BOOLEAN bDLSFrame = FALSE;
1488 INT DlsEntryIndex = 0;
1489 #endif // QOS_DLS_SUPPORT //
1490
1491 //
1492 // MAKE A COMMON 802.11 HEADER
1493 //
1494
1495 // normal wlan header size : 24 octets
1496 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1497
1498 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1499
1500 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1501
1502 pHeader_802_11->FC.FrDs = 0;
1503 pHeader_802_11->FC.Type = BTYPE_DATA;
1504 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1505
1506 #ifdef QOS_DLS_SUPPORT
1507 if (INFRA_ON(pAd))
1508 {
1509 // Check if the frame can be sent through DLS direct link interface
1510 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1511 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1512 if (DlsEntryIndex >= 0)
1513 bDLSFrame = TRUE;
1514 else
1515 bDLSFrame = FALSE;
1516 }
1517 #endif // QOS_DLS_SUPPORT //
1518
1519 if (pTxBlk->pMacEntry)
1520 {
1521 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1522 {
1523 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1524 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1525 }
1526 else
1527 {
1528 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1529 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1530 }
1531 }
1532 else
1533 {
1534 pHeader_802_11->Sequence = pAd->Sequence;
1535 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1536 }
1537
1538 pHeader_802_11->Frag = 0;
1539
1540 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1541
1542 {
1543 if (INFRA_ON(pAd))
1544 {
1545 #ifdef QOS_DLS_SUPPORT
1546 if (bDLSFrame)
1547 {
1548 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1549 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1550 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1551 pHeader_802_11->FC.ToDs = 0;
1552 }
1553 else
1554 #endif // QOS_DLS_SUPPORT //
1555 {
1556 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1557 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1558 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1559 pHeader_802_11->FC.ToDs = 1;
1560 }
1561 }
1562 else if (ADHOC_ON(pAd))
1563 {
1564 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1565 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1566 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1567 pHeader_802_11->FC.ToDs = 0;
1568 }
1569 }
1570
1571 if (pTxBlk->CipherAlg != CIPHER_NONE)
1572 pHeader_802_11->FC.Wep = 1;
1573
1574 // -----------------------------------------------------------------
1575 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1576 // -----------------------------------------------------------------
1577 if (pAd->CommonCfg.bAPSDForcePowerSave)
1578 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1579 else
1580 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1581 }
1582
1583 #ifdef DOT11_N_SUPPORT
STABuildCache802_11Header(IN RTMP_ADAPTER * pAd,IN TX_BLK * pTxBlk,IN UCHAR * pHeader)1584 VOID STABuildCache802_11Header(
1585 IN RTMP_ADAPTER *pAd,
1586 IN TX_BLK *pTxBlk,
1587 IN UCHAR *pHeader)
1588 {
1589 MAC_TABLE_ENTRY *pMacEntry;
1590 PHEADER_802_11 pHeader80211;
1591
1592 pHeader80211 = (PHEADER_802_11)pHeader;
1593 pMacEntry = pTxBlk->pMacEntry;
1594
1595 //
1596 // Update the cached 802.11 HEADER
1597 //
1598
1599 // normal wlan header size : 24 octets
1600 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1601
1602 // More Bit
1603 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1604
1605 // Sequence
1606 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1607 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1608
1609 {
1610 // Check if the frame can be sent through DLS direct link interface
1611 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1612 #ifdef QOS_DLS_SUPPORT
1613 BOOLEAN bDLSFrame = FALSE;
1614 INT DlsEntryIndex = 0;
1615
1616 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1617 if (DlsEntryIndex >= 0)
1618 bDLSFrame = TRUE;
1619 else
1620 bDLSFrame = FALSE;
1621 #endif // QOS_DLS_SUPPORT //
1622
1623 // The addr3 of normal packet send from DS is Dest Mac address.
1624 #ifdef QOS_DLS_SUPPORT
1625 if (bDLSFrame)
1626 {
1627 COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
1628 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1629 pHeader80211->FC.ToDs = 0;
1630 }
1631 else
1632 #endif // QOS_DLS_SUPPORT //
1633 if (ADHOC_ON(pAd))
1634 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1635 else
1636 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1637 }
1638
1639 // -----------------------------------------------------------------
1640 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1641 // -----------------------------------------------------------------
1642 if (pAd->CommonCfg.bAPSDForcePowerSave)
1643 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1644 else
1645 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1646 }
1647 #endif // DOT11_N_SUPPORT //
1648
STA_Build_ARalink_Frame_Header(IN RTMP_ADAPTER * pAd,IN TX_BLK * pTxBlk)1649 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1650 IN RTMP_ADAPTER *pAd,
1651 IN TX_BLK *pTxBlk)
1652 {
1653 PUCHAR pHeaderBufPtr;
1654 HEADER_802_11 *pHeader_802_11;
1655 PNDIS_PACKET pNextPacket;
1656 UINT32 nextBufLen;
1657 PQUEUE_ENTRY pQEntry;
1658
1659 STAFindCipherAlgorithm(pAd, pTxBlk);
1660 STABuildCommon802_11Header(pAd, pTxBlk);
1661
1662
1663 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1664 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1665
1666 // steal "order" bit to mark "aggregation"
1667 pHeader_802_11->FC.Order = 1;
1668
1669 // skip common header
1670 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1671
1672 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1673 {
1674 //
1675 // build QOS Control bytes
1676 //
1677 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1678
1679 *(pHeaderBufPtr+1) = 0;
1680 pHeaderBufPtr +=2;
1681 pTxBlk->MpduHeaderLen += 2;
1682 }
1683
1684 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1685 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1686 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1687 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1688
1689 // For RA Aggregation,
1690 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1691 pQEntry = pTxBlk->TxPacketList.Head;
1692 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1693 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1694 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1695 nextBufLen -= LENGTH_802_1Q;
1696
1697 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1698 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1699
1700 pHeaderBufPtr += 2;
1701 pTxBlk->MpduHeaderLen += 2;
1702
1703 return pHeaderBufPtr;
1704
1705 }
1706
1707 #ifdef DOT11_N_SUPPORT
STA_Build_AMSDU_Frame_Header(IN RTMP_ADAPTER * pAd,IN TX_BLK * pTxBlk)1708 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1709 IN RTMP_ADAPTER *pAd,
1710 IN TX_BLK *pTxBlk)
1711 {
1712 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1713 HEADER_802_11 *pHeader_802_11;
1714
1715
1716 STAFindCipherAlgorithm(pAd, pTxBlk);
1717 STABuildCommon802_11Header(pAd, pTxBlk);
1718
1719 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1720 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1721
1722 // skip common header
1723 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1724
1725 //
1726 // build QOS Control bytes
1727 //
1728 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1729
1730 //
1731 // A-MSDU packet
1732 //
1733 *pHeaderBufPtr |= 0x80;
1734
1735 *(pHeaderBufPtr+1) = 0;
1736 pHeaderBufPtr +=2;
1737 pTxBlk->MpduHeaderLen += 2;
1738
1739 //pSaveBufPtr = pHeaderBufPtr;
1740
1741 //
1742 // padding at front of LLC header
1743 // LLC header should locate at 4-octets aligment
1744 //
1745 // @@@ MpduHeaderLen excluding padding @@@
1746 //
1747 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1748 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1749 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1750
1751 return pHeaderBufPtr;
1752
1753 }
1754
1755
STA_AMPDU_Frame_Tx(IN PRTMP_ADAPTER pAd,IN TX_BLK * pTxBlk)1756 VOID STA_AMPDU_Frame_Tx(
1757 IN PRTMP_ADAPTER pAd,
1758 IN TX_BLK *pTxBlk)
1759 {
1760 HEADER_802_11 *pHeader_802_11;
1761 PUCHAR pHeaderBufPtr;
1762 USHORT FreeNumber;
1763 MAC_TABLE_ENTRY *pMacEntry;
1764 BOOLEAN bVLANPkt;
1765 PQUEUE_ENTRY pQEntry;
1766
1767 ASSERT(pTxBlk);
1768
1769 while(pTxBlk->TxPacketList.Head)
1770 {
1771 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1772 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1773 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1774 {
1775 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1776 continue;
1777 }
1778
1779 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1780
1781 pMacEntry = pTxBlk->pMacEntry;
1782 if (pMacEntry->isCached)
1783 {
1784 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1785 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1786 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1787 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1788 }
1789 else
1790 {
1791 STAFindCipherAlgorithm(pAd, pTxBlk);
1792 STABuildCommon802_11Header(pAd, pTxBlk);
1793
1794 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1795 }
1796
1797
1798 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1799
1800 // skip common header
1801 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1802
1803 //
1804 // build QOS Control bytes
1805 //
1806 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1807 *(pHeaderBufPtr+1) = 0;
1808 pHeaderBufPtr +=2;
1809 pTxBlk->MpduHeaderLen += 2;
1810
1811 //
1812 // build HTC+
1813 // HTC control filed following QoS field
1814 //
1815 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1816 {
1817 if (pMacEntry->isCached == FALSE)
1818 {
1819 // mark HTC bit
1820 pHeader_802_11->FC.Order = 1;
1821
1822 NdisZeroMemory(pHeaderBufPtr, 4);
1823 *(pHeaderBufPtr+3) |= 0x80;
1824 }
1825 pHeaderBufPtr += 4;
1826 pTxBlk->MpduHeaderLen += 4;
1827 }
1828
1829 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1830 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1831
1832 // skip 802.3 header
1833 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1834 pTxBlk->SrcBufLen -= LENGTH_802_3;
1835
1836 // skip vlan tag
1837 if (bVLANPkt)
1838 {
1839 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1840 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1841 }
1842
1843 //
1844 // padding at front of LLC header
1845 // LLC header should locate at 4-octets aligment
1846 //
1847 // @@@ MpduHeaderLen excluding padding @@@
1848 //
1849 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1850 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1851 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1852
1853 {
1854
1855 //
1856 // Insert LLC-SNAP encapsulation - 8 octets
1857 //
1858 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1859 if (pTxBlk->pExtraLlcSnapEncap)
1860 {
1861 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1862 pHeaderBufPtr += 6;
1863 // get 2 octets (TypeofLen)
1864 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1865 pHeaderBufPtr += 2;
1866 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1867 }
1868
1869 }
1870
1871 if (pMacEntry->isCached)
1872 {
1873 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1874 }
1875 else
1876 {
1877 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1878
1879 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1880 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1881 pMacEntry->isCached = TRUE;
1882 }
1883
1884 // calculate Transmitted AMPDU count and ByteCount
1885 {
1886 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1887 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1888 }
1889
1890 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1891
1892 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1893
1894 //
1895 // Kick out Tx
1896 //
1897 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1898
1899 pAd->RalinkCounters.KickTxCount++;
1900 pAd->RalinkCounters.OneSecTxDoneCount++;
1901 }
1902
1903 }
1904
1905
STA_AMSDU_Frame_Tx(IN PRTMP_ADAPTER pAd,IN TX_BLK * pTxBlk)1906 VOID STA_AMSDU_Frame_Tx(
1907 IN PRTMP_ADAPTER pAd,
1908 IN TX_BLK *pTxBlk)
1909 {
1910 PUCHAR pHeaderBufPtr;
1911 USHORT FreeNumber;
1912 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1913 USHORT totalMPDUSize=0;
1914 UCHAR *subFrameHeader;
1915 UCHAR padding = 0;
1916 USHORT FirstTx = 0, LastTxIdx = 0;
1917 BOOLEAN bVLANPkt;
1918 int frameNum = 0;
1919 PQUEUE_ENTRY pQEntry;
1920
1921
1922 ASSERT(pTxBlk);
1923
1924 ASSERT((pTxBlk->TxPacketList.Number > 1));
1925
1926 while(pTxBlk->TxPacketList.Head)
1927 {
1928 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1929 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1930 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1931 {
1932 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1933 continue;
1934 }
1935
1936 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1937
1938 // skip 802.3 header
1939 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1940 pTxBlk->SrcBufLen -= LENGTH_802_3;
1941
1942 // skip vlan tag
1943 if (bVLANPkt)
1944 {
1945 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1946 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1947 }
1948
1949 if (frameNum == 0)
1950 {
1951 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1952
1953 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1954 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1955 }
1956 else
1957 {
1958 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1959 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1960 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1961 pHeaderBufPtr += padding;
1962 pTxBlk->MpduHeaderLen = padding;
1963 }
1964
1965 //
1966 // A-MSDU subframe
1967 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1968 //
1969 subFrameHeader = pHeaderBufPtr;
1970 subFramePayloadLen = pTxBlk->SrcBufLen;
1971
1972 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1973
1974
1975 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1976 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1977
1978
1979 //
1980 // Insert LLC-SNAP encapsulation - 8 octets
1981 //
1982 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1983
1984 subFramePayloadLen = pTxBlk->SrcBufLen;
1985
1986 if (pTxBlk->pExtraLlcSnapEncap)
1987 {
1988 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1989 pHeaderBufPtr += 6;
1990 // get 2 octets (TypeofLen)
1991 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1992 pHeaderBufPtr += 2;
1993 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1994 subFramePayloadLen += LENGTH_802_1_H;
1995 }
1996
1997 // update subFrame Length field
1998 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1999 subFrameHeader[13] = subFramePayloadLen & 0xFF;
2000
2001 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2002
2003 if (frameNum ==0)
2004 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2005 else
2006 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2007
2008 frameNum++;
2009
2010 pAd->RalinkCounters.KickTxCount++;
2011 pAd->RalinkCounters.OneSecTxDoneCount++;
2012
2013 // calculate Transmitted AMSDU Count and ByteCount
2014 {
2015 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
2016 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
2017 }
2018
2019 }
2020
2021 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2022 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2023
2024 //
2025 // Kick out Tx
2026 //
2027 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2028 }
2029 #endif // DOT11_N_SUPPORT //
2030
STA_Legacy_Frame_Tx(IN PRTMP_ADAPTER pAd,IN TX_BLK * pTxBlk)2031 VOID STA_Legacy_Frame_Tx(
2032 IN PRTMP_ADAPTER pAd,
2033 IN TX_BLK *pTxBlk)
2034 {
2035 HEADER_802_11 *pHeader_802_11;
2036 PUCHAR pHeaderBufPtr;
2037 USHORT FreeNumber;
2038 BOOLEAN bVLANPkt;
2039 PQUEUE_ENTRY pQEntry;
2040
2041 ASSERT(pTxBlk);
2042
2043
2044 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2045 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2046 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2047 {
2048 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2049 return;
2050 }
2051
2052 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
2053 {
2054 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
2055 }
2056
2057 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
2058 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
2059 else
2060 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
2061
2062 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2063
2064 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
2065 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
2066
2067 STAFindCipherAlgorithm(pAd, pTxBlk);
2068 STABuildCommon802_11Header(pAd, pTxBlk);
2069
2070
2071 // skip 802.3 header
2072 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2073 pTxBlk->SrcBufLen -= LENGTH_802_3;
2074
2075 // skip vlan tag
2076 if (bVLANPkt)
2077 {
2078 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2079 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2080 }
2081
2082 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2083 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
2084
2085 // skip common header
2086 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2087
2088 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2089 {
2090 //
2091 // build QOS Control bytes
2092 //
2093 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2094 *(pHeaderBufPtr+1) = 0;
2095 pHeaderBufPtr +=2;
2096 pTxBlk->MpduHeaderLen += 2;
2097 }
2098
2099 // The remaining content of MPDU header should locate at 4-octets aligment
2100 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2101 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2102 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2103
2104 {
2105
2106 //
2107 // Insert LLC-SNAP encapsulation - 8 octets
2108 //
2109 //
2110 // if original Ethernet frame contains no LLC/SNAP,
2111 // then an extra LLC/SNAP encap is required
2112 //
2113 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2114 if (pTxBlk->pExtraLlcSnapEncap)
2115 {
2116 UCHAR vlan_size;
2117
2118 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2119 pHeaderBufPtr += 6;
2120 // skip vlan tag
2121 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2122 // get 2 octets (TypeofLen)
2123 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2124 pHeaderBufPtr += 2;
2125 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2126 }
2127
2128 }
2129
2130 //
2131 // prepare for TXWI
2132 // use Wcid as Key Index
2133 //
2134
2135 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2136
2137 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2138
2139 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2140
2141 pAd->RalinkCounters.KickTxCount++;
2142 pAd->RalinkCounters.OneSecTxDoneCount++;
2143
2144 //
2145 // Kick out Tx
2146 //
2147 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2148 }
2149
2150
STA_ARalink_Frame_Tx(IN PRTMP_ADAPTER pAd,IN TX_BLK * pTxBlk)2151 VOID STA_ARalink_Frame_Tx(
2152 IN PRTMP_ADAPTER pAd,
2153 IN TX_BLK *pTxBlk)
2154 {
2155 PUCHAR pHeaderBufPtr;
2156 USHORT FreeNumber;
2157 USHORT totalMPDUSize=0;
2158 USHORT FirstTx, LastTxIdx;
2159 int frameNum = 0;
2160 BOOLEAN bVLANPkt;
2161 PQUEUE_ENTRY pQEntry;
2162
2163
2164 ASSERT(pTxBlk);
2165
2166 ASSERT((pTxBlk->TxPacketList.Number== 2));
2167
2168
2169 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2170 while(pTxBlk->TxPacketList.Head)
2171 {
2172 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2173 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2174
2175 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2176 {
2177 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2178 continue;
2179 }
2180
2181 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2182
2183 // skip 802.3 header
2184 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2185 pTxBlk->SrcBufLen -= LENGTH_802_3;
2186
2187 // skip vlan tag
2188 if (bVLANPkt)
2189 {
2190 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2191 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2192 }
2193
2194 if (frameNum == 0)
2195 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2196
2197 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2198
2199 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2200 // will be updated after final frame was handled.
2201 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2202
2203
2204 //
2205 // Insert LLC-SNAP encapsulation - 8 octets
2206 //
2207 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2208
2209 if (pTxBlk->pExtraLlcSnapEncap)
2210 {
2211 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2212 pHeaderBufPtr += 6;
2213 // get 2 octets (TypeofLen)
2214 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2215 pHeaderBufPtr += 2;
2216 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2217 }
2218 }
2219 else
2220 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2221
2222 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2223 pTxBlk->MpduHeaderLen = 0;
2224
2225 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2226 // DA(6)+SA(6)+FrameType(2)
2227 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2228 pHeaderBufPtr += 12;
2229 // get 2 octets (TypeofLen)
2230 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2231 pHeaderBufPtr += 2;
2232 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2233 }
2234
2235 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2236
2237 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2238 if (frameNum ==0)
2239 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2240 else
2241 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2242
2243 frameNum++;
2244
2245 pAd->RalinkCounters.OneSecTxAggregationCount++;
2246 pAd->RalinkCounters.KickTxCount++;
2247 pAd->RalinkCounters.OneSecTxDoneCount++;
2248
2249 }
2250
2251 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2252 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2253
2254 //
2255 // Kick out Tx
2256 //
2257 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2258
2259 }
2260
2261
STA_Fragment_Frame_Tx(IN RTMP_ADAPTER * pAd,IN TX_BLK * pTxBlk)2262 VOID STA_Fragment_Frame_Tx(
2263 IN RTMP_ADAPTER *pAd,
2264 IN TX_BLK *pTxBlk)
2265 {
2266 HEADER_802_11 *pHeader_802_11;
2267 PUCHAR pHeaderBufPtr;
2268 USHORT FreeNumber;
2269 UCHAR fragNum = 0;
2270 PACKET_INFO PacketInfo;
2271 USHORT EncryptionOverhead = 0;
2272 UINT32 FreeMpduSize, SrcRemainingBytes;
2273 USHORT AckDuration;
2274 UINT NextMpduSize;
2275 BOOLEAN bVLANPkt;
2276 PQUEUE_ENTRY pQEntry;
2277
2278
2279 ASSERT(pTxBlk);
2280
2281 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2282 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2283 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2284 {
2285 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2286 return;
2287 }
2288
2289 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2290 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2291
2292 STAFindCipherAlgorithm(pAd, pTxBlk);
2293 STABuildCommon802_11Header(pAd, pTxBlk);
2294
2295 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2296 {
2297 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2298 if (pTxBlk->pPacket == NULL)
2299 return;
2300 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2301 }
2302
2303 // skip 802.3 header
2304 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2305 pTxBlk->SrcBufLen -= LENGTH_802_3;
2306
2307
2308 // skip vlan tag
2309 if (bVLANPkt)
2310 {
2311 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2312 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2313 }
2314
2315 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2316 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2317
2318
2319 // skip common header
2320 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2321
2322 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2323 {
2324 //
2325 // build QOS Control bytes
2326 //
2327 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2328
2329 *(pHeaderBufPtr+1) = 0;
2330 pHeaderBufPtr +=2;
2331 pTxBlk->MpduHeaderLen += 2;
2332 }
2333
2334 //
2335 // padding at front of LLC header
2336 // LLC header should locate at 4-octets aligment
2337 //
2338 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2339 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2340 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2341
2342
2343
2344 //
2345 // Insert LLC-SNAP encapsulation - 8 octets
2346 //
2347 //
2348 // if original Ethernet frame contains no LLC/SNAP,
2349 // then an extra LLC/SNAP encap is required
2350 //
2351 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2352 if (pTxBlk->pExtraLlcSnapEncap)
2353 {
2354 UCHAR vlan_size;
2355
2356 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2357 pHeaderBufPtr += 6;
2358 // skip vlan tag
2359 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2360 // get 2 octets (TypeofLen)
2361 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2362 pHeaderBufPtr += 2;
2363 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2364 }
2365
2366
2367 // If TKIP is used and fragmentation is required. Driver has to
2368 // append TKIP MIC at tail of the scatter buffer
2369 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2370 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2371 {
2372
2373 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2374 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2375 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2376 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2377 pTxBlk->SrcBufLen += 8;
2378 pTxBlk->TotalFrameLen += 8;
2379 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2380 }
2381
2382 //
2383 // calcuate the overhead bytes that encryption algorithm may add. This
2384 // affects the calculate of "duration" field
2385 //
2386 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2387 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2388 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2389 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2390 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2391 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2392 else if (pTxBlk->CipherAlg == CIPHER_AES)
2393 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2394 else
2395 EncryptionOverhead = 0;
2396
2397 // decide how much time an ACK/CTS frame will consume in the air
2398 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2399
2400 // Init the total payload length of this frame.
2401 SrcRemainingBytes = pTxBlk->SrcBufLen;
2402
2403 pTxBlk->TotalFragNum = 0xff;
2404
2405 do {
2406
2407 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2408
2409 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2410
2411 if (SrcRemainingBytes <= FreeMpduSize)
2412 { // this is the last or only fragment
2413
2414 pTxBlk->SrcBufLen = SrcRemainingBytes;
2415
2416 pHeader_802_11->FC.MoreFrag = 0;
2417 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2418
2419 // Indicate the lower layer that this's the last fragment.
2420 pTxBlk->TotalFragNum = fragNum;
2421 }
2422 else
2423 { // more fragment is required
2424
2425 pTxBlk->SrcBufLen = FreeMpduSize;
2426
2427 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2428 pHeader_802_11->FC.MoreFrag = 1;
2429 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2430 }
2431
2432 if (fragNum == 0)
2433 pTxBlk->FrameGap = IFS_HTTXOP;
2434 else
2435 pTxBlk->FrameGap = IFS_SIFS;
2436
2437 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2438
2439 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2440
2441 pAd->RalinkCounters.KickTxCount++;
2442 pAd->RalinkCounters.OneSecTxDoneCount++;
2443
2444 // Update the frame number, remaining size of the NDIS packet payload.
2445
2446 // space for 802.11 header.
2447 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2448 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2449
2450 fragNum++;
2451 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2452 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2453
2454 pHeader_802_11->Frag++; // increase Frag #
2455
2456 }while(SrcRemainingBytes > 0);
2457
2458 //
2459 // Kick out Tx
2460 //
2461 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2462 }
2463
2464
2465 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2466 while(_pTxBlk->TxPacketList.Head) \
2467 { \
2468 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2469 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2470 }
2471
2472
2473 /*
2474 ========================================================================
2475
2476 Routine Description:
2477 Copy frame from waiting queue into relative ring buffer and set
2478 appropriate ASIC register to kick hardware encryption before really
2479 sent out to air.
2480
2481 Arguments:
2482 pAd Pointer to our adapter
2483 PNDIS_PACKET Pointer to outgoing Ndis frame
2484 NumberOfFrag Number of fragment required
2485
2486 Return Value:
2487 None
2488
2489 IRQL = DISPATCH_LEVEL
2490
2491 Note:
2492
2493 ========================================================================
2494 */
STAHardTransmit(IN PRTMP_ADAPTER pAd,IN TX_BLK * pTxBlk,IN UCHAR QueIdx)2495 NDIS_STATUS STAHardTransmit(
2496 IN PRTMP_ADAPTER pAd,
2497 IN TX_BLK *pTxBlk,
2498 IN UCHAR QueIdx)
2499 {
2500 NDIS_PACKET *pPacket;
2501 PQUEUE_ENTRY pQEntry;
2502
2503 // ---------------------------------------------
2504 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2505 // ---------------------------------------------
2506 //
2507 ASSERT(pTxBlk->TxPacketList.Number);
2508 if (pTxBlk->TxPacketList.Head == NULL)
2509 {
2510 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2511 return NDIS_STATUS_FAILURE;
2512 }
2513
2514 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2515
2516 #if 0 //def CARRIER_DETECTION_SUPPORT // Roger sync Carrier
2517 if ((pAd->CommonCfg.CarrierDetect.Enable == TRUE) && (isCarrierDetectExist(pAd) == TRUE))
2518 {
2519 DBGPRINT(RT_DEBUG_INFO,("STAHardTransmit --> radar detect not in normal mode !!!\n"));
2520 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2521 return (NDIS_STATUS_FAILURE);
2522 }
2523 #endif // CARRIER_DETECTION_SUPPORT //
2524
2525 // ------------------------------------------------------------------
2526 // STEP 1. WAKE UP PHY
2527 // outgoing frame always wakeup PHY to prevent frame lost and
2528 // turn off PSM bit to improve performance
2529 // ------------------------------------------------------------------
2530 // not to change PSM bit, just send this frame out?
2531 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2532 {
2533 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2534 AsicForceWakeup(pAd, TRUE);
2535 }
2536
2537 // It should not change PSM bit, when APSD turn on.
2538 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2539 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2540 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2541 {
2542 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2543 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2544 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2545 }
2546
2547 switch (pTxBlk->TxFrameType)
2548 {
2549 #ifdef DOT11_N_SUPPORT
2550 case TX_AMPDU_FRAME:
2551 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2552 break;
2553 case TX_AMSDU_FRAME:
2554 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2555 break;
2556 #endif // DOT11_N_SUPPORT //
2557 case TX_LEGACY_FRAME:
2558 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2559 break;
2560 case TX_MCAST_FRAME:
2561 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2562 break;
2563 case TX_RALINK_FRAME:
2564 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2565 break;
2566 case TX_FRAG_FRAME:
2567 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2568 break;
2569 default:
2570 {
2571 // It should not happened!
2572 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2573 while(pTxBlk->TxPacketList.Number)
2574 {
2575 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2576 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2577 if (pPacket)
2578 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2579 }
2580 }
2581 break;
2582 }
2583
2584 return (NDIS_STATUS_SUCCESS);
2585
2586 }
2587
HashBytesPolynomial(UCHAR * value,unsigned int len)2588 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2589 {
2590 unsigned char *word = value;
2591 unsigned int ret = 0;
2592 unsigned int i;
2593
2594 for(i=0; i < len; i++)
2595 {
2596 int mod = i % 32;
2597 ret ^=(unsigned int) (word[i]) << mod;
2598 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2599 }
2600 return ret;
2601 }
2602
Sta_Announce_or_Forward_802_3_Packet(IN PRTMP_ADAPTER pAd,IN PNDIS_PACKET pPacket,IN UCHAR FromWhichBSSID)2603 VOID Sta_Announce_or_Forward_802_3_Packet(
2604 IN PRTMP_ADAPTER pAd,
2605 IN PNDIS_PACKET pPacket,
2606 IN UCHAR FromWhichBSSID)
2607 {
2608 if (TRUE
2609 )
2610 {
2611 announce_802_3_packet(pAd, pPacket);
2612 }
2613 else
2614 {
2615 // release packet
2616 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2617 }
2618 }
2619
2620