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