2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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. *
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. *
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. *
25 *************************************************************************
35 -------- ---------- ----------------------------------------------
36 John Aug/17/04 major modification for RT2561/2661
37 Jan Lee Mar/17/06 major modification for RT2860 New Ring Design
39 #include "../rt_config.h"
43 VOID STARxEAPOLFrameIndicate(
45 IN MAC_TABLE_ENTRY *pEntry,
47 IN UCHAR FromWhichBSSID)
49 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
50 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
54 #ifdef WPA_SUPPLICANT_SUPPORT
55 if (pAd->StaCfg.WpaSupplicantUP)
57 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
58 // TBD : process fragmented EAPol frames
60 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
61 if ( pAd->StaCfg.IEEE8021X == TRUE &&
62 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
68 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
69 //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
70 STA_PORT_SECURED(pAd);
72 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
74 idx = pAd->StaCfg.DesireSharedKeyId;
75 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
76 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
78 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
83 char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
84 NDIS_802_11_WEP keyinfo;
89 NdisZeroMemory(&WepKey, sizeof(WepKey));
90 len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
92 NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
93 pAd->StaCfg.DesireSharedKey[idx].Key,
94 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
96 WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
97 WepKey.keyinfo.KeyLength = len;
98 pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
100 pAd->IndicateMediaState = NdisMediaStateConnected;
101 pAd->ExtraInfo = GENERAL_LINK_UP;
102 // need to enqueue cmd to thread
103 RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
105 // For Preventing ShardKey Table is cleared by remove key procedure.
106 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
107 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
108 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
109 pAd->StaCfg.DesireSharedKey[idx].Key,
110 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
115 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
120 #endif // WPA_SUPPLICANT_SUPPORT //
122 // Special DATA frame that has to pass to MLME
123 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
124 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
126 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
127 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
128 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
129 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
133 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
138 VOID STARxDataFrameAnnounce(
139 IN PRTMP_ADAPTER pAd,
140 IN MAC_TABLE_ENTRY *pEntry,
142 IN UCHAR FromWhichBSSID)
146 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
150 // drop all non-EAP DATA frame before
151 // this client's Port-Access-Control is secured
152 if (pRxBlk->pHeader->FC.Wep)
154 // unsupported cipher suite
155 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
158 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
164 // encryption in-use but receive a non-EAPOL clear text frame, drop it
165 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
166 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
169 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
174 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
175 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
177 // Normal legacy, AMPDU or AMSDU
178 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
184 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
186 #ifdef QOS_DLS_SUPPORT
187 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS);
188 #endif // QOS_DLS_SUPPORT //
192 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
193 #ifdef DOT11_N_SUPPORT
194 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
196 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
199 #endif // DOT11_N_SUPPORT //
201 // Determin the destination of the EAP frame
202 // to WPA state machine or upper layer
203 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
209 // For TKIP frame, calculate the MIC value
210 BOOLEAN STACheckTkipMICValue(
211 IN PRTMP_ADAPTER pAd,
212 IN MAC_TABLE_ENTRY *pEntry,
215 PHEADER_802_11 pHeader = pRxBlk->pHeader;
216 UCHAR *pData = pRxBlk->pData;
217 USHORT DataSize = pRxBlk->DataSize;
218 UCHAR UserPriority = pRxBlk->UserPriority;
222 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
224 pDA = pHeader->Addr1;
225 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
227 pSA = pHeader->Addr3;
231 pSA = pHeader->Addr2;
234 if (RTMPTkipCompareMICValue(pAd,
242 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
244 #ifdef WPA_SUPPLICANT_SUPPORT
245 if (pAd->StaCfg.WpaSupplicantUP)
247 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
250 #endif // WPA_SUPPLICANT_SUPPORT //
252 RTMPReportMicError(pAd, pWpaKey);
256 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
265 // All Rx routines use RX_BLK structure to hande rx events
266 // It is very important to build pRxBlk attributes
267 // 1. pHeader pointer to 802.11 Header
268 // 2. pData pointer to payload including LLC (just skip Header)
269 // 3. set payload size including LLC to DataSize
270 // 4. set some flags with RX_BLK_SET_FLAG()
272 VOID STAHandleRxDataFrame(
273 IN PRTMP_ADAPTER pAd,
276 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
277 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
278 PHEADER_802_11 pHeader = pRxBlk->pHeader;
279 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
280 BOOLEAN bFragment = FALSE;
281 MAC_TABLE_ENTRY *pEntry = NULL;
282 UCHAR FromWhichBSSID = BSS0;
283 UCHAR UserPriority = 0;
286 // before LINK UP, all DATA frames are rejected
287 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
290 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
294 #ifdef QOS_DLS_SUPPORT
295 //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
296 if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD))
300 #endif // QOS_DLS_SUPPORT //
302 // Drop not my BSS frames
303 if (pRxD->MyBss == 0)
307 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
312 pAd->RalinkCounters.RxCountSinceLastNULL++;
313 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
316 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
319 pData = (PUCHAR)pHeader + LENGTH_802_11;
320 if ((*pData >> 4) & 0x01)
322 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
323 pAd->CommonCfg.bInServicePeriod = FALSE;
325 // Force driver to fall into sleep mode when rcv EOSP frame
326 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
328 USHORT TbttNumToNextWakeUp;
329 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
332 NdisGetSystemUpTime(&Now);
333 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
335 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
336 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
337 TbttNumToNextWakeUp = NextDtim;
339 MlmeSetPsmBit(pAd, PWR_SAVE);
340 // if WMM-APSD is failed, try to disable following line
341 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
345 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
347 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
351 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
352 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
355 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
359 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
360 #ifdef QOS_DLS_SUPPORT
361 if (!pAd->CommonCfg.bDLSCapable)
363 #endif // QOS_DLS_SUPPORT //
366 // Infrastructure mode, check address 2 for BSSID
367 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
369 // Receive frame not my BSSID
371 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
375 else // Ad-Hoc mode or Not associated
377 // Ad-Hoc mode, check address 3 for BSSID
378 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
380 // Receive frame not my BSSID
382 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
386 #ifdef QOS_DLS_SUPPORT
388 #endif // QOS_DLS_SUPPORT //
393 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
395 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
399 // 1. release packet if infra mode
400 // 2. new a pEntry if ad-hoc mode
401 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
408 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
409 #ifdef QOS_DLS_SUPPORT
410 if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
411 RX_BLK_SET_FLAG(pRxBlk, fRX_DLS);
413 #endif // QOS_DLS_SUPPORT //
414 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
417 // check Atheros Client
418 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
420 pEntry->bIAmBadAtheros = TRUE;
421 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
422 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
423 if (!STA_AES_ON(pAd))
425 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
430 pRxBlk->pData = (UCHAR *)pHeader;
433 // update RxBlk->pData, DataSize
434 // 802.11 Header, QOS, HTC, Hw Padding
437 // 1. skip 802.11 HEADER
439 pRxBlk->pData += LENGTH_802_11;
440 pRxBlk->DataSize -= LENGTH_802_11;
444 if (pHeader->FC.SubType & 0x08)
446 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
447 UserPriority = *(pRxBlk->pData) & 0x0f;
448 // bit 7 in QoS Control field signals the HT A-MSDU format
449 if ((*pRxBlk->pData) & 0x80)
451 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
454 // skip QOS contorl field
456 pRxBlk->DataSize -=2;
458 pRxBlk->UserPriority = UserPriority;
460 // 3. Order bit: A-Ralink or HTC+
461 if (pHeader->FC.Order)
463 #ifdef AGGREGATION_SUPPORT
464 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
466 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
471 #ifdef DOT11_N_SUPPORT
472 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
473 // skip HTC contorl field
475 pRxBlk->DataSize -= 4;
476 #endif // DOT11_N_SUPPORT //
480 // 4. skip HW padding
483 // just move pData pointer
484 // because DataSize excluding HW padding
485 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
489 #ifdef DOT11_N_SUPPORT
492 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
494 #endif // DOT11_N_SUPPORT //
498 // Case I Process Broadcast & Multicast data frame
500 if (pRxD->Bcast || pRxD->Mcast)
502 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
504 // Drop Mcast/Bcast frame with fragment bit on
505 if (pHeader->FC.MoreFrag)
508 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
512 // Filter out Bcast frame which AP relayed for us
513 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
516 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
520 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
525 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
528 #ifdef QOS_DLS_SUPPORT
529 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS))
531 MAC_TABLE_ENTRY *pDlsEntry = NULL;
533 pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE);
535 Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI);
538 #endif // QOS_DLS_SUPPORT //
541 pEntry = MacTableLookup(pAd, pHeader->Addr2);
543 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
547 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
549 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
550 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
552 pAd->RalinkCounters.OneSecRxOkDataCnt++;
555 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
557 // re-assemble the fragmented packets
558 // return complete frame (pRxPacket) or NULL
560 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
565 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
567 // process complete frame
568 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
571 pRxBlk->DataSize -= 8;
573 // For TKIP frame, calculate the MIC value
574 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
580 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
586 // because RTMPDeFragmentDataFrame() will release rx packet,
587 // if packet is fragmented
594 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
597 VOID STAHandleRxMgmtFrame(
598 IN PRTMP_ADAPTER pAd,
601 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
602 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
603 PHEADER_802_11 pHeader = pRxBlk->pHeader;
604 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
609 // We should collect RSSI not only U2M data but also my beacon
610 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))
611 && (pAd->RxAnt.EvaluatePeriod == 0))
613 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
615 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
616 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
620 // collect rssi information for antenna diversity
621 if (pAd->NicConfig2.field.AntDiversity)
623 if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))))
625 COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxWI->RSSI0, RSSI_0), 0); //Note: RSSI2 not used on RT73
626 pAd->StaCfg.NumOfAvgRssiSample ++;
631 // First check the size, it MUST not exceed the mlme queue size
632 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
634 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
638 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
639 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
642 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
645 VOID STAHandleRxControlFrame(
646 IN PRTMP_ADAPTER pAd,
649 #ifdef DOT11_N_SUPPORT
650 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
651 #endif // DOT11_N_SUPPORT //
652 PHEADER_802_11 pHeader = pRxBlk->pHeader;
653 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
655 switch (pHeader->FC.SubType)
657 case SUBTYPE_BLOCK_ACK_REQ:
658 #ifdef DOT11_N_SUPPORT
660 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
663 #endif // DOT11_N_SUPPORT //
664 case SUBTYPE_BLOCK_ACK:
670 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
675 ========================================================================
678 Process RxDone interrupt, running in DPC level
681 pAd Pointer to our adapter
686 IRQL = DISPATCH_LEVEL
689 This routine has to maintain Rx ring read pointer.
690 Need to consider QOS DATA format when converting to 802.3
691 ========================================================================
693 BOOLEAN STARxDoneInterruptHandle(
694 IN PRTMP_ADAPTER pAd,
698 UINT32 RxProcessed, RxPending;
699 BOOLEAN bReschedule = FALSE;
700 RT28XX_RXD_STRUC *pRxD;
703 PNDIS_PACKET pRxPacket;
704 PHEADER_802_11 pHeader;
707 RxProcessed = RxPending = 0;
709 // process whole rx ring
713 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
714 fRTMP_ADAPTER_RESET_IN_PROGRESS |
715 fRTMP_ADAPTER_HALT_IN_PROGRESS |
716 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
717 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
723 RxProcessed ++; // test
725 // 1. allocate a new data packet into rx ring to replace received packet
726 // then processing the received packet
727 // 2. the callee must take charge of release of packet
728 // 3. As far as driver is concerned ,
729 // the rx packet must
730 // a. be indicated to upper layer or
731 // b. be released if it is discarded
732 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
733 if (pRxPacket == NULL)
735 // no more packet to process
739 // get rx ring descriptor
740 pRxD = &(RxCell.RxD);
741 // get rx data buffer
742 pData = GET_OS_PKT_DATAPTR(pRxPacket);
743 pRxWI = (PRXWI_STRUC) pData;
744 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
747 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE);
748 RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI);
752 RxCell.pRxWI = pRxWI;
753 RxCell.pHeader = pHeader;
754 RxCell.pRxPacket = pRxPacket;
755 RxCell.pData = (UCHAR *) pHeader;
756 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
759 // Increase Total receive byte counter after real data received no mater any error or not
760 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
761 pAd->RalinkCounters.RxCount ++;
763 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
765 if (pRxWI->MPDUtotalByteCount < 14)
766 Status = NDIS_STATUS_FAILURE;
770 send_monitor_packets(pAd, &RxCell);
773 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
777 pAd->ate.RxCntPerSec++;
778 ATESampleRssi(pAd, pRxWI);
779 #ifdef RALINK_28xx_QA
780 if (pAd->ate.bQARxStart == TRUE)
782 /* (*pRxD) has been swapped in GetPacketFromRxRing() */
783 ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader);
785 #endif // RALINK_28xx_QA //
786 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
789 #endif // RALINK_ATE //
791 // Check for all RxD errors
792 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
794 // Handle the received frame
795 if (Status == NDIS_STATUS_SUCCESS)
797 switch (pHeader->FC.Type)
799 // CASE I, receive a DATA frame
802 // process DATA frame
803 STAHandleRxDataFrame(pAd, &RxCell);
806 // CASE II, receive a MGMT frame
809 STAHandleRxMgmtFrame(pAd, &RxCell);
812 // CASE III. receive a CNTL frame
815 STAHandleRxControlFrame(pAd, &RxCell);
818 // discard other type
820 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
826 pAd->Counters8023.RxErrors++;
827 // discard this frame
828 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
836 ========================================================================
840 pAd Pointer to our adapter
842 IRQL = DISPATCH_LEVEL
844 ========================================================================
846 VOID RTMPHandleTwakeupInterrupt(
847 IN PRTMP_ADAPTER pAd)
849 AsicForceWakeup(pAd, FALSE);
853 ========================================================================
855 Early checking and OS-depened parsing for Tx packet send to our STA driver.
858 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
859 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
860 UINT NumberOfPackets Number of packet in packet array.
866 This function do early checking and classification for send-out packet.
867 You only can put OS-depened & STA related code in here.
868 ========================================================================
871 IN NDIS_HANDLE MiniportAdapterContext,
872 IN PPNDIS_PACKET ppPacketArray,
873 IN UINT NumberOfPackets)
876 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
877 PNDIS_PACKET pPacket;
878 BOOLEAN allowToSend = FALSE;
881 for (Index = 0; Index < NumberOfPackets; Index++)
883 pPacket = ppPacketArray[Index];
888 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
889 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
890 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
892 // Drop send request since hardware is in reset state
895 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
897 // Drop send request since there are no physical connection yet
902 // Record that orignal packet source is from NDIS layer,so that
903 // later on driver knows how to release this NDIS PACKET
904 #ifdef QOS_DLS_SUPPORT
905 MAC_TABLE_ENTRY *pEntry;
906 PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
908 pEntry = MacTableLookup(pAd, pSrcBufVA);
909 if (pEntry && (pEntry->ValidAsDls == TRUE))
911 RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
914 #endif // QOS_DLS_SUPPORT //
915 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
916 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
917 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
918 pAd->RalinkCounters.PendingNdisPacketCount++;
924 if (allowToSend == TRUE)
925 STASendPacket(pAd, pPacket);
927 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
930 // Dequeue outgoing frames from TxSwQueue[] and process it
931 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
937 ========================================================================
939 This routine is used to do packet parsing and classification for Tx packet
940 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
944 pAd Pointer to our adapter
945 pPacket Pointer to send packet
948 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
949 NDIS_STATUS_FAILURE If failed to do en-queue.
952 You only can put OS-indepened & STA related code in here.
953 ========================================================================
955 NDIS_STATUS STASendPacket(
956 IN PRTMP_ADAPTER pAd,
957 IN PNDIS_PACKET pPacket)
959 PACKET_INFO PacketInfo;
964 // UCHAR RTSRequired;
965 UCHAR QueIdx, UserPriority;
966 MAC_TABLE_ENTRY *pEntry = NULL;
967 unsigned int IrqFlags;
971 // Prepare packet information structure for buffer descriptor
972 // chained within a single NDIS packet.
973 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
975 if (pSrcBufVA == NULL)
977 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
978 // Resourece is low, system did not allocate virtual address
979 // return NDIS_STATUS_FAILURE directly to upper layer
980 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
981 return NDIS_STATUS_FAILURE;
987 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
988 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
989 return (NDIS_STATUS_FAILURE);
992 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
993 // Note multicast packets in adhoc also use BSSID_WCID index.
997 #ifdef QOS_DLS_SUPPORT
1000 tmpWcid = RTMP_GET_PACKET_WCID(pPacket);
1001 if (VALID_WCID(tmpWcid) &&
1002 (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE))
1004 pEntry = &pAd->MacTab.Content[tmpWcid];
1005 Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate;
1008 #endif // QOS_DLS_SUPPORT //
1010 pEntry = &pAd->MacTab.Content[BSSID_WCID];
1011 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
1012 Rate = pAd->CommonCfg.TxRate;
1015 else if (ADHOC_ON(pAd))
1017 if (*pSrcBufVA & 0x01)
1019 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
1020 pEntry = &pAd->MacTab.Content[MCAST_WCID];
1024 pEntry = MacTableLookup(pAd, pSrcBufVA);
1026 Rate = pAd->CommonCfg.TxRate;
1032 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
1033 // Resourece is low, system did not allocate virtual address
1034 // return NDIS_STATUS_FAILURE directly to upper layer
1035 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1036 return NDIS_STATUS_FAILURE;
1042 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
1046 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
1047 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
1048 RTMPCheckEtherType(pAd, pPacket);
1053 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
1055 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1056 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1057 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1058 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1059 #ifdef WPA_SUPPLICANT_SUPPORT
1060 || (pAd->StaCfg.IEEE8021X == TRUE)
1061 #endif // WPA_SUPPLICANT_SUPPORT //
1063 || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
1064 #endif // LEAP_SUPPORT //
1066 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1067 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1070 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1071 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1073 return (NDIS_STATUS_FAILURE);
1077 // STEP 1. Decide number of fragments required to deliver this MSDU.
1078 // The estimation here is not very accurate because difficult to
1079 // take encryption overhead into consideration here. The result
1080 // "NumberOfFrag" is then just used to pre-check if enough free
1081 // TXD are available to hold this MSDU.
1084 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1086 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1087 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1088 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1089 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1090 #ifdef DOT11_N_SUPPORT
1091 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1092 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1093 #endif // DOT11_N_SUPPORT //
1096 // The calculated "NumberOfFrag" is a rough estimation because of various
1097 // encryption/encapsulation overhead not taken into consideration. This number is just
1098 // used to make sure enough free TXD are available before fragmentation takes place.
1099 // In case the actual required number of fragments of an NDIS packet
1100 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1101 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1102 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1103 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1105 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1106 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1107 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1108 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1114 // Save fragment number to Ndis packet reserved field
1115 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1118 // STEP 2. Check the requirement of RTS:
1119 // If multiple fragment required, RTS is required only for the first fragment
1120 // if the fragment size large than RTS threshold
1121 // For RT28xx, Let ASIC send RTS/CTS
1122 RTMP_SET_PACKET_RTS(pPacket, 0);
1123 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1126 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1130 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1131 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1134 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1137 // get Ethernet protocol field
1138 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1139 if (Protocol <= 1500)
1141 // get Ethernet protocol field from LLC/SNAP
1142 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1145 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1149 // always AC_BE for non-IP packet
1150 if (Protocol != 0x0800)
1154 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1157 // return AC_BE if packet is not IPv4
1158 if ((Byte0 & 0xf0) != 0x40)
1162 UserPriority = (Byte1 & 0xe0) >> 5;
1163 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1165 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1166 // TODO: downgrade UP & QueIdx before passing ACM
1167 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1175 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1179 // Make sure SendTxWait queue resource won't be used by other threads
1180 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1181 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1183 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1185 StopNetIfQueue(pAd, QueIdx, pPacket);
1186 #endif // BLOCK_NET_IF //
1187 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1189 return NDIS_STATUS_FAILURE;
1193 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1195 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1197 #ifdef DOT11_N_SUPPORT
1198 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1201 //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID];
1202 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1203 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1204 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1205 // For IOT compatibility, if
1206 // 1. It is Ralink chip or
1207 // 2. It is OPEN or AES mode,
1208 // then BA session can be bulit.
1209 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1210 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1213 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1216 #endif // DOT11_N_SUPPORT //
1218 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1219 return NDIS_STATUS_SUCCESS;
1224 ========================================================================
1226 Routine Description:
1227 This subroutine will scan through releative ring descriptor to find
1228 out avaliable free ring descriptor and compare with request size.
1231 pAd Pointer to our adapter
1232 QueIdx Selected TX Ring
1235 NDIS_STATUS_FAILURE Not enough free descriptor
1236 NDIS_STATUS_SUCCESS Enough free descriptor
1238 IRQL = PASSIVE_LEVEL
1239 IRQL = DISPATCH_LEVEL
1243 ========================================================================
1248 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1249 If no frame need to send, go to sleep, else, still wake up.
1251 NDIS_STATUS RTMPFreeTXDRequest(
1252 IN PRTMP_ADAPTER pAd,
1254 IN UCHAR NumberRequired,
1255 IN PUCHAR FreeNumberIs)
1257 //ULONG FreeNumber = 0;
1258 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1259 unsigned long IrqFlags;
1260 HT_TX_CONTEXT *pHTTXContext;
1270 pHTTXContext = &pAd->TxContext[QueIdx];
1271 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1272 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1273 (pHTTXContext->IRPPending == TRUE))
1275 Status = NDIS_STATUS_FAILURE;
1279 Status = NDIS_STATUS_SUCCESS;
1281 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1286 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1287 Status = NDIS_STATUS_FAILURE;
1289 Status = NDIS_STATUS_SUCCESS;
1293 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1303 VOID RTMPSendDisassociationFrame(
1304 IN PRTMP_ADAPTER pAd)
1308 VOID RTMPSendNullFrame(
1309 IN PRTMP_ADAPTER pAd,
1311 IN BOOLEAN bQosNull)
1313 UCHAR NullFrame[48];
1315 PHEADER_802_11 pHeader_802_11;
1323 #endif // RALINK_ATE //
1325 // WPA 802.1x secured port control
1326 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1327 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1328 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1329 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1330 #ifdef WPA_SUPPLICANT_SUPPORT
1331 || (pAd->StaCfg.IEEE8021X == TRUE)
1334 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1339 NdisZeroMemory(NullFrame, 48);
1340 Length = sizeof(HEADER_802_11);
1342 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1344 pHeader_802_11->FC.Type = BTYPE_DATA;
1345 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1346 pHeader_802_11->FC.ToDs = 1;
1347 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1348 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1349 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1351 if (pAd->CommonCfg.bAPSDForcePowerSave)
1353 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1357 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1359 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1362 pHeader_802_11->Sequence = pAd->Sequence;
1364 // Prepare QosNull function frame
1367 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1369 // copy QOS control bytes
1370 NullFrame[Length] = 0;
1371 NullFrame[Length+1] = 0;
1372 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1375 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1379 // IRQL = DISPATCH_LEVEL
1380 VOID RTMPSendRTSFrame(
1381 IN PRTMP_ADAPTER pAd,
1383 IN unsigned int NextMpduSize,
1386 IN USHORT AckDuration,
1394 // --------------------------------------------------------
1395 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1396 // Find the WPA key, either Group or Pairwise Key
1397 // LEAP + TKIP also use WPA key.
1398 // --------------------------------------------------------
1399 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1400 // In Cisco CCX 2.0 Leap Authentication
1401 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1402 // Instead of the SharedKey, SharedKey Length may be Zero.
1403 VOID STAFindCipherAlgorithm(
1404 IN PRTMP_ADAPTER pAd,
1407 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1408 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1409 UCHAR KeyIdx = 0xff;
1411 PCIPHER_KEY pKey = NULL;
1413 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1417 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1418 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1420 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1422 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1424 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1426 // 4-way handshaking frame must be clear
1427 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1428 (pAd->SharedKey[BSS0][0].KeyLen))
1430 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1434 else if (Cipher == Ndis802_11Encryption1Enabled)
1437 if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1439 if (LEAP_CCKM_ON(pAd))
1441 if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1447 KeyIdx = pAd->StaCfg.DefaultKeyId;
1449 else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1450 KeyIdx = pAd->StaCfg.DefaultKeyId;
1451 else if (LEAP_CCKM_ON(pAd))
1453 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1458 else // standard WEP64 or WEP128
1459 #endif // LEAP_SUPPORT //
1460 KeyIdx = pAd->StaCfg.DefaultKeyId;
1462 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1463 (Cipher == Ndis802_11Encryption3Enabled))
1465 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1466 KeyIdx = pAd->StaCfg.DefaultKeyId;
1467 else if (pAd->SharedKey[BSS0][0].KeyLen)
1470 KeyIdx = pAd->StaCfg.DefaultKeyId;
1474 CipherAlg = CIPHER_NONE;
1475 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1476 CipherAlg = CIPHER_NONE;
1477 #ifdef WPA_SUPPLICANT_SUPPORT
1478 else if ( pAd->StaCfg.WpaSupplicantUP &&
1479 (Cipher == Ndis802_11Encryption1Enabled) &&
1480 (pAd->StaCfg.IEEE8021X == TRUE) &&
1481 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1482 CipherAlg = CIPHER_NONE;
1483 #endif // WPA_SUPPLICANT_SUPPORT //
1486 //Header_802_11.FC.Wep = 1;
1487 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1488 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1492 pTxBlk->CipherAlg = CipherAlg;
1493 pTxBlk->pKey = pKey;
1497 VOID STABuildCommon802_11Header(
1498 IN PRTMP_ADAPTER pAd,
1502 HEADER_802_11 *pHeader_802_11;
1503 #ifdef QOS_DLS_SUPPORT
1504 BOOLEAN bDLSFrame = FALSE;
1505 INT DlsEntryIndex = 0;
1506 #endif // QOS_DLS_SUPPORT //
1509 // MAKE A COMMON 802.11 HEADER
1512 // normal wlan header size : 24 octets
1513 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1515 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1517 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1519 pHeader_802_11->FC.FrDs = 0;
1520 pHeader_802_11->FC.Type = BTYPE_DATA;
1521 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1523 #ifdef QOS_DLS_SUPPORT
1526 // Check if the frame can be sent through DLS direct link interface
1527 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1528 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1529 if (DlsEntryIndex >= 0)
1534 #endif // QOS_DLS_SUPPORT //
1536 if (pTxBlk->pMacEntry)
1538 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1540 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1541 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1545 #ifdef QOS_DLS_SUPPORT
1548 pHeader_802_11->Sequence = pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence;
1549 pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence = (pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence+1) & MAXSEQ;
1552 #endif // QOS_DLS_SUPPORT //
1554 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1555 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1561 pHeader_802_11->Sequence = pAd->Sequence;
1562 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1565 pHeader_802_11->Frag = 0;
1567 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1572 #ifdef QOS_DLS_SUPPORT
1575 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1576 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1577 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1578 pHeader_802_11->FC.ToDs = 0;
1581 #endif // QOS_DLS_SUPPORT //
1583 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1584 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1585 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1586 pHeader_802_11->FC.ToDs = 1;
1589 else if (ADHOC_ON(pAd))
1591 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1592 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1593 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1594 pHeader_802_11->FC.ToDs = 0;
1598 if (pTxBlk->CipherAlg != CIPHER_NONE)
1599 pHeader_802_11->FC.Wep = 1;
1601 // -----------------------------------------------------------------
1602 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1603 // -----------------------------------------------------------------
1604 if (pAd->CommonCfg.bAPSDForcePowerSave)
1605 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1607 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1610 #ifdef DOT11_N_SUPPORT
1611 VOID STABuildCache802_11Header(
1612 IN RTMP_ADAPTER *pAd,
1616 MAC_TABLE_ENTRY *pMacEntry;
1617 PHEADER_802_11 pHeader80211;
1619 pHeader80211 = (PHEADER_802_11)pHeader;
1620 pMacEntry = pTxBlk->pMacEntry;
1623 // Update the cached 802.11 HEADER
1626 // normal wlan header size : 24 octets
1627 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1630 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1633 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1634 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1637 // Check if the frame can be sent through DLS direct link interface
1638 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1639 #ifdef QOS_DLS_SUPPORT
1640 BOOLEAN bDLSFrame = FALSE;
1641 INT DlsEntryIndex = 0;
1643 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1644 if (DlsEntryIndex >= 0)
1648 #endif // QOS_DLS_SUPPORT //
1650 // The addr3 of normal packet send from DS is Dest Mac address.
1651 #ifdef QOS_DLS_SUPPORT
1654 COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
1655 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1656 pHeader80211->FC.ToDs = 0;
1659 #endif // QOS_DLS_SUPPORT //
1661 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1663 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1666 // -----------------------------------------------------------------
1667 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1668 // -----------------------------------------------------------------
1669 if (pAd->CommonCfg.bAPSDForcePowerSave)
1670 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1672 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1674 #endif // DOT11_N_SUPPORT //
1676 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1677 IN RTMP_ADAPTER *pAd,
1680 PUCHAR pHeaderBufPtr;
1681 HEADER_802_11 *pHeader_802_11;
1682 PNDIS_PACKET pNextPacket;
1684 PQUEUE_ENTRY pQEntry;
1686 STAFindCipherAlgorithm(pAd, pTxBlk);
1687 STABuildCommon802_11Header(pAd, pTxBlk);
1690 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1691 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1693 // steal "order" bit to mark "aggregation"
1694 pHeader_802_11->FC.Order = 1;
1696 // skip common header
1697 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1699 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1702 // build QOS Control bytes
1704 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1706 *(pHeaderBufPtr+1) = 0;
1708 pTxBlk->MpduHeaderLen += 2;
1711 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1712 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1713 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1714 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1716 // For RA Aggregation,
1717 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1718 pQEntry = pTxBlk->TxPacketList.Head;
1719 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1720 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1721 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1722 nextBufLen -= LENGTH_802_1Q;
1724 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1725 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1728 pTxBlk->MpduHeaderLen += 2;
1730 return pHeaderBufPtr;
1734 #ifdef DOT11_N_SUPPORT
1735 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1736 IN RTMP_ADAPTER *pAd,
1739 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1740 HEADER_802_11 *pHeader_802_11;
1743 STAFindCipherAlgorithm(pAd, pTxBlk);
1744 STABuildCommon802_11Header(pAd, pTxBlk);
1746 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1747 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1749 // skip common header
1750 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1753 // build QOS Control bytes
1755 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1760 *pHeaderBufPtr |= 0x80;
1762 *(pHeaderBufPtr+1) = 0;
1764 pTxBlk->MpduHeaderLen += 2;
1766 //pSaveBufPtr = pHeaderBufPtr;
1769 // padding at front of LLC header
1770 // LLC header should locate at 4-octets aligment
1772 // @@@ MpduHeaderLen excluding padding @@@
1774 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1775 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1776 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1778 return pHeaderBufPtr;
1783 VOID STA_AMPDU_Frame_Tx(
1784 IN PRTMP_ADAPTER pAd,
1787 HEADER_802_11 *pHeader_802_11;
1788 PUCHAR pHeaderBufPtr;
1790 MAC_TABLE_ENTRY *pMacEntry;
1792 PQUEUE_ENTRY pQEntry;
1796 while(pTxBlk->TxPacketList.Head)
1798 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1799 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1800 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1802 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1806 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1808 pMacEntry = pTxBlk->pMacEntry;
1809 if (pMacEntry->isCached)
1811 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1812 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1813 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1814 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1818 STAFindCipherAlgorithm(pAd, pTxBlk);
1819 STABuildCommon802_11Header(pAd, pTxBlk);
1821 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1825 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1827 // skip common header
1828 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1831 // build QOS Control bytes
1833 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1834 *(pHeaderBufPtr+1) = 0;
1836 pTxBlk->MpduHeaderLen += 2;
1840 // HTC control filed following QoS field
1842 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1844 if (pMacEntry->isCached == FALSE)
1847 pHeader_802_11->FC.Order = 1;
1849 NdisZeroMemory(pHeaderBufPtr, 4);
1850 *(pHeaderBufPtr+3) |= 0x80;
1853 pTxBlk->MpduHeaderLen += 4;
1856 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1857 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1859 // skip 802.3 header
1860 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1861 pTxBlk->SrcBufLen -= LENGTH_802_3;
1866 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1867 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1871 // padding at front of LLC header
1872 // LLC header should locate at 4-octets aligment
1874 // @@@ MpduHeaderLen excluding padding @@@
1876 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1877 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1878 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1883 // Insert LLC-SNAP encapsulation - 8 octets
1885 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1886 if (pTxBlk->pExtraLlcSnapEncap)
1888 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1890 // get 2 octets (TypeofLen)
1891 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1893 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1898 if (pMacEntry->isCached)
1900 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1904 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1906 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1907 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1908 pMacEntry->isCached = TRUE;
1911 // calculate Transmitted AMPDU count and ByteCount
1913 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1914 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1917 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1919 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1924 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1926 pAd->RalinkCounters.KickTxCount++;
1927 pAd->RalinkCounters.OneSecTxDoneCount++;
1933 VOID STA_AMSDU_Frame_Tx(
1934 IN PRTMP_ADAPTER pAd,
1937 PUCHAR pHeaderBufPtr;
1939 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1940 USHORT totalMPDUSize=0;
1941 UCHAR *subFrameHeader;
1943 USHORT FirstTx = 0, LastTxIdx = 0;
1946 PQUEUE_ENTRY pQEntry;
1951 ASSERT((pTxBlk->TxPacketList.Number > 1));
1953 while(pTxBlk->TxPacketList.Head)
1955 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1956 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1957 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1959 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1963 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1965 // skip 802.3 header
1966 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1967 pTxBlk->SrcBufLen -= LENGTH_802_3;
1972 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1973 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1978 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1980 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1981 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1985 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1986 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1987 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1988 pHeaderBufPtr += padding;
1989 pTxBlk->MpduHeaderLen = padding;
1994 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1996 subFrameHeader = pHeaderBufPtr;
1997 subFramePayloadLen = pTxBlk->SrcBufLen;
1999 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
2002 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
2003 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
2007 // Insert LLC-SNAP encapsulation - 8 octets
2009 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2011 subFramePayloadLen = pTxBlk->SrcBufLen;
2013 if (pTxBlk->pExtraLlcSnapEncap)
2015 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2017 // get 2 octets (TypeofLen)
2018 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2020 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2021 subFramePayloadLen += LENGTH_802_1_H;
2024 // update subFrame Length field
2025 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
2026 subFrameHeader[13] = subFramePayloadLen & 0xFF;
2028 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2031 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2033 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2037 pAd->RalinkCounters.KickTxCount++;
2038 pAd->RalinkCounters.OneSecTxDoneCount++;
2040 // calculate Transmitted AMSDU Count and ByteCount
2042 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
2043 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
2048 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2049 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2054 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2056 #endif // DOT11_N_SUPPORT //
2058 VOID STA_Legacy_Frame_Tx(
2059 IN PRTMP_ADAPTER pAd,
2062 HEADER_802_11 *pHeader_802_11;
2063 PUCHAR pHeaderBufPtr;
2066 PQUEUE_ENTRY pQEntry;
2071 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2072 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2073 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2075 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2079 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
2081 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
2084 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
2085 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
2087 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
2089 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2091 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
2092 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
2094 STAFindCipherAlgorithm(pAd, pTxBlk);
2095 STABuildCommon802_11Header(pAd, pTxBlk);
2098 // skip 802.3 header
2099 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2100 pTxBlk->SrcBufLen -= LENGTH_802_3;
2105 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2106 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2109 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2110 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
2112 // skip common header
2113 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2115 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2118 // build QOS Control bytes
2120 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2121 *(pHeaderBufPtr+1) = 0;
2123 pTxBlk->MpduHeaderLen += 2;
2126 // The remaining content of MPDU header should locate at 4-octets aligment
2127 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2128 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2129 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2134 // Insert LLC-SNAP encapsulation - 8 octets
2137 // if original Ethernet frame contains no LLC/SNAP,
2138 // then an extra LLC/SNAP encap is required
2140 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2141 if (pTxBlk->pExtraLlcSnapEncap)
2145 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2148 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2149 // get 2 octets (TypeofLen)
2150 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2152 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2159 // use Wcid as Key Index
2162 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2164 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2166 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2168 pAd->RalinkCounters.KickTxCount++;
2169 pAd->RalinkCounters.OneSecTxDoneCount++;
2174 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2178 VOID STA_ARalink_Frame_Tx(
2179 IN PRTMP_ADAPTER pAd,
2182 PUCHAR pHeaderBufPtr;
2184 USHORT totalMPDUSize=0;
2185 USHORT FirstTx, LastTxIdx;
2188 PQUEUE_ENTRY pQEntry;
2193 ASSERT((pTxBlk->TxPacketList.Number== 2));
2196 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2197 while(pTxBlk->TxPacketList.Head)
2199 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2200 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2202 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2204 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2208 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2210 // skip 802.3 header
2211 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2212 pTxBlk->SrcBufLen -= LENGTH_802_3;
2217 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2218 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2222 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2224 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2226 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2227 // will be updated after final frame was handled.
2228 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2232 // Insert LLC-SNAP encapsulation - 8 octets
2234 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2236 if (pTxBlk->pExtraLlcSnapEncap)
2238 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2240 // get 2 octets (TypeofLen)
2241 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2243 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2247 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2249 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2250 pTxBlk->MpduHeaderLen = 0;
2252 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2253 // DA(6)+SA(6)+FrameType(2)
2254 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2255 pHeaderBufPtr += 12;
2256 // get 2 octets (TypeofLen)
2257 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2259 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2262 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2264 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2266 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2268 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2272 pAd->RalinkCounters.OneSecTxAggregationCount++;
2273 pAd->RalinkCounters.KickTxCount++;
2274 pAd->RalinkCounters.OneSecTxDoneCount++;
2278 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2279 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2284 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2289 VOID STA_Fragment_Frame_Tx(
2290 IN RTMP_ADAPTER *pAd,
2293 HEADER_802_11 *pHeader_802_11;
2294 PUCHAR pHeaderBufPtr;
2297 PACKET_INFO PacketInfo;
2298 USHORT EncryptionOverhead = 0;
2299 UINT32 FreeMpduSize, SrcRemainingBytes;
2303 PQUEUE_ENTRY pQEntry;
2308 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2309 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2310 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2312 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2316 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2317 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2319 STAFindCipherAlgorithm(pAd, pTxBlk);
2320 STABuildCommon802_11Header(pAd, pTxBlk);
2322 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2324 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2325 if (pTxBlk->pPacket == NULL)
2327 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2330 // skip 802.3 header
2331 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2332 pTxBlk->SrcBufLen -= LENGTH_802_3;
2338 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2339 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2342 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2343 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2346 // skip common header
2347 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2349 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2352 // build QOS Control bytes
2354 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2356 *(pHeaderBufPtr+1) = 0;
2358 pTxBlk->MpduHeaderLen += 2;
2362 // padding at front of LLC header
2363 // LLC header should locate at 4-octets aligment
2365 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2366 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2367 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2372 // Insert LLC-SNAP encapsulation - 8 octets
2375 // if original Ethernet frame contains no LLC/SNAP,
2376 // then an extra LLC/SNAP encap is required
2378 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2379 if (pTxBlk->pExtraLlcSnapEncap)
2383 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2386 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2387 // get 2 octets (TypeofLen)
2388 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2390 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2394 // If TKIP is used and fragmentation is required. Driver has to
2395 // append TKIP MIC at tail of the scatter buffer
2396 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2397 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2400 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2401 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2402 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2403 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2404 pTxBlk->SrcBufLen += 8;
2405 pTxBlk->TotalFrameLen += 8;
2406 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2410 // calcuate the overhead bytes that encryption algorithm may add. This
2411 // affects the calculate of "duration" field
2413 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2414 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2415 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2416 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2417 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2418 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2419 else if (pTxBlk->CipherAlg == CIPHER_AES)
2420 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2422 EncryptionOverhead = 0;
2424 // decide how much time an ACK/CTS frame will consume in the air
2425 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2427 // Init the total payload length of this frame.
2428 SrcRemainingBytes = pTxBlk->SrcBufLen;
2430 pTxBlk->TotalFragNum = 0xff;
2434 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2436 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2438 if (SrcRemainingBytes <= FreeMpduSize)
2439 { // this is the last or only fragment
2441 pTxBlk->SrcBufLen = SrcRemainingBytes;
2443 pHeader_802_11->FC.MoreFrag = 0;
2444 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2446 // Indicate the lower layer that this's the last fragment.
2447 pTxBlk->TotalFragNum = fragNum;
2450 { // more fragment is required
2452 pTxBlk->SrcBufLen = FreeMpduSize;
2454 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2455 pHeader_802_11->FC.MoreFrag = 1;
2456 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2460 pTxBlk->FrameGap = IFS_HTTXOP;
2462 pTxBlk->FrameGap = IFS_SIFS;
2464 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2466 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2468 pAd->RalinkCounters.KickTxCount++;
2469 pAd->RalinkCounters.OneSecTxDoneCount++;
2471 // Update the frame number, remaining size of the NDIS packet payload.
2473 // space for 802.11 header.
2474 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2475 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2478 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2479 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2481 pHeader_802_11->Frag++; // increase Frag #
2483 }while(SrcRemainingBytes > 0);
2488 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2492 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2493 while(_pTxBlk->TxPacketList.Head) \
2495 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2496 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2501 ========================================================================
2503 Routine Description:
2504 Copy frame from waiting queue into relative ring buffer and set
2505 appropriate ASIC register to kick hardware encryption before really
2509 pAd Pointer to our adapter
2510 PNDIS_PACKET Pointer to outgoing Ndis frame
2511 NumberOfFrag Number of fragment required
2516 IRQL = DISPATCH_LEVEL
2520 ========================================================================
2522 NDIS_STATUS STAHardTransmit(
2523 IN PRTMP_ADAPTER pAd,
2527 NDIS_PACKET *pPacket;
2528 PQUEUE_ENTRY pQEntry;
2530 // ---------------------------------------------
2531 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2532 // ---------------------------------------------
2534 ASSERT(pTxBlk->TxPacketList.Number);
2535 if (pTxBlk->TxPacketList.Head == NULL)
2537 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2538 return NDIS_STATUS_FAILURE;
2541 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2543 // ------------------------------------------------------------------
2544 // STEP 1. WAKE UP PHY
2545 // outgoing frame always wakeup PHY to prevent frame lost and
2546 // turn off PSM bit to improve performance
2547 // ------------------------------------------------------------------
2548 // not to change PSM bit, just send this frame out?
2549 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2551 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2552 AsicForceWakeup(pAd, TRUE);
2555 // It should not change PSM bit, when APSD turn on.
2556 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2557 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2558 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2560 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2561 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2562 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2565 switch (pTxBlk->TxFrameType)
2567 #ifdef DOT11_N_SUPPORT
2568 case TX_AMPDU_FRAME:
2569 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2571 case TX_AMSDU_FRAME:
2572 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2574 #endif // DOT11_N_SUPPORT //
2575 case TX_LEGACY_FRAME:
2576 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2578 case TX_MCAST_FRAME:
2579 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2581 case TX_RALINK_FRAME:
2582 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2585 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2589 // It should not happened!
2590 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2591 while(pTxBlk->TxPacketList.Number)
2593 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2594 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2596 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2602 return (NDIS_STATUS_SUCCESS);
2606 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2608 unsigned char *word = value;
2609 unsigned int ret = 0;
2612 for(i=0; i < len; i++)
2615 ret ^=(unsigned int) (word[i]) << mod;
2616 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2621 VOID Sta_Announce_or_Forward_802_3_Packet(
2622 IN PRTMP_ADAPTER pAd,
2623 IN PNDIS_PACKET pPacket,
2624 IN UCHAR FromWhichBSSID)
2629 announce_802_3_packet(pAd, pPacket);
2634 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);