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