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;
53 #ifdef WPA_SUPPLICANT_SUPPORT
54 if (pAd->StaCfg.WpaSupplicantUP)
56 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
57 // TBD : process fragmented EAPol frames
59 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
60 if ( pAd->StaCfg.IEEE8021X == TRUE &&
61 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
67 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
68 STA_PORT_SECURED(pAd);
70 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
72 idx = pAd->StaCfg.DesireSharedKeyId;
73 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
74 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
76 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
78 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
80 // Set key material and cipherAlg to Asic
81 AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
83 // Assign group key info
84 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
86 // Assign pairwise key info
87 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
89 pAd->IndicateMediaState = NdisMediaStateConnected;
90 pAd->ExtraInfo = GENERAL_LINK_UP;
91 // For Preventing ShardKey Table is cleared by remove key procedure.
92 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
93 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
94 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
95 pAd->StaCfg.DesireSharedKey[idx].Key,
96 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
101 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
106 #endif // WPA_SUPPLICANT_SUPPORT //
108 // Special DATA frame that has to pass to MLME
109 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
110 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
112 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
113 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
114 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
115 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
119 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
124 VOID STARxDataFrameAnnounce(
125 IN PRTMP_ADAPTER pAd,
126 IN MAC_TABLE_ENTRY *pEntry,
128 IN UCHAR FromWhichBSSID)
132 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
135 // drop all non-EAP DATA frame before
136 // this client's Port-Access-Control is secured
137 if (pRxBlk->pHeader->FC.Wep)
139 // unsupported cipher suite
140 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
143 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
149 // encryption in-use but receive a non-EAPOL clear text frame, drop it
150 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
151 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
154 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
159 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
160 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
162 // Normal legacy, AMPDU or AMSDU
163 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
169 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
171 #ifdef QOS_DLS_SUPPORT
172 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS);
173 #endif // QOS_DLS_SUPPORT //
177 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
178 #ifdef DOT11_N_SUPPORT
179 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
181 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
184 #endif // DOT11_N_SUPPORT //
186 // Determin the destination of the EAP frame
187 // to WPA state machine or upper layer
188 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
194 // For TKIP frame, calculate the MIC value
195 BOOLEAN STACheckTkipMICValue(
196 IN PRTMP_ADAPTER pAd,
197 IN MAC_TABLE_ENTRY *pEntry,
200 PHEADER_802_11 pHeader = pRxBlk->pHeader;
201 UCHAR *pData = pRxBlk->pData;
202 USHORT DataSize = pRxBlk->DataSize;
203 UCHAR UserPriority = pRxBlk->UserPriority;
207 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
209 pDA = pHeader->Addr1;
210 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
212 pSA = pHeader->Addr3;
216 pSA = pHeader->Addr2;
219 if (RTMPTkipCompareMICValue(pAd,
227 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
229 #ifdef WPA_SUPPLICANT_SUPPORT
230 if (pAd->StaCfg.WpaSupplicantUP)
232 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
235 #endif // WPA_SUPPLICANT_SUPPORT //
237 RTMPReportMicError(pAd, pWpaKey);
241 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
250 // All Rx routines use RX_BLK structure to hande rx events
251 // It is very important to build pRxBlk attributes
252 // 1. pHeader pointer to 802.11 Header
253 // 2. pData pointer to payload including LLC (just skip Header)
254 // 3. set payload size including LLC to DataSize
255 // 4. set some flags with RX_BLK_SET_FLAG()
257 VOID STAHandleRxDataFrame(
258 IN PRTMP_ADAPTER pAd,
261 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
262 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
263 PHEADER_802_11 pHeader = pRxBlk->pHeader;
264 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
265 BOOLEAN bFragment = FALSE;
266 MAC_TABLE_ENTRY *pEntry = NULL;
267 UCHAR FromWhichBSSID = BSS0;
268 UCHAR UserPriority = 0;
271 // before LINK UP, all DATA frames are rejected
272 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
275 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
279 #ifdef QOS_DLS_SUPPORT
280 //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
281 if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD))
285 #endif // QOS_DLS_SUPPORT //
287 // Drop not my BSS frames
288 if (pRxD->MyBss == 0)
292 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
297 pAd->RalinkCounters.RxCountSinceLastNULL++;
298 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
301 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
304 pData = (PUCHAR)pHeader + LENGTH_802_11;
305 if ((*pData >> 4) & 0x01)
307 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
308 pAd->CommonCfg.bInServicePeriod = FALSE;
310 // Force driver to fall into sleep mode when rcv EOSP frame
311 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
313 USHORT TbttNumToNextWakeUp;
314 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
317 NdisGetSystemUpTime(&Now);
318 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
320 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
321 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
322 TbttNumToNextWakeUp = NextDtim;
324 MlmeSetPsmBit(pAd, PWR_SAVE);
325 // if WMM-APSD is failed, try to disable following line
326 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
330 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
332 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
336 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
337 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
340 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
344 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
345 #ifdef QOS_DLS_SUPPORT
346 if (!pAd->CommonCfg.bDLSCapable)
348 #endif // QOS_DLS_SUPPORT //
351 // Infrastructure mode, check address 2 for BSSID
352 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
354 // Receive frame not my BSSID
356 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
360 else // Ad-Hoc mode or Not associated
362 // Ad-Hoc mode, check address 3 for BSSID
363 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
365 // Receive frame not my BSSID
367 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
371 #ifdef QOS_DLS_SUPPORT
373 #endif // QOS_DLS_SUPPORT //
378 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
380 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
384 // 1. release packet if infra mode
385 // 2. new a pEntry if ad-hoc mode
386 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
393 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
394 #ifdef QOS_DLS_SUPPORT
395 if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
396 RX_BLK_SET_FLAG(pRxBlk, fRX_DLS);
398 #endif // QOS_DLS_SUPPORT //
399 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
402 // check Atheros Client
403 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
405 pEntry->bIAmBadAtheros = TRUE;
406 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
407 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
408 if (!STA_AES_ON(pAd))
410 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
415 pRxBlk->pData = (UCHAR *)pHeader;
418 // update RxBlk->pData, DataSize
419 // 802.11 Header, QOS, HTC, Hw Padding
422 // 1. skip 802.11 HEADER
424 pRxBlk->pData += LENGTH_802_11;
425 pRxBlk->DataSize -= LENGTH_802_11;
429 if (pHeader->FC.SubType & 0x08)
431 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
432 UserPriority = *(pRxBlk->pData) & 0x0f;
433 // bit 7 in QoS Control field signals the HT A-MSDU format
434 if ((*pRxBlk->pData) & 0x80)
436 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
439 // skip QOS contorl field
441 pRxBlk->DataSize -=2;
443 pRxBlk->UserPriority = UserPriority;
445 // 3. Order bit: A-Ralink or HTC+
446 if (pHeader->FC.Order)
448 #ifdef AGGREGATION_SUPPORT
449 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
451 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
456 #ifdef DOT11_N_SUPPORT
457 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
458 // skip HTC contorl field
460 pRxBlk->DataSize -= 4;
461 #endif // DOT11_N_SUPPORT //
465 // 4. skip HW padding
468 // just move pData pointer
469 // because DataSize excluding HW padding
470 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
474 #ifdef DOT11_N_SUPPORT
477 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
479 #endif // DOT11_N_SUPPORT //
483 // Case I Process Broadcast & Multicast data frame
485 if (pRxD->Bcast || pRxD->Mcast)
487 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
489 // Drop Mcast/Bcast frame with fragment bit on
490 if (pHeader->FC.MoreFrag)
493 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
497 // Filter out Bcast frame which AP relayed for us
498 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
501 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
505 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
510 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
513 #ifdef QOS_DLS_SUPPORT
514 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS))
516 MAC_TABLE_ENTRY *pDlsEntry = NULL;
518 pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE);
520 Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI);
523 #endif // QOS_DLS_SUPPORT //
526 pEntry = MacTableLookup(pAd, pHeader->Addr2);
528 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
532 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
534 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
535 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
537 pAd->RalinkCounters.OneSecRxOkDataCnt++;
540 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
542 // re-assemble the fragmented packets
543 // return complete frame (pRxPacket) or NULL
545 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
550 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
552 // process complete frame
553 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
556 pRxBlk->DataSize -= 8;
558 // For TKIP frame, calculate the MIC value
559 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
565 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
571 // because RTMPDeFragmentDataFrame() will release rx packet,
572 // if packet is fragmented
579 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
582 VOID STAHandleRxMgmtFrame(
583 IN PRTMP_ADAPTER pAd,
586 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
587 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
588 PHEADER_802_11 pHeader = pRxBlk->pHeader;
589 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
594 // We should collect RSSI not only U2M data but also my beacon
595 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
597 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
599 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
600 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
603 // First check the size, it MUST not exceed the mlme queue size
604 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
606 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
610 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
611 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
614 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
617 VOID STAHandleRxControlFrame(
618 IN PRTMP_ADAPTER pAd,
621 #ifdef DOT11_N_SUPPORT
622 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
623 #endif // DOT11_N_SUPPORT //
624 PHEADER_802_11 pHeader = pRxBlk->pHeader;
625 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
627 switch (pHeader->FC.SubType)
629 case SUBTYPE_BLOCK_ACK_REQ:
630 #ifdef DOT11_N_SUPPORT
632 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
635 #endif // DOT11_N_SUPPORT //
636 case SUBTYPE_BLOCK_ACK:
642 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
647 ========================================================================
650 Process RxDone interrupt, running in DPC level
653 pAd Pointer to our adapter
658 IRQL = DISPATCH_LEVEL
661 This routine has to maintain Rx ring read pointer.
662 Need to consider QOS DATA format when converting to 802.3
663 ========================================================================
665 BOOLEAN STARxDoneInterruptHandle(
666 IN PRTMP_ADAPTER pAd,
670 UINT32 RxProcessed, RxPending;
671 BOOLEAN bReschedule = FALSE;
672 RT28XX_RXD_STRUC *pRxD;
675 PNDIS_PACKET pRxPacket;
676 PHEADER_802_11 pHeader;
679 RxProcessed = RxPending = 0;
681 // process whole rx ring
685 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
686 fRTMP_ADAPTER_RESET_IN_PROGRESS |
687 fRTMP_ADAPTER_HALT_IN_PROGRESS |
688 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
689 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
694 if (RxProcessed++ > MAX_RX_PROCESS_CNT)
696 // need to reschedule rx handle
701 RxProcessed ++; // test
703 // 1. allocate a new data packet into rx ring to replace received packet
704 // then processing the received packet
705 // 2. the callee must take charge of release of packet
706 // 3. As far as driver is concerned ,
707 // the rx packet must
708 // a. be indicated to upper layer or
709 // b. be released if it is discarded
710 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
711 if (pRxPacket == NULL)
713 // no more packet to process
717 // get rx ring descriptor
718 pRxD = &(RxCell.RxD);
719 // get rx data buffer
720 pData = GET_OS_PKT_DATAPTR(pRxPacket);
721 pRxWI = (PRXWI_STRUC) pData;
722 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
725 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE);
726 RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI);
730 RxCell.pRxWI = pRxWI;
731 RxCell.pHeader = pHeader;
732 RxCell.pRxPacket = pRxPacket;
733 RxCell.pData = (UCHAR *) pHeader;
734 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
737 // Increase Total receive byte counter after real data received no mater any error or not
738 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
739 pAd->RalinkCounters.RxCount ++;
741 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
743 if (pRxWI->MPDUtotalByteCount < 14)
744 Status = NDIS_STATUS_FAILURE;
748 send_monitor_packets(pAd, &RxCell);
751 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
753 // Check for all RxD errors
754 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
756 // Handle the received frame
757 if (Status == NDIS_STATUS_SUCCESS)
759 switch (pHeader->FC.Type)
761 // CASE I, receive a DATA frame
764 // process DATA frame
765 STAHandleRxDataFrame(pAd, &RxCell);
768 // CASE II, receive a MGMT frame
771 STAHandleRxMgmtFrame(pAd, &RxCell);
774 // CASE III. receive a CNTL frame
777 STAHandleRxControlFrame(pAd, &RxCell);
780 // discard other type
782 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
788 pAd->Counters8023.RxErrors++;
789 // discard this frame
790 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
794 // fRTMP_PS_GO_TO_SLEEP_NOW is set if receiving beacon.
795 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW) && (INFRA_ON(pAd)))
797 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
798 AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp);
805 ========================================================================
809 pAd Pointer to our adapter
811 IRQL = DISPATCH_LEVEL
813 ========================================================================
815 VOID RTMPHandleTwakeupInterrupt(
816 IN PRTMP_ADAPTER pAd)
818 AsicForceWakeup(pAd, DOT11POWERSAVE);
822 ========================================================================
824 Early checking and OS-depened parsing for Tx packet send to our STA driver.
827 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
828 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
829 UINT NumberOfPackets Number of packet in packet array.
835 This function do early checking and classification for send-out packet.
836 You only can put OS-depened & STA related code in here.
837 ========================================================================
840 IN NDIS_HANDLE MiniportAdapterContext,
841 IN PPNDIS_PACKET ppPacketArray,
842 IN UINT NumberOfPackets)
845 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
846 PNDIS_PACKET pPacket;
847 BOOLEAN allowToSend = FALSE;
850 for (Index = 0; Index < NumberOfPackets; Index++)
852 pPacket = ppPacketArray[Index];
856 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
857 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
858 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
860 // Drop send request since hardware is in reset state
863 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
865 // Drop send request since there are no physical connection yet
870 // Record that orignal packet source is from NDIS layer,so that
871 // later on driver knows how to release this NDIS PACKET
872 #ifdef QOS_DLS_SUPPORT
873 MAC_TABLE_ENTRY *pEntry;
874 PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
876 pEntry = MacTableLookup(pAd, pSrcBufVA);
877 if (pEntry && (pEntry->ValidAsDls == TRUE))
879 RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
882 #endif // QOS_DLS_SUPPORT //
883 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
884 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
885 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
886 pAd->RalinkCounters.PendingNdisPacketCount++;
892 if (allowToSend == TRUE)
893 STASendPacket(pAd, pPacket);
895 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
898 // Dequeue outgoing frames from TxSwQueue[] and process it
899 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
905 ========================================================================
907 This routine is used to do packet parsing and classification for Tx packet
908 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
912 pAd Pointer to our adapter
913 pPacket Pointer to send packet
916 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
917 NDIS_STATUS_FAILURE If failed to do en-queue.
920 You only can put OS-indepened & STA related code in here.
921 ========================================================================
923 NDIS_STATUS STASendPacket(
924 IN PRTMP_ADAPTER pAd,
925 IN PNDIS_PACKET pPacket)
927 PACKET_INFO PacketInfo;
932 UCHAR QueIdx, UserPriority;
933 MAC_TABLE_ENTRY *pEntry = NULL;
934 unsigned int IrqFlags;
938 // Prepare packet information structure for buffer descriptor
939 // chained within a single NDIS packet.
940 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
942 if (pSrcBufVA == NULL)
944 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
945 // Resourece is low, system did not allocate virtual address
946 // return NDIS_STATUS_FAILURE directly to upper layer
947 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
948 return NDIS_STATUS_FAILURE;
954 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
955 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
956 return (NDIS_STATUS_FAILURE);
959 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
960 // Note multicast packets in adhoc also use BSSID_WCID index.
964 #ifdef QOS_DLS_SUPPORT
967 tmpWcid = RTMP_GET_PACKET_WCID(pPacket);
968 if (VALID_WCID(tmpWcid) &&
969 (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE))
971 pEntry = &pAd->MacTab.Content[tmpWcid];
972 Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate;
975 #endif // QOS_DLS_SUPPORT //
977 pEntry = &pAd->MacTab.Content[BSSID_WCID];
978 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
979 Rate = pAd->CommonCfg.TxRate;
982 else if (ADHOC_ON(pAd))
984 if (*pSrcBufVA & 0x01)
986 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
987 pEntry = &pAd->MacTab.Content[MCAST_WCID];
991 pEntry = MacTableLookup(pAd, pSrcBufVA);
993 Rate = pAd->CommonCfg.TxRate;
999 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
1000 // Resourece is low, system did not allocate virtual address
1001 // return NDIS_STATUS_FAILURE directly to upper layer
1002 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1003 return NDIS_STATUS_FAILURE;
1009 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
1013 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
1014 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
1015 RTMPCheckEtherType(pAd, pPacket);
1020 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
1022 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1023 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1024 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1025 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1026 #ifdef WPA_SUPPLICANT_SUPPORT
1027 || (pAd->StaCfg.IEEE8021X == TRUE)
1028 #endif // WPA_SUPPLICANT_SUPPORT //
1030 || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
1031 #endif // LEAP_SUPPORT //
1033 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1034 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1037 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1038 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1040 return (NDIS_STATUS_FAILURE);
1044 // STEP 1. Decide number of fragments required to deliver this MSDU.
1045 // The estimation here is not very accurate because difficult to
1046 // take encryption overhead into consideration here. The result
1047 // "NumberOfFrag" is then just used to pre-check if enough free
1048 // TXD are available to hold this MSDU.
1051 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1053 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1054 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1055 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1056 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1057 #ifdef DOT11_N_SUPPORT
1058 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1059 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1060 #endif // DOT11_N_SUPPORT //
1063 // The calculated "NumberOfFrag" is a rough estimation because of various
1064 // encryption/encapsulation overhead not taken into consideration. This number is just
1065 // used to make sure enough free TXD are available before fragmentation takes place.
1066 // In case the actual required number of fragments of an NDIS packet
1067 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1068 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1069 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1070 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1072 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1073 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1074 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1075 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1081 // Save fragment number to Ndis packet reserved field
1082 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1085 // STEP 2. Check the requirement of RTS:
1086 // If multiple fragment required, RTS is required only for the first fragment
1087 // if the fragment size large than RTS threshold
1088 // For RT28xx, Let ASIC send RTS/CTS
1089 RTMP_SET_PACKET_RTS(pPacket, 0);
1090 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1093 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1097 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1100 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1103 // get Ethernet protocol field
1104 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1105 if (Protocol <= 1500)
1107 // get Ethernet protocol field from LLC/SNAP
1108 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1111 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1115 // always AC_BE for non-IP packet
1116 if (Protocol != 0x0800)
1120 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1123 // return AC_BE if packet is not IPv4
1124 if ((Byte0 & 0xf0) != 0x40)
1128 UserPriority = (Byte1 & 0xe0) >> 5;
1129 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1131 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1132 // TODO: downgrade UP & QueIdx before passing ACM
1133 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1141 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1145 // Make sure SendTxWait queue resource won't be used by other threads
1146 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1147 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1149 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1151 StopNetIfQueue(pAd, QueIdx, pPacket);
1152 #endif // BLOCK_NET_IF //
1153 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1155 return NDIS_STATUS_FAILURE;
1159 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1161 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1163 #ifdef DOT11_N_SUPPORT
1164 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1165 (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1167 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1168 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1169 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1170 // For IOT compatibility, if
1171 // 1. It is Ralink chip or
1172 // 2. It is OPEN or AES mode,
1173 // then BA session can be bulit.
1174 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1175 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1178 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1181 #endif // DOT11_N_SUPPORT //
1183 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1184 return NDIS_STATUS_SUCCESS;
1189 ========================================================================
1191 Routine Description:
1192 This subroutine will scan through releative ring descriptor to find
1193 out avaliable free ring descriptor and compare with request size.
1196 pAd Pointer to our adapter
1197 QueIdx Selected TX Ring
1200 NDIS_STATUS_FAILURE Not enough free descriptor
1201 NDIS_STATUS_SUCCESS Enough free descriptor
1203 IRQL = PASSIVE_LEVEL
1204 IRQL = DISPATCH_LEVEL
1208 ========================================================================
1210 NDIS_STATUS RTMPFreeTXDRequest(
1211 IN PRTMP_ADAPTER pAd,
1213 IN UCHAR NumberRequired,
1214 IN PUCHAR FreeNumberIs)
1216 ULONG FreeNumber = 0;
1217 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1226 if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1227 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1229 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1231 if (FreeNumber >= NumberRequired)
1232 Status = NDIS_STATUS_SUCCESS;
1236 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1237 FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1239 FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1241 if (FreeNumber >= NumberRequired)
1242 Status = NDIS_STATUS_SUCCESS;
1246 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1249 *FreeNumberIs = (UCHAR)FreeNumber;
1256 VOID RTMPSendDisassociationFrame(
1257 IN PRTMP_ADAPTER pAd)
1261 VOID RTMPSendNullFrame(
1262 IN PRTMP_ADAPTER pAd,
1264 IN BOOLEAN bQosNull)
1266 UCHAR NullFrame[48];
1268 PHEADER_802_11 pHeader_802_11;
1270 // WPA 802.1x secured port control
1271 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1272 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1273 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1274 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1275 #ifdef WPA_SUPPLICANT_SUPPORT
1276 || (pAd->StaCfg.IEEE8021X == TRUE)
1279 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1284 NdisZeroMemory(NullFrame, 48);
1285 Length = sizeof(HEADER_802_11);
1287 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1289 pHeader_802_11->FC.Type = BTYPE_DATA;
1290 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1291 pHeader_802_11->FC.ToDs = 1;
1292 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1293 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1294 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1296 if (pAd->CommonCfg.bAPSDForcePowerSave)
1298 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1302 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1304 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1307 pHeader_802_11->Sequence = pAd->Sequence;
1309 // Prepare QosNull function frame
1312 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1314 // copy QOS control bytes
1315 NullFrame[Length] = 0;
1316 NullFrame[Length+1] = 0;
1317 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1320 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1324 // IRQL = DISPATCH_LEVEL
1325 VOID RTMPSendRTSFrame(
1326 IN PRTMP_ADAPTER pAd,
1328 IN unsigned int NextMpduSize,
1331 IN USHORT AckDuration,
1339 // --------------------------------------------------------
1340 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1341 // Find the WPA key, either Group or Pairwise Key
1342 // LEAP + TKIP also use WPA key.
1343 // --------------------------------------------------------
1344 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1345 // In Cisco CCX 2.0 Leap Authentication
1346 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1347 // Instead of the SharedKey, SharedKey Length may be Zero.
1348 VOID STAFindCipherAlgorithm(
1349 IN PRTMP_ADAPTER pAd,
1352 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1353 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1354 UCHAR KeyIdx = 0xff;
1356 PCIPHER_KEY pKey = NULL;
1358 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1362 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1363 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1365 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1367 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1369 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1371 // 4-way handshaking frame must be clear
1372 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1373 (pAd->SharedKey[BSS0][0].KeyLen))
1375 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1379 else if (Cipher == Ndis802_11Encryption1Enabled)
1382 if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1384 if (LEAP_CCKM_ON(pAd))
1386 if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1392 KeyIdx = pAd->StaCfg.DefaultKeyId;
1394 else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1395 KeyIdx = pAd->StaCfg.DefaultKeyId;
1396 else if (LEAP_CCKM_ON(pAd))
1398 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1403 else // standard WEP64 or WEP128
1404 #endif // LEAP_SUPPORT //
1405 KeyIdx = pAd->StaCfg.DefaultKeyId;
1407 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1408 (Cipher == Ndis802_11Encryption3Enabled))
1410 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1411 KeyIdx = pAd->StaCfg.DefaultKeyId;
1412 else if (pAd->SharedKey[BSS0][0].KeyLen)
1415 KeyIdx = pAd->StaCfg.DefaultKeyId;
1419 CipherAlg = CIPHER_NONE;
1420 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1421 CipherAlg = CIPHER_NONE;
1422 #ifdef WPA_SUPPLICANT_SUPPORT
1423 else if ( pAd->StaCfg.WpaSupplicantUP &&
1424 (Cipher == Ndis802_11Encryption1Enabled) &&
1425 (pAd->StaCfg.IEEE8021X == TRUE) &&
1426 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1427 CipherAlg = CIPHER_NONE;
1428 #endif // WPA_SUPPLICANT_SUPPORT //
1431 //Header_802_11.FC.Wep = 1;
1432 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1433 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1437 pTxBlk->CipherAlg = CipherAlg;
1438 pTxBlk->pKey = pKey;
1442 VOID STABuildCommon802_11Header(
1443 IN PRTMP_ADAPTER pAd,
1447 HEADER_802_11 *pHeader_802_11;
1448 #ifdef QOS_DLS_SUPPORT
1449 BOOLEAN bDLSFrame = FALSE;
1450 INT DlsEntryIndex = 0;
1451 #endif // QOS_DLS_SUPPORT //
1454 // MAKE A COMMON 802.11 HEADER
1457 // normal wlan header size : 24 octets
1458 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1460 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1462 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1464 pHeader_802_11->FC.FrDs = 0;
1465 pHeader_802_11->FC.Type = BTYPE_DATA;
1466 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1468 #ifdef QOS_DLS_SUPPORT
1471 // Check if the frame can be sent through DLS direct link interface
1472 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1473 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1474 if (DlsEntryIndex >= 0)
1479 #endif // QOS_DLS_SUPPORT //
1481 if (pTxBlk->pMacEntry)
1483 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1485 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1486 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1490 #ifdef QOS_DLS_SUPPORT
1493 pHeader_802_11->Sequence = pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence;
1494 pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence = (pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence+1) & MAXSEQ;
1497 #endif // QOS_DLS_SUPPORT //
1499 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1500 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1506 pHeader_802_11->Sequence = pAd->Sequence;
1507 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1510 pHeader_802_11->Frag = 0;
1512 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1517 #ifdef QOS_DLS_SUPPORT
1520 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1521 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1522 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1523 pHeader_802_11->FC.ToDs = 0;
1526 #endif // QOS_DLS_SUPPORT //
1528 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1529 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1530 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1531 pHeader_802_11->FC.ToDs = 1;
1534 else if (ADHOC_ON(pAd))
1536 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1537 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1538 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1539 pHeader_802_11->FC.ToDs = 0;
1543 if (pTxBlk->CipherAlg != CIPHER_NONE)
1544 pHeader_802_11->FC.Wep = 1;
1546 // -----------------------------------------------------------------
1547 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1548 // -----------------------------------------------------------------
1549 if (pAd->CommonCfg.bAPSDForcePowerSave)
1550 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1552 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1555 #ifdef DOT11_N_SUPPORT
1556 VOID STABuildCache802_11Header(
1557 IN RTMP_ADAPTER *pAd,
1561 MAC_TABLE_ENTRY *pMacEntry;
1562 PHEADER_802_11 pHeader80211;
1564 pHeader80211 = (PHEADER_802_11)pHeader;
1565 pMacEntry = pTxBlk->pMacEntry;
1568 // Update the cached 802.11 HEADER
1571 // normal wlan header size : 24 octets
1572 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1575 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1578 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1579 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1582 // Check if the frame can be sent through DLS direct link interface
1583 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1584 #ifdef QOS_DLS_SUPPORT
1585 BOOLEAN bDLSFrame = FALSE;
1586 INT DlsEntryIndex = 0;
1588 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1589 if (DlsEntryIndex >= 0)
1593 #endif // QOS_DLS_SUPPORT //
1595 // The addr3 of normal packet send from DS is Dest Mac address.
1596 #ifdef QOS_DLS_SUPPORT
1599 COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
1600 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1601 pHeader80211->FC.ToDs = 0;
1604 #endif // QOS_DLS_SUPPORT //
1606 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1608 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1611 // -----------------------------------------------------------------
1612 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1613 // -----------------------------------------------------------------
1614 if (pAd->CommonCfg.bAPSDForcePowerSave)
1615 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1617 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1619 #endif // DOT11_N_SUPPORT //
1621 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1622 IN RTMP_ADAPTER *pAd,
1625 PUCHAR pHeaderBufPtr;
1626 HEADER_802_11 *pHeader_802_11;
1627 PNDIS_PACKET pNextPacket;
1629 PQUEUE_ENTRY pQEntry;
1631 STAFindCipherAlgorithm(pAd, pTxBlk);
1632 STABuildCommon802_11Header(pAd, pTxBlk);
1635 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1636 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1638 // steal "order" bit to mark "aggregation"
1639 pHeader_802_11->FC.Order = 1;
1641 // skip common header
1642 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1644 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1647 // build QOS Control bytes
1649 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1651 *(pHeaderBufPtr+1) = 0;
1653 pTxBlk->MpduHeaderLen += 2;
1656 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1657 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1658 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1659 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1661 // For RA Aggregation,
1662 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1663 pQEntry = pTxBlk->TxPacketList.Head;
1664 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1665 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1666 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1667 nextBufLen -= LENGTH_802_1Q;
1669 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1670 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1673 pTxBlk->MpduHeaderLen += 2;
1675 return pHeaderBufPtr;
1679 #ifdef DOT11_N_SUPPORT
1680 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1681 IN RTMP_ADAPTER *pAd,
1684 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1685 HEADER_802_11 *pHeader_802_11;
1688 STAFindCipherAlgorithm(pAd, pTxBlk);
1689 STABuildCommon802_11Header(pAd, pTxBlk);
1691 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1692 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1694 // skip common header
1695 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1698 // build QOS Control bytes
1700 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1705 *pHeaderBufPtr |= 0x80;
1707 *(pHeaderBufPtr+1) = 0;
1709 pTxBlk->MpduHeaderLen += 2;
1711 //pSaveBufPtr = pHeaderBufPtr;
1714 // padding at front of LLC header
1715 // LLC header should locate at 4-octets aligment
1717 // @@@ MpduHeaderLen excluding padding @@@
1719 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1720 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1721 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1723 return pHeaderBufPtr;
1728 VOID STA_AMPDU_Frame_Tx(
1729 IN PRTMP_ADAPTER pAd,
1732 HEADER_802_11 *pHeader_802_11;
1733 PUCHAR pHeaderBufPtr;
1735 MAC_TABLE_ENTRY *pMacEntry;
1737 PQUEUE_ENTRY pQEntry;
1741 while(pTxBlk->TxPacketList.Head)
1743 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1744 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1745 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1747 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1751 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1753 pMacEntry = pTxBlk->pMacEntry;
1754 if (pMacEntry->isCached)
1756 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1757 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1758 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1759 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1763 STAFindCipherAlgorithm(pAd, pTxBlk);
1764 STABuildCommon802_11Header(pAd, pTxBlk);
1766 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1770 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1772 // skip common header
1773 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1776 // build QOS Control bytes
1778 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1779 *(pHeaderBufPtr+1) = 0;
1781 pTxBlk->MpduHeaderLen += 2;
1785 // HTC control filed following QoS field
1787 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1789 if (pMacEntry->isCached == FALSE)
1792 pHeader_802_11->FC.Order = 1;
1794 NdisZeroMemory(pHeaderBufPtr, 4);
1795 *(pHeaderBufPtr+3) |= 0x80;
1798 pTxBlk->MpduHeaderLen += 4;
1801 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1802 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1804 // skip 802.3 header
1805 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1806 pTxBlk->SrcBufLen -= LENGTH_802_3;
1811 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1812 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1816 // padding at front of LLC header
1817 // LLC header should locate at 4-octets aligment
1819 // @@@ MpduHeaderLen excluding padding @@@
1821 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1822 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1823 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1828 // Insert LLC-SNAP encapsulation - 8 octets
1830 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1831 if (pTxBlk->pExtraLlcSnapEncap)
1833 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1835 // get 2 octets (TypeofLen)
1836 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1838 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1843 if (pMacEntry->isCached)
1845 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1849 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1851 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1852 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1853 pMacEntry->isCached = TRUE;
1856 // calculate Transmitted AMPDU count and ByteCount
1858 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1859 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1862 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1864 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1869 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1870 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1872 pAd->RalinkCounters.KickTxCount++;
1873 pAd->RalinkCounters.OneSecTxDoneCount++;
1879 VOID STA_AMSDU_Frame_Tx(
1880 IN PRTMP_ADAPTER pAd,
1883 PUCHAR pHeaderBufPtr;
1885 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1886 USHORT totalMPDUSize=0;
1887 UCHAR *subFrameHeader;
1889 USHORT FirstTx = 0, LastTxIdx = 0;
1892 PQUEUE_ENTRY pQEntry;
1897 ASSERT((pTxBlk->TxPacketList.Number > 1));
1899 while(pTxBlk->TxPacketList.Head)
1901 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1902 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1903 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1905 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1909 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1911 // skip 802.3 header
1912 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1913 pTxBlk->SrcBufLen -= LENGTH_802_3;
1918 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1919 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1924 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1926 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1927 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1931 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1932 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1933 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1934 pHeaderBufPtr += padding;
1935 pTxBlk->MpduHeaderLen = padding;
1940 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1942 subFrameHeader = pHeaderBufPtr;
1943 subFramePayloadLen = pTxBlk->SrcBufLen;
1945 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1948 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1949 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1953 // Insert LLC-SNAP encapsulation - 8 octets
1955 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1957 subFramePayloadLen = pTxBlk->SrcBufLen;
1959 if (pTxBlk->pExtraLlcSnapEncap)
1961 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1963 // get 2 octets (TypeofLen)
1964 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1966 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1967 subFramePayloadLen += LENGTH_802_1_H;
1970 // update subFrame Length field
1971 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1972 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1974 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1977 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1979 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1983 pAd->RalinkCounters.KickTxCount++;
1984 pAd->RalinkCounters.OneSecTxDoneCount++;
1986 // calculate Transmitted AMSDU Count and ByteCount
1988 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1989 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1994 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1995 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2000 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2001 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2003 #endif // DOT11_N_SUPPORT //
2005 VOID STA_Legacy_Frame_Tx(
2006 IN PRTMP_ADAPTER pAd,
2009 HEADER_802_11 *pHeader_802_11;
2010 PUCHAR pHeaderBufPtr;
2013 PQUEUE_ENTRY pQEntry;
2018 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2019 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2020 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2022 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2026 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
2028 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
2031 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
2032 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
2034 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
2036 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2038 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
2039 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
2041 STAFindCipherAlgorithm(pAd, pTxBlk);
2042 STABuildCommon802_11Header(pAd, pTxBlk);
2045 // skip 802.3 header
2046 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2047 pTxBlk->SrcBufLen -= LENGTH_802_3;
2052 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2053 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2056 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2057 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
2059 // skip common header
2060 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2062 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2065 // build QOS Control bytes
2067 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2068 *(pHeaderBufPtr+1) = 0;
2070 pTxBlk->MpduHeaderLen += 2;
2073 // The remaining content of MPDU header should locate at 4-octets aligment
2074 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2075 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2076 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2081 // Insert LLC-SNAP encapsulation - 8 octets
2084 // if original Ethernet frame contains no LLC/SNAP,
2085 // then an extra LLC/SNAP encap is required
2087 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2088 if (pTxBlk->pExtraLlcSnapEncap)
2092 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2095 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2096 // get 2 octets (TypeofLen)
2097 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2099 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2106 // use Wcid as Key Index
2109 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2111 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2113 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2115 pAd->RalinkCounters.KickTxCount++;
2116 pAd->RalinkCounters.OneSecTxDoneCount++;
2121 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2122 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2126 VOID STA_ARalink_Frame_Tx(
2127 IN PRTMP_ADAPTER pAd,
2130 PUCHAR pHeaderBufPtr;
2132 USHORT totalMPDUSize=0;
2133 USHORT FirstTx, LastTxIdx;
2136 PQUEUE_ENTRY pQEntry;
2141 ASSERT((pTxBlk->TxPacketList.Number== 2));
2144 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2145 while(pTxBlk->TxPacketList.Head)
2147 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2148 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2150 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2152 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2156 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2158 // skip 802.3 header
2159 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2160 pTxBlk->SrcBufLen -= LENGTH_802_3;
2165 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2166 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2170 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2172 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2174 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2175 // will be updated after final frame was handled.
2176 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2180 // Insert LLC-SNAP encapsulation - 8 octets
2182 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2184 if (pTxBlk->pExtraLlcSnapEncap)
2186 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2188 // get 2 octets (TypeofLen)
2189 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2191 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2195 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2197 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2198 pTxBlk->MpduHeaderLen = 0;
2200 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2201 // DA(6)+SA(6)+FrameType(2)
2202 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2203 pHeaderBufPtr += 12;
2204 // get 2 octets (TypeofLen)
2205 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2207 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2210 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2212 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2214 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2216 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2220 pAd->RalinkCounters.OneSecTxAggregationCount++;
2221 pAd->RalinkCounters.KickTxCount++;
2222 pAd->RalinkCounters.OneSecTxDoneCount++;
2226 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2227 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2232 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2233 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2238 VOID STA_Fragment_Frame_Tx(
2239 IN RTMP_ADAPTER *pAd,
2242 HEADER_802_11 *pHeader_802_11;
2243 PUCHAR pHeaderBufPtr;
2246 PACKET_INFO PacketInfo;
2247 USHORT EncryptionOverhead = 0;
2248 UINT32 FreeMpduSize, SrcRemainingBytes;
2252 PQUEUE_ENTRY pQEntry;
2257 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2258 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2259 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2261 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2265 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2266 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2268 STAFindCipherAlgorithm(pAd, pTxBlk);
2269 STABuildCommon802_11Header(pAd, pTxBlk);
2271 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2273 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2274 if (pTxBlk->pPacket == NULL)
2276 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2279 // skip 802.3 header
2280 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2281 pTxBlk->SrcBufLen -= LENGTH_802_3;
2287 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2288 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2291 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2292 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2295 // skip common header
2296 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2298 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2301 // build QOS Control bytes
2303 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2305 *(pHeaderBufPtr+1) = 0;
2307 pTxBlk->MpduHeaderLen += 2;
2311 // padding at front of LLC header
2312 // LLC header should locate at 4-octets aligment
2314 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2315 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2316 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2321 // Insert LLC-SNAP encapsulation - 8 octets
2324 // if original Ethernet frame contains no LLC/SNAP,
2325 // then an extra LLC/SNAP encap is required
2327 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2328 if (pTxBlk->pExtraLlcSnapEncap)
2332 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2335 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2336 // get 2 octets (TypeofLen)
2337 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2339 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2343 // If TKIP is used and fragmentation is required. Driver has to
2344 // append TKIP MIC at tail of the scatter buffer
2345 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2346 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2349 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2350 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2351 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2352 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2353 pTxBlk->SrcBufLen += 8;
2354 pTxBlk->TotalFrameLen += 8;
2355 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2359 // calcuate the overhead bytes that encryption algorithm may add. This
2360 // affects the calculate of "duration" field
2362 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2363 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2364 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2365 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2366 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2367 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2368 else if (pTxBlk->CipherAlg == CIPHER_AES)
2369 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2371 EncryptionOverhead = 0;
2373 // decide how much time an ACK/CTS frame will consume in the air
2374 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2376 // Init the total payload length of this frame.
2377 SrcRemainingBytes = pTxBlk->SrcBufLen;
2379 pTxBlk->TotalFragNum = 0xff;
2383 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2385 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2387 if (SrcRemainingBytes <= FreeMpduSize)
2388 { // this is the last or only fragment
2390 pTxBlk->SrcBufLen = SrcRemainingBytes;
2392 pHeader_802_11->FC.MoreFrag = 0;
2393 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2395 // Indicate the lower layer that this's the last fragment.
2396 pTxBlk->TotalFragNum = fragNum;
2399 { // more fragment is required
2401 pTxBlk->SrcBufLen = FreeMpduSize;
2403 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2404 pHeader_802_11->FC.MoreFrag = 1;
2405 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2409 pTxBlk->FrameGap = IFS_HTTXOP;
2411 pTxBlk->FrameGap = IFS_SIFS;
2413 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2415 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2417 pAd->RalinkCounters.KickTxCount++;
2418 pAd->RalinkCounters.OneSecTxDoneCount++;
2420 // Update the frame number, remaining size of the NDIS packet payload.
2422 // space for 802.11 header.
2423 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2424 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2427 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2428 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2430 pHeader_802_11->Frag++; // increase Frag #
2432 }while(SrcRemainingBytes > 0);
2437 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2441 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2442 while(_pTxBlk->TxPacketList.Head) \
2444 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2445 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2450 ========================================================================
2452 Routine Description:
2453 Copy frame from waiting queue into relative ring buffer and set
2454 appropriate ASIC register to kick hardware encryption before really
2458 pAd Pointer to our adapter
2459 PNDIS_PACKET Pointer to outgoing Ndis frame
2460 NumberOfFrag Number of fragment required
2465 IRQL = DISPATCH_LEVEL
2469 ========================================================================
2471 NDIS_STATUS STAHardTransmit(
2472 IN PRTMP_ADAPTER pAd,
2476 NDIS_PACKET *pPacket;
2477 PQUEUE_ENTRY pQEntry;
2479 // ---------------------------------------------
2480 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2481 // ---------------------------------------------
2483 ASSERT(pTxBlk->TxPacketList.Number);
2484 if (pTxBlk->TxPacketList.Head == NULL)
2486 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2487 return NDIS_STATUS_FAILURE;
2490 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2492 #if 0 //def CARRIER_DETECTION_SUPPORT // Roger sync Carrier
2493 if ((pAd->CommonCfg.CarrierDetect.Enable == TRUE) && (isCarrierDetectExist(pAd) == TRUE))
2495 DBGPRINT(RT_DEBUG_INFO,("STAHardTransmit --> radar detect not in normal mode !!!\n"));
2496 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2497 return (NDIS_STATUS_FAILURE);
2499 #endif // CARRIER_DETECTION_SUPPORT //
2501 // ------------------------------------------------------------------
2502 // STEP 1. WAKE UP PHY
2503 // outgoing frame always wakeup PHY to prevent frame lost and
2504 // turn off PSM bit to improve performance
2505 // ------------------------------------------------------------------
2506 // not to change PSM bit, just send this frame out?
2507 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2509 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2510 AsicForceWakeup(pAd, FROM_TX);
2513 // It should not change PSM bit, when APSD turn on.
2514 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2515 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2516 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2518 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2519 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2520 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2523 switch (pTxBlk->TxFrameType)
2525 #ifdef DOT11_N_SUPPORT
2526 case TX_AMPDU_FRAME:
2527 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2529 case TX_AMSDU_FRAME:
2530 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2532 #endif // DOT11_N_SUPPORT //
2533 case TX_LEGACY_FRAME:
2534 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2536 case TX_MCAST_FRAME:
2537 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2539 case TX_RALINK_FRAME:
2540 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2543 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2547 // It should not happened!
2548 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2549 while(pTxBlk->TxPacketList.Number)
2551 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2552 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2554 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2560 return (NDIS_STATUS_SUCCESS);
2564 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2566 unsigned char *word = value;
2567 unsigned int ret = 0;
2570 for(i=0; i < len; i++)
2573 ret ^=(unsigned int) (word[i]) << mod;
2574 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2579 VOID Sta_Announce_or_Forward_802_3_Packet(
2580 IN PRTMP_ADAPTER pAd,
2581 IN PNDIS_PACKET pPacket,
2582 IN UCHAR FromWhichBSSID)
2587 announce_802_3_packet(pAd, pPacket);
2592 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);