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 */
755 pAd->ate.RxCntPerSec++;
756 ATESampleRssi(pAd, pRxWI);
757 #ifdef RALINK_28xx_QA
758 if (pAd->ate.bQARxStart == TRUE)
760 /* (*pRxD) has been swapped in GetPacketFromRxRing() */
761 ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader);
763 #endif // RALINK_28xx_QA //
764 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
767 #endif // RALINK_ATE //
769 // Check for all RxD errors
770 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
772 // Handle the received frame
773 if (Status == NDIS_STATUS_SUCCESS)
775 switch (pHeader->FC.Type)
777 // CASE I, receive a DATA frame
780 // process DATA frame
781 STAHandleRxDataFrame(pAd, &RxCell);
784 // CASE II, receive a MGMT frame
787 STAHandleRxMgmtFrame(pAd, &RxCell);
790 // CASE III. receive a CNTL frame
793 STAHandleRxControlFrame(pAd, &RxCell);
796 // discard other type
798 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
804 pAd->Counters8023.RxErrors++;
805 // discard this frame
806 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
810 // fRTMP_PS_GO_TO_SLEEP_NOW is set if receiving beacon.
811 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW) && (INFRA_ON(pAd)))
813 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
814 AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp);
821 ========================================================================
825 pAd Pointer to our adapter
827 IRQL = DISPATCH_LEVEL
829 ========================================================================
831 VOID RTMPHandleTwakeupInterrupt(
832 IN PRTMP_ADAPTER pAd)
834 AsicForceWakeup(pAd, DOT11POWERSAVE);
838 ========================================================================
840 Early checking and OS-depened parsing for Tx packet send to our STA driver.
843 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
844 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
845 UINT NumberOfPackets Number of packet in packet array.
851 This function do early checking and classification for send-out packet.
852 You only can put OS-depened & STA related code in here.
853 ========================================================================
856 IN NDIS_HANDLE MiniportAdapterContext,
857 IN PPNDIS_PACKET ppPacketArray,
858 IN UINT NumberOfPackets)
861 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
862 PNDIS_PACKET pPacket;
863 BOOLEAN allowToSend = FALSE;
866 for (Index = 0; Index < NumberOfPackets; Index++)
868 pPacket = ppPacketArray[Index];
872 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
873 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
874 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
876 // Drop send request since hardware is in reset state
879 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
881 // Drop send request since there are no physical connection yet
886 // Record that orignal packet source is from NDIS layer,so that
887 // later on driver knows how to release this NDIS PACKET
888 #ifdef QOS_DLS_SUPPORT
889 MAC_TABLE_ENTRY *pEntry;
890 PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
892 pEntry = MacTableLookup(pAd, pSrcBufVA);
893 if (pEntry && (pEntry->ValidAsDls == TRUE))
895 RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
898 #endif // QOS_DLS_SUPPORT //
899 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
900 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
901 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
902 pAd->RalinkCounters.PendingNdisPacketCount++;
908 if (allowToSend == TRUE)
909 STASendPacket(pAd, pPacket);
911 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
914 // Dequeue outgoing frames from TxSwQueue[] and process it
915 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
921 ========================================================================
923 This routine is used to do packet parsing and classification for Tx packet
924 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
928 pAd Pointer to our adapter
929 pPacket Pointer to send packet
932 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
933 NDIS_STATUS_FAILURE If failed to do en-queue.
936 You only can put OS-indepened & STA related code in here.
937 ========================================================================
939 NDIS_STATUS STASendPacket(
940 IN PRTMP_ADAPTER pAd,
941 IN PNDIS_PACKET pPacket)
943 PACKET_INFO PacketInfo;
948 UCHAR QueIdx, UserPriority;
949 MAC_TABLE_ENTRY *pEntry = NULL;
950 unsigned int IrqFlags;
954 // Prepare packet information structure for buffer descriptor
955 // chained within a single NDIS packet.
956 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
958 if (pSrcBufVA == NULL)
960 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
961 // Resourece is low, system did not allocate virtual address
962 // return NDIS_STATUS_FAILURE directly to upper layer
963 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
964 return NDIS_STATUS_FAILURE;
970 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
971 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
972 return (NDIS_STATUS_FAILURE);
975 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
976 // Note multicast packets in adhoc also use BSSID_WCID index.
980 #ifdef QOS_DLS_SUPPORT
983 tmpWcid = RTMP_GET_PACKET_WCID(pPacket);
984 if (VALID_WCID(tmpWcid) &&
985 (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE))
987 pEntry = &pAd->MacTab.Content[tmpWcid];
988 Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate;
991 #endif // QOS_DLS_SUPPORT //
993 pEntry = &pAd->MacTab.Content[BSSID_WCID];
994 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
995 Rate = pAd->CommonCfg.TxRate;
998 else if (ADHOC_ON(pAd))
1000 if (*pSrcBufVA & 0x01)
1002 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
1003 pEntry = &pAd->MacTab.Content[MCAST_WCID];
1007 pEntry = MacTableLookup(pAd, pSrcBufVA);
1009 Rate = pAd->CommonCfg.TxRate;
1015 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
1016 // Resourece is low, system did not allocate virtual address
1017 // return NDIS_STATUS_FAILURE directly to upper layer
1018 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1019 return NDIS_STATUS_FAILURE;
1025 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
1029 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
1030 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
1031 RTMPCheckEtherType(pAd, pPacket);
1036 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
1038 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1039 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1040 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1041 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1042 #ifdef WPA_SUPPLICANT_SUPPORT
1043 || (pAd->StaCfg.IEEE8021X == TRUE)
1044 #endif // WPA_SUPPLICANT_SUPPORT //
1046 || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
1047 #endif // LEAP_SUPPORT //
1049 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1050 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1053 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1054 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1056 return (NDIS_STATUS_FAILURE);
1060 // STEP 1. Decide number of fragments required to deliver this MSDU.
1061 // The estimation here is not very accurate because difficult to
1062 // take encryption overhead into consideration here. The result
1063 // "NumberOfFrag" is then just used to pre-check if enough free
1064 // TXD are available to hold this MSDU.
1067 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1069 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1070 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1071 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1072 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1073 #ifdef DOT11_N_SUPPORT
1074 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1075 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1076 #endif // DOT11_N_SUPPORT //
1079 // The calculated "NumberOfFrag" is a rough estimation because of various
1080 // encryption/encapsulation overhead not taken into consideration. This number is just
1081 // used to make sure enough free TXD are available before fragmentation takes place.
1082 // In case the actual required number of fragments of an NDIS packet
1083 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1084 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1085 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1086 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1088 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1089 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1090 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1091 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1097 // Save fragment number to Ndis packet reserved field
1098 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1101 // STEP 2. Check the requirement of RTS:
1102 // If multiple fragment required, RTS is required only for the first fragment
1103 // if the fragment size large than RTS threshold
1104 // For RT28xx, Let ASIC send RTS/CTS
1105 RTMP_SET_PACKET_RTS(pPacket, 0);
1106 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1109 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1113 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1116 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1119 // get Ethernet protocol field
1120 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1121 if (Protocol <= 1500)
1123 // get Ethernet protocol field from LLC/SNAP
1124 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1127 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1131 // always AC_BE for non-IP packet
1132 if (Protocol != 0x0800)
1136 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1139 // return AC_BE if packet is not IPv4
1140 if ((Byte0 & 0xf0) != 0x40)
1144 UserPriority = (Byte1 & 0xe0) >> 5;
1145 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1147 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1148 // TODO: downgrade UP & QueIdx before passing ACM
1149 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1157 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1161 // Make sure SendTxWait queue resource won't be used by other threads
1162 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1163 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1165 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1167 StopNetIfQueue(pAd, QueIdx, pPacket);
1168 #endif // BLOCK_NET_IF //
1169 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1171 return NDIS_STATUS_FAILURE;
1175 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1177 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1179 #ifdef DOT11_N_SUPPORT
1180 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1181 (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1183 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1184 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1185 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1186 // For IOT compatibility, if
1187 // 1. It is Ralink chip or
1188 // 2. It is OPEN or AES mode,
1189 // then BA session can be bulit.
1190 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1191 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1194 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1197 #endif // DOT11_N_SUPPORT //
1199 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1200 return NDIS_STATUS_SUCCESS;
1205 ========================================================================
1207 Routine Description:
1208 This subroutine will scan through releative ring descriptor to find
1209 out avaliable free ring descriptor and compare with request size.
1212 pAd Pointer to our adapter
1213 QueIdx Selected TX Ring
1216 NDIS_STATUS_FAILURE Not enough free descriptor
1217 NDIS_STATUS_SUCCESS Enough free descriptor
1219 IRQL = PASSIVE_LEVEL
1220 IRQL = DISPATCH_LEVEL
1224 ========================================================================
1226 NDIS_STATUS RTMPFreeTXDRequest(
1227 IN PRTMP_ADAPTER pAd,
1229 IN UCHAR NumberRequired,
1230 IN PUCHAR FreeNumberIs)
1232 ULONG FreeNumber = 0;
1233 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1242 if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1243 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1245 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1247 if (FreeNumber >= NumberRequired)
1248 Status = NDIS_STATUS_SUCCESS;
1252 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1253 FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1255 FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1257 if (FreeNumber >= NumberRequired)
1258 Status = NDIS_STATUS_SUCCESS;
1262 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1265 *FreeNumberIs = (UCHAR)FreeNumber;
1272 VOID RTMPSendDisassociationFrame(
1273 IN PRTMP_ADAPTER pAd)
1277 VOID RTMPSendNullFrame(
1278 IN PRTMP_ADAPTER pAd,
1280 IN BOOLEAN bQosNull)
1282 UCHAR NullFrame[48];
1284 PHEADER_802_11 pHeader_802_11;
1292 #endif // RALINK_ATE //
1294 // WPA 802.1x secured port control
1295 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1296 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1297 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1298 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1299 #ifdef WPA_SUPPLICANT_SUPPORT
1300 || (pAd->StaCfg.IEEE8021X == TRUE)
1303 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1308 NdisZeroMemory(NullFrame, 48);
1309 Length = sizeof(HEADER_802_11);
1311 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1313 pHeader_802_11->FC.Type = BTYPE_DATA;
1314 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1315 pHeader_802_11->FC.ToDs = 1;
1316 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1317 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1318 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1320 if (pAd->CommonCfg.bAPSDForcePowerSave)
1322 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1326 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1328 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1331 pHeader_802_11->Sequence = pAd->Sequence;
1333 // Prepare QosNull function frame
1336 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1338 // copy QOS control bytes
1339 NullFrame[Length] = 0;
1340 NullFrame[Length+1] = 0;
1341 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1344 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1348 // IRQL = DISPATCH_LEVEL
1349 VOID RTMPSendRTSFrame(
1350 IN PRTMP_ADAPTER pAd,
1352 IN unsigned int NextMpduSize,
1355 IN USHORT AckDuration,
1363 // --------------------------------------------------------
1364 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1365 // Find the WPA key, either Group or Pairwise Key
1366 // LEAP + TKIP also use WPA key.
1367 // --------------------------------------------------------
1368 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1369 // In Cisco CCX 2.0 Leap Authentication
1370 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1371 // Instead of the SharedKey, SharedKey Length may be Zero.
1372 VOID STAFindCipherAlgorithm(
1373 IN PRTMP_ADAPTER pAd,
1376 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1377 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1378 UCHAR KeyIdx = 0xff;
1380 PCIPHER_KEY pKey = NULL;
1382 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1386 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1387 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1389 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1391 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1393 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1395 // 4-way handshaking frame must be clear
1396 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1397 (pAd->SharedKey[BSS0][0].KeyLen))
1399 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1403 else if (Cipher == Ndis802_11Encryption1Enabled)
1406 if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1408 if (LEAP_CCKM_ON(pAd))
1410 if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1416 KeyIdx = pAd->StaCfg.DefaultKeyId;
1418 else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1419 KeyIdx = pAd->StaCfg.DefaultKeyId;
1420 else if (LEAP_CCKM_ON(pAd))
1422 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1427 else // standard WEP64 or WEP128
1428 #endif // LEAP_SUPPORT //
1429 KeyIdx = pAd->StaCfg.DefaultKeyId;
1431 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1432 (Cipher == Ndis802_11Encryption3Enabled))
1434 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1435 KeyIdx = pAd->StaCfg.DefaultKeyId;
1436 else if (pAd->SharedKey[BSS0][0].KeyLen)
1439 KeyIdx = pAd->StaCfg.DefaultKeyId;
1443 CipherAlg = CIPHER_NONE;
1444 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1445 CipherAlg = CIPHER_NONE;
1446 #ifdef WPA_SUPPLICANT_SUPPORT
1447 else if ( pAd->StaCfg.WpaSupplicantUP &&
1448 (Cipher == Ndis802_11Encryption1Enabled) &&
1449 (pAd->StaCfg.IEEE8021X == TRUE) &&
1450 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1451 CipherAlg = CIPHER_NONE;
1452 #endif // WPA_SUPPLICANT_SUPPORT //
1455 //Header_802_11.FC.Wep = 1;
1456 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1457 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1461 pTxBlk->CipherAlg = CipherAlg;
1462 pTxBlk->pKey = pKey;
1466 VOID STABuildCommon802_11Header(
1467 IN PRTMP_ADAPTER pAd,
1471 HEADER_802_11 *pHeader_802_11;
1472 #ifdef QOS_DLS_SUPPORT
1473 BOOLEAN bDLSFrame = FALSE;
1474 INT DlsEntryIndex = 0;
1475 #endif // QOS_DLS_SUPPORT //
1478 // MAKE A COMMON 802.11 HEADER
1481 // normal wlan header size : 24 octets
1482 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1484 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1486 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1488 pHeader_802_11->FC.FrDs = 0;
1489 pHeader_802_11->FC.Type = BTYPE_DATA;
1490 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1492 #ifdef QOS_DLS_SUPPORT
1495 // Check if the frame can be sent through DLS direct link interface
1496 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1497 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1498 if (DlsEntryIndex >= 0)
1503 #endif // QOS_DLS_SUPPORT //
1505 if (pTxBlk->pMacEntry)
1507 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1509 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1510 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1514 #ifdef QOS_DLS_SUPPORT
1517 pHeader_802_11->Sequence = pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence;
1518 pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence = (pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence+1) & MAXSEQ;
1521 #endif // QOS_DLS_SUPPORT //
1523 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1524 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1530 pHeader_802_11->Sequence = pAd->Sequence;
1531 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1534 pHeader_802_11->Frag = 0;
1536 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1541 #ifdef QOS_DLS_SUPPORT
1544 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1545 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1546 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1547 pHeader_802_11->FC.ToDs = 0;
1550 #endif // QOS_DLS_SUPPORT //
1552 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1553 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1554 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1555 pHeader_802_11->FC.ToDs = 1;
1558 else if (ADHOC_ON(pAd))
1560 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1561 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1562 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1563 pHeader_802_11->FC.ToDs = 0;
1567 if (pTxBlk->CipherAlg != CIPHER_NONE)
1568 pHeader_802_11->FC.Wep = 1;
1570 // -----------------------------------------------------------------
1571 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1572 // -----------------------------------------------------------------
1573 if (pAd->CommonCfg.bAPSDForcePowerSave)
1574 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1576 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1579 #ifdef DOT11_N_SUPPORT
1580 VOID STABuildCache802_11Header(
1581 IN RTMP_ADAPTER *pAd,
1585 MAC_TABLE_ENTRY *pMacEntry;
1586 PHEADER_802_11 pHeader80211;
1588 pHeader80211 = (PHEADER_802_11)pHeader;
1589 pMacEntry = pTxBlk->pMacEntry;
1592 // Update the cached 802.11 HEADER
1595 // normal wlan header size : 24 octets
1596 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1599 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1602 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1603 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1606 // Check if the frame can be sent through DLS direct link interface
1607 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1608 #ifdef QOS_DLS_SUPPORT
1609 BOOLEAN bDLSFrame = FALSE;
1610 INT DlsEntryIndex = 0;
1612 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1613 if (DlsEntryIndex >= 0)
1617 #endif // QOS_DLS_SUPPORT //
1619 // The addr3 of normal packet send from DS is Dest Mac address.
1620 #ifdef QOS_DLS_SUPPORT
1623 COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
1624 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1625 pHeader80211->FC.ToDs = 0;
1628 #endif // QOS_DLS_SUPPORT //
1630 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1632 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1635 // -----------------------------------------------------------------
1636 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1637 // -----------------------------------------------------------------
1638 if (pAd->CommonCfg.bAPSDForcePowerSave)
1639 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1641 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1643 #endif // DOT11_N_SUPPORT //
1645 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1646 IN RTMP_ADAPTER *pAd,
1649 PUCHAR pHeaderBufPtr;
1650 HEADER_802_11 *pHeader_802_11;
1651 PNDIS_PACKET pNextPacket;
1653 PQUEUE_ENTRY pQEntry;
1655 STAFindCipherAlgorithm(pAd, pTxBlk);
1656 STABuildCommon802_11Header(pAd, pTxBlk);
1659 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1660 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1662 // steal "order" bit to mark "aggregation"
1663 pHeader_802_11->FC.Order = 1;
1665 // skip common header
1666 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1668 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1671 // build QOS Control bytes
1673 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1675 *(pHeaderBufPtr+1) = 0;
1677 pTxBlk->MpduHeaderLen += 2;
1680 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1681 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1682 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1683 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1685 // For RA Aggregation,
1686 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1687 pQEntry = pTxBlk->TxPacketList.Head;
1688 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1689 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1690 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1691 nextBufLen -= LENGTH_802_1Q;
1693 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1694 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1697 pTxBlk->MpduHeaderLen += 2;
1699 return pHeaderBufPtr;
1703 #ifdef DOT11_N_SUPPORT
1704 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1705 IN RTMP_ADAPTER *pAd,
1708 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1709 HEADER_802_11 *pHeader_802_11;
1712 STAFindCipherAlgorithm(pAd, pTxBlk);
1713 STABuildCommon802_11Header(pAd, pTxBlk);
1715 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1716 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1718 // skip common header
1719 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1722 // build QOS Control bytes
1724 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1729 *pHeaderBufPtr |= 0x80;
1731 *(pHeaderBufPtr+1) = 0;
1733 pTxBlk->MpduHeaderLen += 2;
1735 //pSaveBufPtr = pHeaderBufPtr;
1738 // padding at front of LLC header
1739 // LLC header should locate at 4-octets aligment
1741 // @@@ MpduHeaderLen excluding padding @@@
1743 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1744 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1745 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1747 return pHeaderBufPtr;
1752 VOID STA_AMPDU_Frame_Tx(
1753 IN PRTMP_ADAPTER pAd,
1756 HEADER_802_11 *pHeader_802_11;
1757 PUCHAR pHeaderBufPtr;
1759 MAC_TABLE_ENTRY *pMacEntry;
1761 PQUEUE_ENTRY pQEntry;
1765 while(pTxBlk->TxPacketList.Head)
1767 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1768 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1769 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1771 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1775 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1777 pMacEntry = pTxBlk->pMacEntry;
1778 if (pMacEntry->isCached)
1780 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1781 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1782 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1783 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1787 STAFindCipherAlgorithm(pAd, pTxBlk);
1788 STABuildCommon802_11Header(pAd, pTxBlk);
1790 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1794 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1796 // skip common header
1797 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1800 // build QOS Control bytes
1802 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1803 *(pHeaderBufPtr+1) = 0;
1805 pTxBlk->MpduHeaderLen += 2;
1809 // HTC control filed following QoS field
1811 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1813 if (pMacEntry->isCached == FALSE)
1816 pHeader_802_11->FC.Order = 1;
1818 NdisZeroMemory(pHeaderBufPtr, 4);
1819 *(pHeaderBufPtr+3) |= 0x80;
1822 pTxBlk->MpduHeaderLen += 4;
1825 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1826 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1828 // skip 802.3 header
1829 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1830 pTxBlk->SrcBufLen -= LENGTH_802_3;
1835 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1836 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1840 // padding at front of LLC header
1841 // LLC header should locate at 4-octets aligment
1843 // @@@ MpduHeaderLen excluding padding @@@
1845 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1846 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1847 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1852 // Insert LLC-SNAP encapsulation - 8 octets
1854 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1855 if (pTxBlk->pExtraLlcSnapEncap)
1857 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1859 // get 2 octets (TypeofLen)
1860 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1862 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1867 if (pMacEntry->isCached)
1869 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1873 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1875 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1876 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1877 pMacEntry->isCached = TRUE;
1880 // calculate Transmitted AMPDU count and ByteCount
1882 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1883 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1886 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1888 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1893 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1894 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1896 pAd->RalinkCounters.KickTxCount++;
1897 pAd->RalinkCounters.OneSecTxDoneCount++;
1903 VOID STA_AMSDU_Frame_Tx(
1904 IN PRTMP_ADAPTER pAd,
1907 PUCHAR pHeaderBufPtr;
1909 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1910 USHORT totalMPDUSize=0;
1911 UCHAR *subFrameHeader;
1913 USHORT FirstTx = 0, LastTxIdx = 0;
1916 PQUEUE_ENTRY pQEntry;
1921 ASSERT((pTxBlk->TxPacketList.Number > 1));
1923 while(pTxBlk->TxPacketList.Head)
1925 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1926 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1927 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1929 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1933 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1935 // skip 802.3 header
1936 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1937 pTxBlk->SrcBufLen -= LENGTH_802_3;
1942 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1943 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1948 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1950 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1951 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1955 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1956 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1957 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1958 pHeaderBufPtr += padding;
1959 pTxBlk->MpduHeaderLen = padding;
1964 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1966 subFrameHeader = pHeaderBufPtr;
1967 subFramePayloadLen = pTxBlk->SrcBufLen;
1969 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1972 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1973 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1977 // Insert LLC-SNAP encapsulation - 8 octets
1979 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1981 subFramePayloadLen = pTxBlk->SrcBufLen;
1983 if (pTxBlk->pExtraLlcSnapEncap)
1985 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1987 // get 2 octets (TypeofLen)
1988 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1990 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1991 subFramePayloadLen += LENGTH_802_1_H;
1994 // update subFrame Length field
1995 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1996 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1998 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2001 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2003 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2007 pAd->RalinkCounters.KickTxCount++;
2008 pAd->RalinkCounters.OneSecTxDoneCount++;
2010 // calculate Transmitted AMSDU Count and ByteCount
2012 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
2013 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
2018 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2019 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2024 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2025 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2027 #endif // DOT11_N_SUPPORT //
2029 VOID STA_Legacy_Frame_Tx(
2030 IN PRTMP_ADAPTER pAd,
2033 HEADER_802_11 *pHeader_802_11;
2034 PUCHAR pHeaderBufPtr;
2037 PQUEUE_ENTRY pQEntry;
2042 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2043 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2044 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2046 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2050 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
2052 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
2055 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
2056 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
2058 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
2060 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2062 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
2063 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
2065 STAFindCipherAlgorithm(pAd, pTxBlk);
2066 STABuildCommon802_11Header(pAd, pTxBlk);
2069 // skip 802.3 header
2070 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2071 pTxBlk->SrcBufLen -= LENGTH_802_3;
2076 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2077 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2080 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2081 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
2083 // skip common header
2084 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2086 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2089 // build QOS Control bytes
2091 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2092 *(pHeaderBufPtr+1) = 0;
2094 pTxBlk->MpduHeaderLen += 2;
2097 // The remaining content of MPDU header should locate at 4-octets aligment
2098 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2099 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2100 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2105 // Insert LLC-SNAP encapsulation - 8 octets
2108 // if original Ethernet frame contains no LLC/SNAP,
2109 // then an extra LLC/SNAP encap is required
2111 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2112 if (pTxBlk->pExtraLlcSnapEncap)
2116 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2119 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2120 // get 2 octets (TypeofLen)
2121 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2123 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2130 // use Wcid as Key Index
2133 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2135 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2137 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2139 pAd->RalinkCounters.KickTxCount++;
2140 pAd->RalinkCounters.OneSecTxDoneCount++;
2145 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2146 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2150 VOID STA_ARalink_Frame_Tx(
2151 IN PRTMP_ADAPTER pAd,
2154 PUCHAR pHeaderBufPtr;
2156 USHORT totalMPDUSize=0;
2157 USHORT FirstTx, LastTxIdx;
2160 PQUEUE_ENTRY pQEntry;
2165 ASSERT((pTxBlk->TxPacketList.Number== 2));
2168 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2169 while(pTxBlk->TxPacketList.Head)
2171 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2172 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2174 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2176 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2180 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2182 // skip 802.3 header
2183 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2184 pTxBlk->SrcBufLen -= LENGTH_802_3;
2189 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2190 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2194 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2196 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2198 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2199 // will be updated after final frame was handled.
2200 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2204 // Insert LLC-SNAP encapsulation - 8 octets
2206 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2208 if (pTxBlk->pExtraLlcSnapEncap)
2210 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2212 // get 2 octets (TypeofLen)
2213 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2215 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2219 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2221 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2222 pTxBlk->MpduHeaderLen = 0;
2224 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2225 // DA(6)+SA(6)+FrameType(2)
2226 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2227 pHeaderBufPtr += 12;
2228 // get 2 octets (TypeofLen)
2229 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2231 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2234 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2236 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2238 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2240 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2244 pAd->RalinkCounters.OneSecTxAggregationCount++;
2245 pAd->RalinkCounters.KickTxCount++;
2246 pAd->RalinkCounters.OneSecTxDoneCount++;
2250 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2251 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2256 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2257 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2262 VOID STA_Fragment_Frame_Tx(
2263 IN RTMP_ADAPTER *pAd,
2266 HEADER_802_11 *pHeader_802_11;
2267 PUCHAR pHeaderBufPtr;
2270 PACKET_INFO PacketInfo;
2271 USHORT EncryptionOverhead = 0;
2272 UINT32 FreeMpduSize, SrcRemainingBytes;
2276 PQUEUE_ENTRY pQEntry;
2281 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2282 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2283 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2285 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2289 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2290 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2292 STAFindCipherAlgorithm(pAd, pTxBlk);
2293 STABuildCommon802_11Header(pAd, pTxBlk);
2295 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2297 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2298 if (pTxBlk->pPacket == NULL)
2300 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2303 // skip 802.3 header
2304 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2305 pTxBlk->SrcBufLen -= LENGTH_802_3;
2311 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2312 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2315 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2316 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2319 // skip common header
2320 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2322 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2325 // build QOS Control bytes
2327 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2329 *(pHeaderBufPtr+1) = 0;
2331 pTxBlk->MpduHeaderLen += 2;
2335 // padding at front of LLC header
2336 // LLC header should locate at 4-octets aligment
2338 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2339 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2340 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2345 // Insert LLC-SNAP encapsulation - 8 octets
2348 // if original Ethernet frame contains no LLC/SNAP,
2349 // then an extra LLC/SNAP encap is required
2351 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2352 if (pTxBlk->pExtraLlcSnapEncap)
2356 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2359 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2360 // get 2 octets (TypeofLen)
2361 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2363 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2367 // If TKIP is used and fragmentation is required. Driver has to
2368 // append TKIP MIC at tail of the scatter buffer
2369 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2370 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2373 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2374 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2375 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2376 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2377 pTxBlk->SrcBufLen += 8;
2378 pTxBlk->TotalFrameLen += 8;
2379 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2383 // calcuate the overhead bytes that encryption algorithm may add. This
2384 // affects the calculate of "duration" field
2386 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2387 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2388 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2389 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2390 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2391 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2392 else if (pTxBlk->CipherAlg == CIPHER_AES)
2393 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2395 EncryptionOverhead = 0;
2397 // decide how much time an ACK/CTS frame will consume in the air
2398 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2400 // Init the total payload length of this frame.
2401 SrcRemainingBytes = pTxBlk->SrcBufLen;
2403 pTxBlk->TotalFragNum = 0xff;
2407 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2409 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2411 if (SrcRemainingBytes <= FreeMpduSize)
2412 { // this is the last or only fragment
2414 pTxBlk->SrcBufLen = SrcRemainingBytes;
2416 pHeader_802_11->FC.MoreFrag = 0;
2417 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2419 // Indicate the lower layer that this's the last fragment.
2420 pTxBlk->TotalFragNum = fragNum;
2423 { // more fragment is required
2425 pTxBlk->SrcBufLen = FreeMpduSize;
2427 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2428 pHeader_802_11->FC.MoreFrag = 1;
2429 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2433 pTxBlk->FrameGap = IFS_HTTXOP;
2435 pTxBlk->FrameGap = IFS_SIFS;
2437 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2439 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2441 pAd->RalinkCounters.KickTxCount++;
2442 pAd->RalinkCounters.OneSecTxDoneCount++;
2444 // Update the frame number, remaining size of the NDIS packet payload.
2446 // space for 802.11 header.
2447 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2448 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2451 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2452 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2454 pHeader_802_11->Frag++; // increase Frag #
2456 }while(SrcRemainingBytes > 0);
2461 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2465 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2466 while(_pTxBlk->TxPacketList.Head) \
2468 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2469 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2474 ========================================================================
2476 Routine Description:
2477 Copy frame from waiting queue into relative ring buffer and set
2478 appropriate ASIC register to kick hardware encryption before really
2482 pAd Pointer to our adapter
2483 PNDIS_PACKET Pointer to outgoing Ndis frame
2484 NumberOfFrag Number of fragment required
2489 IRQL = DISPATCH_LEVEL
2493 ========================================================================
2495 NDIS_STATUS STAHardTransmit(
2496 IN PRTMP_ADAPTER pAd,
2500 NDIS_PACKET *pPacket;
2501 PQUEUE_ENTRY pQEntry;
2503 // ---------------------------------------------
2504 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2505 // ---------------------------------------------
2507 ASSERT(pTxBlk->TxPacketList.Number);
2508 if (pTxBlk->TxPacketList.Head == NULL)
2510 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2511 return NDIS_STATUS_FAILURE;
2514 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2516 #if 0 //def CARRIER_DETECTION_SUPPORT // Roger sync Carrier
2517 if ((pAd->CommonCfg.CarrierDetect.Enable == TRUE) && (isCarrierDetectExist(pAd) == TRUE))
2519 DBGPRINT(RT_DEBUG_INFO,("STAHardTransmit --> radar detect not in normal mode !!!\n"));
2520 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2521 return (NDIS_STATUS_FAILURE);
2523 #endif // CARRIER_DETECTION_SUPPORT //
2525 // ------------------------------------------------------------------
2526 // STEP 1. WAKE UP PHY
2527 // outgoing frame always wakeup PHY to prevent frame lost and
2528 // turn off PSM bit to improve performance
2529 // ------------------------------------------------------------------
2530 // not to change PSM bit, just send this frame out?
2531 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2533 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2534 AsicForceWakeup(pAd, FROM_TX);
2537 // It should not change PSM bit, when APSD turn on.
2538 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2539 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2540 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2542 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2543 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2544 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2547 switch (pTxBlk->TxFrameType)
2549 #ifdef DOT11_N_SUPPORT
2550 case TX_AMPDU_FRAME:
2551 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2553 case TX_AMSDU_FRAME:
2554 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2556 #endif // DOT11_N_SUPPORT //
2557 case TX_LEGACY_FRAME:
2558 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2560 case TX_MCAST_FRAME:
2561 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2563 case TX_RALINK_FRAME:
2564 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2567 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2571 // It should not happened!
2572 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2573 while(pTxBlk->TxPacketList.Number)
2575 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2576 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2578 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2584 return (NDIS_STATUS_SUCCESS);
2588 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2590 unsigned char *word = value;
2591 unsigned int ret = 0;
2594 for(i=0; i < len; i++)
2597 ret ^=(unsigned int) (word[i]) << mod;
2598 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2603 VOID Sta_Announce_or_Forward_802_3_Packet(
2604 IN PRTMP_ADAPTER pAd,
2605 IN PNDIS_PACKET pPacket,
2606 IN UCHAR FromWhichBSSID)
2611 announce_802_3_packet(pAd, pPacket);
2616 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);