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