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"
42 VOID STARxEAPOLFrameIndicate(
44 IN MAC_TABLE_ENTRY *pEntry,
46 IN UCHAR FromWhichBSSID)
48 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
49 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
52 #ifdef WPA_SUPPLICANT_SUPPORT
53 if (pAd->StaCfg.WpaSupplicantUP)
55 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
56 // TBD : process fragmented EAPol frames
58 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
59 if ( pAd->StaCfg.IEEE8021X == TRUE &&
60 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
66 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
67 //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
68 STA_PORT_SECURED(pAd);
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)
81 char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
82 NDIS_802_11_WEP keyinfo;
87 NdisZeroMemory(&WepKey, sizeof(WepKey));
88 len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
90 NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
91 pAd->StaCfg.DesireSharedKey[idx].Key,
92 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
94 WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
95 WepKey.keyinfo.KeyLength = len;
96 pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
98 pAd->IndicateMediaState = NdisMediaStateConnected;
99 pAd->ExtraInfo = GENERAL_LINK_UP;
100 // need to enqueue cmd to thread
101 RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
103 // For Preventing ShardKey Table is cleared by remove key procedure.
104 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
105 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
106 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
107 pAd->StaCfg.DesireSharedKey[idx].Key,
108 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
113 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
118 #endif // WPA_SUPPLICANT_SUPPORT //
120 // Special DATA frame that has to pass to MLME
121 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
122 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
124 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
125 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
126 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
127 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
131 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
136 VOID STARxDataFrameAnnounce(
137 IN PRTMP_ADAPTER pAd,
138 IN MAC_TABLE_ENTRY *pEntry,
140 IN UCHAR FromWhichBSSID)
144 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
147 // drop all non-EAP DATA frame before
148 // this client's Port-Access-Control is secured
149 if (pRxBlk->pHeader->FC.Wep)
151 // unsupported cipher suite
152 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
155 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
161 // encryption in-use but receive a non-EAPOL clear text frame, drop it
162 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
163 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
166 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
171 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
172 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
174 // Normal legacy, AMPDU or AMSDU
175 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
181 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
183 #ifdef QOS_DLS_SUPPORT
184 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS);
185 #endif // QOS_DLS_SUPPORT //
189 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
190 #ifdef DOT11_N_SUPPORT
191 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
193 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
196 #endif // DOT11_N_SUPPORT //
198 // Determin the destination of the EAP frame
199 // to WPA state machine or upper layer
200 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
206 // For TKIP frame, calculate the MIC value
207 BOOLEAN STACheckTkipMICValue(
208 IN PRTMP_ADAPTER pAd,
209 IN MAC_TABLE_ENTRY *pEntry,
212 PHEADER_802_11 pHeader = pRxBlk->pHeader;
213 UCHAR *pData = pRxBlk->pData;
214 USHORT DataSize = pRxBlk->DataSize;
215 UCHAR UserPriority = pRxBlk->UserPriority;
219 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
221 pDA = pHeader->Addr1;
222 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
224 pSA = pHeader->Addr3;
228 pSA = pHeader->Addr2;
231 if (RTMPTkipCompareMICValue(pAd,
239 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
241 #ifdef WPA_SUPPLICANT_SUPPORT
242 if (pAd->StaCfg.WpaSupplicantUP)
244 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
247 #endif // WPA_SUPPLICANT_SUPPORT //
249 RTMPReportMicError(pAd, pWpaKey);
253 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
262 // All Rx routines use RX_BLK structure to hande rx events
263 // It is very important to build pRxBlk attributes
264 // 1. pHeader pointer to 802.11 Header
265 // 2. pData pointer to payload including LLC (just skip Header)
266 // 3. set payload size including LLC to DataSize
267 // 4. set some flags with RX_BLK_SET_FLAG()
269 VOID STAHandleRxDataFrame(
270 IN PRTMP_ADAPTER pAd,
273 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
274 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
275 PHEADER_802_11 pHeader = pRxBlk->pHeader;
276 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
277 BOOLEAN bFragment = FALSE;
278 MAC_TABLE_ENTRY *pEntry = NULL;
279 UCHAR FromWhichBSSID = BSS0;
280 UCHAR UserPriority = 0;
283 // before LINK UP, all DATA frames are rejected
284 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
287 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
291 #ifdef QOS_DLS_SUPPORT
292 //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
293 if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD))
297 #endif // QOS_DLS_SUPPORT //
299 // Drop not my BSS frames
300 if (pRxD->MyBss == 0)
304 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
309 pAd->RalinkCounters.RxCountSinceLastNULL++;
310 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
313 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
316 pData = (PUCHAR)pHeader + LENGTH_802_11;
317 if ((*pData >> 4) & 0x01)
319 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
320 pAd->CommonCfg.bInServicePeriod = FALSE;
322 // Force driver to fall into sleep mode when rcv EOSP frame
323 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
325 USHORT TbttNumToNextWakeUp;
326 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
329 NdisGetSystemUpTime(&Now);
330 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
332 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
333 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
334 TbttNumToNextWakeUp = NextDtim;
336 MlmeSetPsmBit(pAd, PWR_SAVE);
337 // if WMM-APSD is failed, try to disable following line
338 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
342 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
344 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
348 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
349 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
352 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
356 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
357 #ifdef QOS_DLS_SUPPORT
358 if (!pAd->CommonCfg.bDLSCapable)
360 #endif // QOS_DLS_SUPPORT //
363 // Infrastructure mode, check address 2 for BSSID
364 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
366 // Receive frame not my BSSID
368 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
372 else // Ad-Hoc mode or Not associated
374 // Ad-Hoc mode, check address 3 for BSSID
375 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
377 // Receive frame not my BSSID
379 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
383 #ifdef QOS_DLS_SUPPORT
385 #endif // QOS_DLS_SUPPORT //
390 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
392 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
396 // 1. release packet if infra mode
397 // 2. new a pEntry if ad-hoc mode
398 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
405 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
406 #ifdef QOS_DLS_SUPPORT
407 if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
408 RX_BLK_SET_FLAG(pRxBlk, fRX_DLS);
410 #endif // QOS_DLS_SUPPORT //
411 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
414 // check Atheros Client
415 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
417 pEntry->bIAmBadAtheros = TRUE;
418 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
419 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
420 if (!STA_AES_ON(pAd))
422 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
427 pRxBlk->pData = (UCHAR *)pHeader;
430 // update RxBlk->pData, DataSize
431 // 802.11 Header, QOS, HTC, Hw Padding
434 // 1. skip 802.11 HEADER
436 pRxBlk->pData += LENGTH_802_11;
437 pRxBlk->DataSize -= LENGTH_802_11;
441 if (pHeader->FC.SubType & 0x08)
443 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
444 UserPriority = *(pRxBlk->pData) & 0x0f;
445 // bit 7 in QoS Control field signals the HT A-MSDU format
446 if ((*pRxBlk->pData) & 0x80)
448 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
451 // skip QOS contorl field
453 pRxBlk->DataSize -=2;
455 pRxBlk->UserPriority = UserPriority;
457 // 3. Order bit: A-Ralink or HTC+
458 if (pHeader->FC.Order)
460 #ifdef AGGREGATION_SUPPORT
461 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
463 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
468 #ifdef DOT11_N_SUPPORT
469 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
470 // skip HTC contorl field
472 pRxBlk->DataSize -= 4;
473 #endif // DOT11_N_SUPPORT //
477 // 4. skip HW padding
480 // just move pData pointer
481 // because DataSize excluding HW padding
482 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
486 #ifdef DOT11_N_SUPPORT
489 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
491 #endif // DOT11_N_SUPPORT //
495 // Case I Process Broadcast & Multicast data frame
497 if (pRxD->Bcast || pRxD->Mcast)
499 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
501 // Drop Mcast/Bcast frame with fragment bit on
502 if (pHeader->FC.MoreFrag)
505 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
509 // Filter out Bcast frame which AP relayed for us
510 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
513 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
517 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
522 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
525 #ifdef QOS_DLS_SUPPORT
526 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS))
528 MAC_TABLE_ENTRY *pDlsEntry = NULL;
530 pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE);
532 Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI);
535 #endif // QOS_DLS_SUPPORT //
538 pEntry = MacTableLookup(pAd, pHeader->Addr2);
540 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
544 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
546 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
547 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
549 pAd->RalinkCounters.OneSecRxOkDataCnt++;
552 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
554 // re-assemble the fragmented packets
555 // return complete frame (pRxPacket) or NULL
557 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
562 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
564 // process complete frame
565 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
568 pRxBlk->DataSize -= 8;
570 // For TKIP frame, calculate the MIC value
571 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
577 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
583 // because RTMPDeFragmentDataFrame() will release rx packet,
584 // if packet is fragmented
591 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
594 VOID STAHandleRxMgmtFrame(
595 IN PRTMP_ADAPTER pAd,
598 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
599 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
600 PHEADER_802_11 pHeader = pRxBlk->pHeader;
601 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
606 // We should collect RSSI not only U2M data but also my beacon
607 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
609 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
611 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
612 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
615 // First check the size, it MUST not exceed the mlme queue size
616 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
618 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
622 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
623 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
626 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
629 VOID STAHandleRxControlFrame(
630 IN PRTMP_ADAPTER pAd,
633 #ifdef DOT11_N_SUPPORT
634 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
635 #endif // DOT11_N_SUPPORT //
636 PHEADER_802_11 pHeader = pRxBlk->pHeader;
637 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
639 switch (pHeader->FC.SubType)
641 case SUBTYPE_BLOCK_ACK_REQ:
642 #ifdef DOT11_N_SUPPORT
644 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
647 #endif // DOT11_N_SUPPORT //
648 case SUBTYPE_BLOCK_ACK:
654 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
659 ========================================================================
662 Process RxDone interrupt, running in DPC level
665 pAd Pointer to our adapter
670 IRQL = DISPATCH_LEVEL
673 This routine has to maintain Rx ring read pointer.
674 Need to consider QOS DATA format when converting to 802.3
675 ========================================================================
677 BOOLEAN STARxDoneInterruptHandle(
678 IN PRTMP_ADAPTER pAd,
682 UINT32 RxProcessed, RxPending;
683 BOOLEAN bReschedule = FALSE;
684 RT28XX_RXD_STRUC *pRxD;
687 PNDIS_PACKET pRxPacket;
688 PHEADER_802_11 pHeader;
691 RxProcessed = RxPending = 0;
693 // process whole rx ring
697 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
698 fRTMP_ADAPTER_RESET_IN_PROGRESS |
699 fRTMP_ADAPTER_HALT_IN_PROGRESS |
700 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
701 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
707 RxProcessed ++; // test
709 // 1. allocate a new data packet into rx ring to replace received packet
710 // then processing the received packet
711 // 2. the callee must take charge of release of packet
712 // 3. As far as driver is concerned ,
713 // the rx packet must
714 // a. be indicated to upper layer or
715 // b. be released if it is discarded
716 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
717 if (pRxPacket == NULL)
719 // no more packet to process
723 // get rx ring descriptor
724 pRxD = &(RxCell.RxD);
725 // get rx data buffer
726 pData = GET_OS_PKT_DATAPTR(pRxPacket);
727 pRxWI = (PRXWI_STRUC) pData;
728 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
731 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE);
732 RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI);
736 RxCell.pRxWI = pRxWI;
737 RxCell.pHeader = pHeader;
738 RxCell.pRxPacket = pRxPacket;
739 RxCell.pData = (UCHAR *) pHeader;
740 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
743 // Increase Total receive byte counter after real data received no mater any error or not
744 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
745 pAd->RalinkCounters.RxCount ++;
747 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
749 if (pRxWI->MPDUtotalByteCount < 14)
750 Status = NDIS_STATUS_FAILURE;
754 send_monitor_packets(pAd, &RxCell);
757 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
761 pAd->ate.RxCntPerSec++;
762 ATESampleRssi(pAd, pRxWI);
763 #ifdef RALINK_28xx_QA
764 if (pAd->ate.bQARxStart == TRUE)
766 /* (*pRxD) has been swapped in GetPacketFromRxRing() */
767 ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader);
769 #endif // RALINK_28xx_QA //
770 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
773 #endif // RALINK_ATE //
775 // Check for all RxD errors
776 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
778 // Handle the received frame
779 if (Status == NDIS_STATUS_SUCCESS)
781 switch (pHeader->FC.Type)
783 // CASE I, receive a DATA frame
786 // process DATA frame
787 STAHandleRxDataFrame(pAd, &RxCell);
790 // CASE II, receive a MGMT frame
793 STAHandleRxMgmtFrame(pAd, &RxCell);
796 // CASE III. receive a CNTL frame
799 STAHandleRxControlFrame(pAd, &RxCell);
802 // discard other type
804 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
810 pAd->Counters8023.RxErrors++;
811 // discard this frame
812 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
820 ========================================================================
824 pAd Pointer to our adapter
826 IRQL = DISPATCH_LEVEL
828 ========================================================================
830 VOID RTMPHandleTwakeupInterrupt(
831 IN PRTMP_ADAPTER pAd)
833 AsicForceWakeup(pAd, FALSE);
837 ========================================================================
839 Early checking and OS-depened parsing for Tx packet send to our STA driver.
842 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
843 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
844 UINT NumberOfPackets Number of packet in packet array.
850 This function do early checking and classification for send-out packet.
851 You only can put OS-depened & STA related code in here.
852 ========================================================================
855 IN NDIS_HANDLE MiniportAdapterContext,
856 IN PPNDIS_PACKET ppPacketArray,
857 IN UINT NumberOfPackets)
860 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
861 PNDIS_PACKET pPacket;
862 BOOLEAN allowToSend = FALSE;
865 for (Index = 0; Index < NumberOfPackets; Index++)
867 pPacket = ppPacketArray[Index];
871 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
872 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
873 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
875 // Drop send request since hardware is in reset state
878 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
880 // Drop send request since there are no physical connection yet
885 // Record that orignal packet source is from NDIS layer,so that
886 // later on driver knows how to release this NDIS PACKET
887 #ifdef QOS_DLS_SUPPORT
888 MAC_TABLE_ENTRY *pEntry;
889 PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
891 pEntry = MacTableLookup(pAd, pSrcBufVA);
892 if (pEntry && (pEntry->ValidAsDls == TRUE))
894 RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
897 #endif // QOS_DLS_SUPPORT //
898 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
899 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
900 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
901 pAd->RalinkCounters.PendingNdisPacketCount++;
907 if (allowToSend == TRUE)
908 STASendPacket(pAd, pPacket);
910 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
913 // Dequeue outgoing frames from TxSwQueue[] and process it
914 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
920 ========================================================================
922 This routine is used to do packet parsing and classification for Tx packet
923 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
927 pAd Pointer to our adapter
928 pPacket Pointer to send packet
931 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
932 NDIS_STATUS_FAILURE If failed to do en-queue.
935 You only can put OS-indepened & STA related code in here.
936 ========================================================================
938 NDIS_STATUS STASendPacket(
939 IN PRTMP_ADAPTER pAd,
940 IN PNDIS_PACKET pPacket)
942 PACKET_INFO PacketInfo;
947 // UCHAR RTSRequired;
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) &&
1114 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1117 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1120 // get Ethernet protocol field
1121 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1122 if (Protocol <= 1500)
1124 // get Ethernet protocol field from LLC/SNAP
1125 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1128 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1132 // always AC_BE for non-IP packet
1133 if (Protocol != 0x0800)
1137 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1140 // return AC_BE if packet is not IPv4
1141 if ((Byte0 & 0xf0) != 0x40)
1145 UserPriority = (Byte1 & 0xe0) >> 5;
1146 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1148 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1149 // TODO: downgrade UP & QueIdx before passing ACM
1150 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1158 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1162 // Make sure SendTxWait queue resource won't be used by other threads
1163 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1164 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1166 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1168 StopNetIfQueue(pAd, QueIdx, pPacket);
1169 #endif // BLOCK_NET_IF //
1170 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1172 return NDIS_STATUS_FAILURE;
1176 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1178 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1180 #ifdef DOT11_N_SUPPORT
1181 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1184 //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID];
1185 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1186 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1187 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1188 // For IOT compatibility, if
1189 // 1. It is Ralink chip or
1190 // 2. It is OPEN or AES mode,
1191 // then BA session can be bulit.
1192 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1193 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1196 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1199 #endif // DOT11_N_SUPPORT //
1201 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1202 return NDIS_STATUS_SUCCESS;
1207 ========================================================================
1209 Routine Description:
1210 This subroutine will scan through releative ring descriptor to find
1211 out avaliable free ring descriptor and compare with request size.
1214 pAd Pointer to our adapter
1215 QueIdx Selected TX Ring
1218 NDIS_STATUS_FAILURE Not enough free descriptor
1219 NDIS_STATUS_SUCCESS Enough free descriptor
1221 IRQL = PASSIVE_LEVEL
1222 IRQL = DISPATCH_LEVEL
1226 ========================================================================
1231 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1232 If no frame need to send, go to sleep, else, still wake up.
1234 NDIS_STATUS RTMPFreeTXDRequest(
1235 IN PRTMP_ADAPTER pAd,
1237 IN UCHAR NumberRequired,
1238 IN PUCHAR FreeNumberIs)
1240 //ULONG FreeNumber = 0;
1241 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1242 unsigned long IrqFlags;
1243 HT_TX_CONTEXT *pHTTXContext;
1253 pHTTXContext = &pAd->TxContext[QueIdx];
1254 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1255 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1256 (pHTTXContext->IRPPending == TRUE))
1258 Status = NDIS_STATUS_FAILURE;
1262 Status = NDIS_STATUS_SUCCESS;
1264 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1269 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1270 Status = NDIS_STATUS_FAILURE;
1272 Status = NDIS_STATUS_SUCCESS;
1276 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1286 VOID RTMPSendDisassociationFrame(
1287 IN PRTMP_ADAPTER pAd)
1291 VOID RTMPSendNullFrame(
1292 IN PRTMP_ADAPTER pAd,
1294 IN BOOLEAN bQosNull)
1296 UCHAR NullFrame[48];
1298 PHEADER_802_11 pHeader_802_11;
1306 #endif // RALINK_ATE //
1308 // WPA 802.1x secured port control
1309 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1310 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1311 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1312 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1313 #ifdef WPA_SUPPLICANT_SUPPORT
1314 || (pAd->StaCfg.IEEE8021X == TRUE)
1317 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1322 NdisZeroMemory(NullFrame, 48);
1323 Length = sizeof(HEADER_802_11);
1325 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1327 pHeader_802_11->FC.Type = BTYPE_DATA;
1328 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1329 pHeader_802_11->FC.ToDs = 1;
1330 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1331 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1332 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1334 if (pAd->CommonCfg.bAPSDForcePowerSave)
1336 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1340 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1342 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1345 pHeader_802_11->Sequence = pAd->Sequence;
1347 // Prepare QosNull function frame
1350 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1352 // copy QOS control bytes
1353 NullFrame[Length] = 0;
1354 NullFrame[Length+1] = 0;
1355 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1358 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1362 // IRQL = DISPATCH_LEVEL
1363 VOID RTMPSendRTSFrame(
1364 IN PRTMP_ADAPTER pAd,
1366 IN unsigned int NextMpduSize,
1369 IN USHORT AckDuration,
1377 // --------------------------------------------------------
1378 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1379 // Find the WPA key, either Group or Pairwise Key
1380 // LEAP + TKIP also use WPA key.
1381 // --------------------------------------------------------
1382 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1383 // In Cisco CCX 2.0 Leap Authentication
1384 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1385 // Instead of the SharedKey, SharedKey Length may be Zero.
1386 VOID STAFindCipherAlgorithm(
1387 IN PRTMP_ADAPTER pAd,
1390 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1391 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1392 UCHAR KeyIdx = 0xff;
1394 PCIPHER_KEY pKey = NULL;
1396 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1400 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1401 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1403 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1405 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1407 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1409 // 4-way handshaking frame must be clear
1410 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1411 (pAd->SharedKey[BSS0][0].KeyLen))
1413 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1417 else if (Cipher == Ndis802_11Encryption1Enabled)
1420 if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1422 if (LEAP_CCKM_ON(pAd))
1424 if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1430 KeyIdx = pAd->StaCfg.DefaultKeyId;
1432 else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1433 KeyIdx = pAd->StaCfg.DefaultKeyId;
1434 else if (LEAP_CCKM_ON(pAd))
1436 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1441 else // standard WEP64 or WEP128
1442 #endif // LEAP_SUPPORT //
1443 KeyIdx = pAd->StaCfg.DefaultKeyId;
1445 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1446 (Cipher == Ndis802_11Encryption3Enabled))
1448 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1449 KeyIdx = pAd->StaCfg.DefaultKeyId;
1450 else if (pAd->SharedKey[BSS0][0].KeyLen)
1453 KeyIdx = pAd->StaCfg.DefaultKeyId;
1457 CipherAlg = CIPHER_NONE;
1458 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1459 CipherAlg = CIPHER_NONE;
1460 #ifdef WPA_SUPPLICANT_SUPPORT
1461 else if ( pAd->StaCfg.WpaSupplicantUP &&
1462 (Cipher == Ndis802_11Encryption1Enabled) &&
1463 (pAd->StaCfg.IEEE8021X == TRUE) &&
1464 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1465 CipherAlg = CIPHER_NONE;
1466 #endif // WPA_SUPPLICANT_SUPPORT //
1469 //Header_802_11.FC.Wep = 1;
1470 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1471 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1475 pTxBlk->CipherAlg = CipherAlg;
1476 pTxBlk->pKey = pKey;
1480 VOID STABuildCommon802_11Header(
1481 IN PRTMP_ADAPTER pAd,
1485 HEADER_802_11 *pHeader_802_11;
1486 #ifdef QOS_DLS_SUPPORT
1487 BOOLEAN bDLSFrame = FALSE;
1488 INT DlsEntryIndex = 0;
1489 #endif // QOS_DLS_SUPPORT //
1492 // MAKE A COMMON 802.11 HEADER
1495 // normal wlan header size : 24 octets
1496 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1498 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1500 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1502 pHeader_802_11->FC.FrDs = 0;
1503 pHeader_802_11->FC.Type = BTYPE_DATA;
1504 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1506 #ifdef QOS_DLS_SUPPORT
1509 // Check if the frame can be sent through DLS direct link interface
1510 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1511 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1512 if (DlsEntryIndex >= 0)
1517 #endif // QOS_DLS_SUPPORT //
1519 if (pTxBlk->pMacEntry)
1521 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1523 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1524 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1528 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1529 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1534 pHeader_802_11->Sequence = pAd->Sequence;
1535 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1538 pHeader_802_11->Frag = 0;
1540 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1545 #ifdef QOS_DLS_SUPPORT
1548 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1549 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1550 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1551 pHeader_802_11->FC.ToDs = 0;
1554 #endif // QOS_DLS_SUPPORT //
1556 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1557 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1558 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1559 pHeader_802_11->FC.ToDs = 1;
1562 else if (ADHOC_ON(pAd))
1564 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1565 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1566 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1567 pHeader_802_11->FC.ToDs = 0;
1571 if (pTxBlk->CipherAlg != CIPHER_NONE)
1572 pHeader_802_11->FC.Wep = 1;
1574 // -----------------------------------------------------------------
1575 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1576 // -----------------------------------------------------------------
1577 if (pAd->CommonCfg.bAPSDForcePowerSave)
1578 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1580 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1583 #ifdef DOT11_N_SUPPORT
1584 VOID STABuildCache802_11Header(
1585 IN RTMP_ADAPTER *pAd,
1589 MAC_TABLE_ENTRY *pMacEntry;
1590 PHEADER_802_11 pHeader80211;
1592 pHeader80211 = (PHEADER_802_11)pHeader;
1593 pMacEntry = pTxBlk->pMacEntry;
1596 // Update the cached 802.11 HEADER
1599 // normal wlan header size : 24 octets
1600 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1603 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1606 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1607 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1610 // Check if the frame can be sent through DLS direct link interface
1611 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1612 #ifdef QOS_DLS_SUPPORT
1613 BOOLEAN bDLSFrame = FALSE;
1614 INT DlsEntryIndex = 0;
1616 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1617 if (DlsEntryIndex >= 0)
1621 #endif // QOS_DLS_SUPPORT //
1623 // The addr3 of normal packet send from DS is Dest Mac address.
1624 #ifdef QOS_DLS_SUPPORT
1627 COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
1628 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1629 pHeader80211->FC.ToDs = 0;
1632 #endif // QOS_DLS_SUPPORT //
1634 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1636 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1639 // -----------------------------------------------------------------
1640 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1641 // -----------------------------------------------------------------
1642 if (pAd->CommonCfg.bAPSDForcePowerSave)
1643 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1645 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1647 #endif // DOT11_N_SUPPORT //
1649 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1650 IN RTMP_ADAPTER *pAd,
1653 PUCHAR pHeaderBufPtr;
1654 HEADER_802_11 *pHeader_802_11;
1655 PNDIS_PACKET pNextPacket;
1657 PQUEUE_ENTRY pQEntry;
1659 STAFindCipherAlgorithm(pAd, pTxBlk);
1660 STABuildCommon802_11Header(pAd, pTxBlk);
1663 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1664 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1666 // steal "order" bit to mark "aggregation"
1667 pHeader_802_11->FC.Order = 1;
1669 // skip common header
1670 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1672 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1675 // build QOS Control bytes
1677 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1679 *(pHeaderBufPtr+1) = 0;
1681 pTxBlk->MpduHeaderLen += 2;
1684 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1685 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1686 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1687 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1689 // For RA Aggregation,
1690 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1691 pQEntry = pTxBlk->TxPacketList.Head;
1692 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1693 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1694 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1695 nextBufLen -= LENGTH_802_1Q;
1697 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1698 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1701 pTxBlk->MpduHeaderLen += 2;
1703 return pHeaderBufPtr;
1707 #ifdef DOT11_N_SUPPORT
1708 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1709 IN RTMP_ADAPTER *pAd,
1712 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1713 HEADER_802_11 *pHeader_802_11;
1716 STAFindCipherAlgorithm(pAd, pTxBlk);
1717 STABuildCommon802_11Header(pAd, pTxBlk);
1719 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1720 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1722 // skip common header
1723 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1726 // build QOS Control bytes
1728 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1733 *pHeaderBufPtr |= 0x80;
1735 *(pHeaderBufPtr+1) = 0;
1737 pTxBlk->MpduHeaderLen += 2;
1739 //pSaveBufPtr = pHeaderBufPtr;
1742 // padding at front of LLC header
1743 // LLC header should locate at 4-octets aligment
1745 // @@@ MpduHeaderLen excluding padding @@@
1747 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1748 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1749 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1751 return pHeaderBufPtr;
1756 VOID STA_AMPDU_Frame_Tx(
1757 IN PRTMP_ADAPTER pAd,
1760 HEADER_802_11 *pHeader_802_11;
1761 PUCHAR pHeaderBufPtr;
1763 MAC_TABLE_ENTRY *pMacEntry;
1765 PQUEUE_ENTRY pQEntry;
1769 while(pTxBlk->TxPacketList.Head)
1771 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1772 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1773 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1775 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1779 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1781 pMacEntry = pTxBlk->pMacEntry;
1782 if (pMacEntry->isCached)
1784 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1785 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1786 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1787 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1791 STAFindCipherAlgorithm(pAd, pTxBlk);
1792 STABuildCommon802_11Header(pAd, pTxBlk);
1794 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1798 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1800 // skip common header
1801 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1804 // build QOS Control bytes
1806 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1807 *(pHeaderBufPtr+1) = 0;
1809 pTxBlk->MpduHeaderLen += 2;
1813 // HTC control filed following QoS field
1815 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1817 if (pMacEntry->isCached == FALSE)
1820 pHeader_802_11->FC.Order = 1;
1822 NdisZeroMemory(pHeaderBufPtr, 4);
1823 *(pHeaderBufPtr+3) |= 0x80;
1826 pTxBlk->MpduHeaderLen += 4;
1829 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1830 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1832 // skip 802.3 header
1833 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1834 pTxBlk->SrcBufLen -= LENGTH_802_3;
1839 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1840 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1844 // padding at front of LLC header
1845 // LLC header should locate at 4-octets aligment
1847 // @@@ MpduHeaderLen excluding padding @@@
1849 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1850 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1851 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1856 // Insert LLC-SNAP encapsulation - 8 octets
1858 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1859 if (pTxBlk->pExtraLlcSnapEncap)
1861 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1863 // get 2 octets (TypeofLen)
1864 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1866 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1871 if (pMacEntry->isCached)
1873 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1877 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1879 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1880 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1881 pMacEntry->isCached = TRUE;
1884 // calculate Transmitted AMPDU count and ByteCount
1886 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1887 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1890 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1892 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1897 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1899 pAd->RalinkCounters.KickTxCount++;
1900 pAd->RalinkCounters.OneSecTxDoneCount++;
1906 VOID STA_AMSDU_Frame_Tx(
1907 IN PRTMP_ADAPTER pAd,
1910 PUCHAR pHeaderBufPtr;
1912 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1913 USHORT totalMPDUSize=0;
1914 UCHAR *subFrameHeader;
1916 USHORT FirstTx = 0, LastTxIdx = 0;
1919 PQUEUE_ENTRY pQEntry;
1924 ASSERT((pTxBlk->TxPacketList.Number > 1));
1926 while(pTxBlk->TxPacketList.Head)
1928 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1929 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1930 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1932 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1936 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1938 // skip 802.3 header
1939 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1940 pTxBlk->SrcBufLen -= LENGTH_802_3;
1945 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1946 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1951 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1953 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1954 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1958 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1959 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1960 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1961 pHeaderBufPtr += padding;
1962 pTxBlk->MpduHeaderLen = padding;
1967 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1969 subFrameHeader = pHeaderBufPtr;
1970 subFramePayloadLen = pTxBlk->SrcBufLen;
1972 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1975 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1976 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1980 // Insert LLC-SNAP encapsulation - 8 octets
1982 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1984 subFramePayloadLen = pTxBlk->SrcBufLen;
1986 if (pTxBlk->pExtraLlcSnapEncap)
1988 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1990 // get 2 octets (TypeofLen)
1991 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1993 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1994 subFramePayloadLen += LENGTH_802_1_H;
1997 // update subFrame Length field
1998 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1999 subFrameHeader[13] = subFramePayloadLen & 0xFF;
2001 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2004 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2006 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2010 pAd->RalinkCounters.KickTxCount++;
2011 pAd->RalinkCounters.OneSecTxDoneCount++;
2013 // calculate Transmitted AMSDU Count and ByteCount
2015 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
2016 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
2021 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2022 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2027 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2029 #endif // DOT11_N_SUPPORT //
2031 VOID STA_Legacy_Frame_Tx(
2032 IN PRTMP_ADAPTER pAd,
2035 HEADER_802_11 *pHeader_802_11;
2036 PUCHAR pHeaderBufPtr;
2039 PQUEUE_ENTRY pQEntry;
2044 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2045 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2046 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2048 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2052 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
2054 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
2057 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
2058 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
2060 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
2062 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2064 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
2065 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
2067 STAFindCipherAlgorithm(pAd, pTxBlk);
2068 STABuildCommon802_11Header(pAd, pTxBlk);
2071 // skip 802.3 header
2072 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2073 pTxBlk->SrcBufLen -= LENGTH_802_3;
2078 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2079 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2082 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2083 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
2085 // skip common header
2086 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2088 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2091 // build QOS Control bytes
2093 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2094 *(pHeaderBufPtr+1) = 0;
2096 pTxBlk->MpduHeaderLen += 2;
2099 // The remaining content of MPDU header should locate at 4-octets aligment
2100 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2101 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2102 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2107 // Insert LLC-SNAP encapsulation - 8 octets
2110 // if original Ethernet frame contains no LLC/SNAP,
2111 // then an extra LLC/SNAP encap is required
2113 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2114 if (pTxBlk->pExtraLlcSnapEncap)
2118 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2121 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2122 // get 2 octets (TypeofLen)
2123 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2125 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2132 // use Wcid as Key Index
2135 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2137 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2139 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2141 pAd->RalinkCounters.KickTxCount++;
2142 pAd->RalinkCounters.OneSecTxDoneCount++;
2147 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2151 VOID STA_ARalink_Frame_Tx(
2152 IN PRTMP_ADAPTER pAd,
2155 PUCHAR pHeaderBufPtr;
2157 USHORT totalMPDUSize=0;
2158 USHORT FirstTx, LastTxIdx;
2161 PQUEUE_ENTRY pQEntry;
2166 ASSERT((pTxBlk->TxPacketList.Number== 2));
2169 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2170 while(pTxBlk->TxPacketList.Head)
2172 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2173 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2175 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2177 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2181 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2183 // skip 802.3 header
2184 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2185 pTxBlk->SrcBufLen -= LENGTH_802_3;
2190 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2191 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2195 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2197 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2199 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2200 // will be updated after final frame was handled.
2201 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2205 // Insert LLC-SNAP encapsulation - 8 octets
2207 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2209 if (pTxBlk->pExtraLlcSnapEncap)
2211 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2213 // get 2 octets (TypeofLen)
2214 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2216 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2220 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2222 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2223 pTxBlk->MpduHeaderLen = 0;
2225 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2226 // DA(6)+SA(6)+FrameType(2)
2227 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2228 pHeaderBufPtr += 12;
2229 // get 2 octets (TypeofLen)
2230 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2232 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2235 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2237 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2239 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2241 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2245 pAd->RalinkCounters.OneSecTxAggregationCount++;
2246 pAd->RalinkCounters.KickTxCount++;
2247 pAd->RalinkCounters.OneSecTxDoneCount++;
2251 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2252 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
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, TRUE);
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);