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 */
759 // Check for all RxD errors
760 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
762 // Handle the received frame
763 if (Status == NDIS_STATUS_SUCCESS)
765 switch (pHeader->FC.Type)
767 // CASE I, receive a DATA frame
770 // process DATA frame
771 STAHandleRxDataFrame(pAd, &RxCell);
774 // CASE II, receive a MGMT frame
777 STAHandleRxMgmtFrame(pAd, &RxCell);
780 // CASE III. receive a CNTL frame
783 STAHandleRxControlFrame(pAd, &RxCell);
786 // discard other type
788 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
794 pAd->Counters8023.RxErrors++;
795 // discard this frame
796 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
804 ========================================================================
808 pAd Pointer to our adapter
810 IRQL = DISPATCH_LEVEL
812 ========================================================================
814 VOID RTMPHandleTwakeupInterrupt(
815 IN PRTMP_ADAPTER pAd)
817 AsicForceWakeup(pAd, FALSE);
821 ========================================================================
823 Early checking and OS-depened parsing for Tx packet send to our STA driver.
826 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
827 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
828 UINT NumberOfPackets Number of packet in packet array.
834 This function do early checking and classification for send-out packet.
835 You only can put OS-depened & STA related code in here.
836 ========================================================================
839 IN NDIS_HANDLE MiniportAdapterContext,
840 IN PPNDIS_PACKET ppPacketArray,
841 IN UINT NumberOfPackets)
844 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
845 PNDIS_PACKET pPacket;
846 BOOLEAN allowToSend = FALSE;
849 for (Index = 0; Index < NumberOfPackets; Index++)
851 pPacket = ppPacketArray[Index];
855 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
856 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
857 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
859 // Drop send request since hardware is in reset state
862 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
864 // Drop send request since there are no physical connection yet
869 // Record that orignal packet source is from NDIS layer,so that
870 // later on driver knows how to release this NDIS PACKET
871 #ifdef QOS_DLS_SUPPORT
872 MAC_TABLE_ENTRY *pEntry;
873 PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
875 pEntry = MacTableLookup(pAd, pSrcBufVA);
876 if (pEntry && (pEntry->ValidAsDls == TRUE))
878 RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
881 #endif // QOS_DLS_SUPPORT //
882 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
883 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
884 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
885 pAd->RalinkCounters.PendingNdisPacketCount++;
891 if (allowToSend == TRUE)
892 STASendPacket(pAd, pPacket);
894 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
897 // Dequeue outgoing frames from TxSwQueue[] and process it
898 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
904 ========================================================================
906 This routine is used to do packet parsing and classification for Tx packet
907 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
911 pAd Pointer to our adapter
912 pPacket Pointer to send packet
915 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
916 NDIS_STATUS_FAILURE If failed to do en-queue.
919 You only can put OS-indepened & STA related code in here.
920 ========================================================================
922 NDIS_STATUS STASendPacket(
923 IN PRTMP_ADAPTER pAd,
924 IN PNDIS_PACKET pPacket)
926 PACKET_INFO PacketInfo;
931 // UCHAR RTSRequired;
932 UCHAR QueIdx, UserPriority;
933 MAC_TABLE_ENTRY *pEntry = NULL;
934 unsigned int IrqFlags;
938 // Prepare packet information structure for buffer descriptor
939 // chained within a single NDIS packet.
940 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
942 if (pSrcBufVA == NULL)
944 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
945 // Resourece is low, system did not allocate virtual address
946 // return NDIS_STATUS_FAILURE directly to upper layer
947 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
948 return NDIS_STATUS_FAILURE;
954 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
955 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
956 return (NDIS_STATUS_FAILURE);
959 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
960 // Note multicast packets in adhoc also use BSSID_WCID index.
964 #ifdef QOS_DLS_SUPPORT
967 tmpWcid = RTMP_GET_PACKET_WCID(pPacket);
968 if (VALID_WCID(tmpWcid) &&
969 (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE))
971 pEntry = &pAd->MacTab.Content[tmpWcid];
972 Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate;
975 #endif // QOS_DLS_SUPPORT //
977 pEntry = &pAd->MacTab.Content[BSSID_WCID];
978 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
979 Rate = pAd->CommonCfg.TxRate;
982 else if (ADHOC_ON(pAd))
984 if (*pSrcBufVA & 0x01)
986 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
987 pEntry = &pAd->MacTab.Content[MCAST_WCID];
991 pEntry = MacTableLookup(pAd, pSrcBufVA);
993 Rate = pAd->CommonCfg.TxRate;
999 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
1000 // Resourece is low, system did not allocate virtual address
1001 // return NDIS_STATUS_FAILURE directly to upper layer
1002 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1003 return NDIS_STATUS_FAILURE;
1009 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
1013 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
1014 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
1015 RTMPCheckEtherType(pAd, pPacket);
1020 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
1022 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1023 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1024 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1025 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1026 #ifdef WPA_SUPPLICANT_SUPPORT
1027 || (pAd->StaCfg.IEEE8021X == TRUE)
1028 #endif // WPA_SUPPLICANT_SUPPORT //
1030 || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
1031 #endif // LEAP_SUPPORT //
1033 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1034 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1037 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1038 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1040 return (NDIS_STATUS_FAILURE);
1044 // STEP 1. Decide number of fragments required to deliver this MSDU.
1045 // The estimation here is not very accurate because difficult to
1046 // take encryption overhead into consideration here. The result
1047 // "NumberOfFrag" is then just used to pre-check if enough free
1048 // TXD are available to hold this MSDU.
1051 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1053 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1054 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1055 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1056 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1057 #ifdef DOT11_N_SUPPORT
1058 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1059 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1060 #endif // DOT11_N_SUPPORT //
1063 // The calculated "NumberOfFrag" is a rough estimation because of various
1064 // encryption/encapsulation overhead not taken into consideration. This number is just
1065 // used to make sure enough free TXD are available before fragmentation takes place.
1066 // In case the actual required number of fragments of an NDIS packet
1067 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1068 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1069 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1070 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1072 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1073 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1074 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1075 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1081 // Save fragment number to Ndis packet reserved field
1082 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1085 // STEP 2. Check the requirement of RTS:
1086 // If multiple fragment required, RTS is required only for the first fragment
1087 // if the fragment size large than RTS threshold
1088 // For RT28xx, Let ASIC send RTS/CTS
1089 RTMP_SET_PACKET_RTS(pPacket, 0);
1090 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1093 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1097 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1098 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1101 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1104 // get Ethernet protocol field
1105 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1106 if (Protocol <= 1500)
1108 // get Ethernet protocol field from LLC/SNAP
1109 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1112 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1116 // always AC_BE for non-IP packet
1117 if (Protocol != 0x0800)
1121 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1124 // return AC_BE if packet is not IPv4
1125 if ((Byte0 & 0xf0) != 0x40)
1129 UserPriority = (Byte1 & 0xe0) >> 5;
1130 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1132 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1133 // TODO: downgrade UP & QueIdx before passing ACM
1134 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1142 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1146 // Make sure SendTxWait queue resource won't be used by other threads
1147 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1148 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1150 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1151 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1153 return NDIS_STATUS_FAILURE;
1157 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1159 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1161 #ifdef DOT11_N_SUPPORT
1162 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1165 //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID];
1166 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1167 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1168 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1169 // For IOT compatibility, if
1170 // 1. It is Ralink chip or
1171 // 2. It is OPEN or AES mode,
1172 // then BA session can be bulit.
1173 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1174 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1177 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1180 #endif // DOT11_N_SUPPORT //
1182 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1183 return NDIS_STATUS_SUCCESS;
1188 ========================================================================
1190 Routine Description:
1191 This subroutine will scan through releative ring descriptor to find
1192 out avaliable free ring descriptor and compare with request size.
1195 pAd Pointer to our adapter
1196 QueIdx Selected TX Ring
1199 NDIS_STATUS_FAILURE Not enough free descriptor
1200 NDIS_STATUS_SUCCESS Enough free descriptor
1202 IRQL = PASSIVE_LEVEL
1203 IRQL = DISPATCH_LEVEL
1207 ========================================================================
1212 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1213 If no frame need to send, go to sleep, else, still wake up.
1215 NDIS_STATUS RTMPFreeTXDRequest(
1216 IN PRTMP_ADAPTER pAd,
1218 IN UCHAR NumberRequired,
1219 IN PUCHAR FreeNumberIs)
1221 //ULONG FreeNumber = 0;
1222 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1223 unsigned long IrqFlags;
1224 HT_TX_CONTEXT *pHTTXContext;
1234 pHTTXContext = &pAd->TxContext[QueIdx];
1235 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1236 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1237 (pHTTXContext->IRPPending == TRUE))
1239 Status = NDIS_STATUS_FAILURE;
1243 Status = NDIS_STATUS_SUCCESS;
1245 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1250 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1251 Status = NDIS_STATUS_FAILURE;
1253 Status = NDIS_STATUS_SUCCESS;
1257 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1267 VOID RTMPSendDisassociationFrame(
1268 IN PRTMP_ADAPTER pAd)
1272 VOID RTMPSendNullFrame(
1273 IN PRTMP_ADAPTER pAd,
1275 IN BOOLEAN bQosNull)
1277 UCHAR NullFrame[48];
1279 PHEADER_802_11 pHeader_802_11;
1281 // WPA 802.1x secured port control
1282 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1283 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1284 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1285 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1286 #ifdef WPA_SUPPLICANT_SUPPORT
1287 || (pAd->StaCfg.IEEE8021X == TRUE)
1290 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1295 NdisZeroMemory(NullFrame, 48);
1296 Length = sizeof(HEADER_802_11);
1298 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1300 pHeader_802_11->FC.Type = BTYPE_DATA;
1301 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1302 pHeader_802_11->FC.ToDs = 1;
1303 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1304 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1305 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1307 if (pAd->CommonCfg.bAPSDForcePowerSave)
1309 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1313 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1315 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1318 pHeader_802_11->Sequence = pAd->Sequence;
1320 // Prepare QosNull function frame
1323 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1325 // copy QOS control bytes
1326 NullFrame[Length] = 0;
1327 NullFrame[Length+1] = 0;
1328 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1331 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1335 // IRQL = DISPATCH_LEVEL
1336 VOID RTMPSendRTSFrame(
1337 IN PRTMP_ADAPTER pAd,
1339 IN unsigned int NextMpduSize,
1342 IN USHORT AckDuration,
1350 // --------------------------------------------------------
1351 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1352 // Find the WPA key, either Group or Pairwise Key
1353 // LEAP + TKIP also use WPA key.
1354 // --------------------------------------------------------
1355 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1356 // In Cisco CCX 2.0 Leap Authentication
1357 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1358 // Instead of the SharedKey, SharedKey Length may be Zero.
1359 VOID STAFindCipherAlgorithm(
1360 IN PRTMP_ADAPTER pAd,
1363 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1364 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1365 UCHAR KeyIdx = 0xff;
1367 PCIPHER_KEY pKey = NULL;
1369 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1373 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1374 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1376 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1378 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1380 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1382 // 4-way handshaking frame must be clear
1383 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1384 (pAd->SharedKey[BSS0][0].KeyLen))
1386 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1390 else if (Cipher == Ndis802_11Encryption1Enabled)
1393 if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1395 if (LEAP_CCKM_ON(pAd))
1397 if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1403 KeyIdx = pAd->StaCfg.DefaultKeyId;
1405 else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1406 KeyIdx = pAd->StaCfg.DefaultKeyId;
1407 else if (LEAP_CCKM_ON(pAd))
1409 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1414 else // standard WEP64 or WEP128
1415 #endif // LEAP_SUPPORT //
1416 KeyIdx = pAd->StaCfg.DefaultKeyId;
1418 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1419 (Cipher == Ndis802_11Encryption3Enabled))
1421 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1422 KeyIdx = pAd->StaCfg.DefaultKeyId;
1423 else if (pAd->SharedKey[BSS0][0].KeyLen)
1426 KeyIdx = pAd->StaCfg.DefaultKeyId;
1430 CipherAlg = CIPHER_NONE;
1431 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1432 CipherAlg = CIPHER_NONE;
1433 #ifdef WPA_SUPPLICANT_SUPPORT
1434 else if ( pAd->StaCfg.WpaSupplicantUP &&
1435 (Cipher == Ndis802_11Encryption1Enabled) &&
1436 (pAd->StaCfg.IEEE8021X == TRUE) &&
1437 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1438 CipherAlg = CIPHER_NONE;
1439 #endif // WPA_SUPPLICANT_SUPPORT //
1442 //Header_802_11.FC.Wep = 1;
1443 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1444 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1448 pTxBlk->CipherAlg = CipherAlg;
1449 pTxBlk->pKey = pKey;
1453 VOID STABuildCommon802_11Header(
1454 IN PRTMP_ADAPTER pAd,
1458 HEADER_802_11 *pHeader_802_11;
1459 #ifdef QOS_DLS_SUPPORT
1460 BOOLEAN bDLSFrame = FALSE;
1461 INT DlsEntryIndex = 0;
1462 #endif // QOS_DLS_SUPPORT //
1465 // MAKE A COMMON 802.11 HEADER
1468 // normal wlan header size : 24 octets
1469 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1471 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1473 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1475 pHeader_802_11->FC.FrDs = 0;
1476 pHeader_802_11->FC.Type = BTYPE_DATA;
1477 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1479 #ifdef QOS_DLS_SUPPORT
1482 // Check if the frame can be sent through DLS direct link interface
1483 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1484 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1485 if (DlsEntryIndex >= 0)
1490 #endif // QOS_DLS_SUPPORT //
1492 if (pTxBlk->pMacEntry)
1494 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1496 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1497 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1501 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1502 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1507 pHeader_802_11->Sequence = pAd->Sequence;
1508 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1511 pHeader_802_11->Frag = 0;
1513 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1518 #ifdef QOS_DLS_SUPPORT
1521 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1522 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1523 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1524 pHeader_802_11->FC.ToDs = 0;
1527 #endif // QOS_DLS_SUPPORT //
1529 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1530 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1531 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1532 pHeader_802_11->FC.ToDs = 1;
1535 else if (ADHOC_ON(pAd))
1537 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1538 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1539 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1540 pHeader_802_11->FC.ToDs = 0;
1544 if (pTxBlk->CipherAlg != CIPHER_NONE)
1545 pHeader_802_11->FC.Wep = 1;
1547 // -----------------------------------------------------------------
1548 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1549 // -----------------------------------------------------------------
1550 if (pAd->CommonCfg.bAPSDForcePowerSave)
1551 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1553 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1556 #ifdef DOT11_N_SUPPORT
1557 VOID STABuildCache802_11Header(
1558 IN RTMP_ADAPTER *pAd,
1562 MAC_TABLE_ENTRY *pMacEntry;
1563 PHEADER_802_11 pHeader80211;
1565 pHeader80211 = (PHEADER_802_11)pHeader;
1566 pMacEntry = pTxBlk->pMacEntry;
1569 // Update the cached 802.11 HEADER
1572 // normal wlan header size : 24 octets
1573 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1576 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1579 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1580 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1583 // Check if the frame can be sent through DLS direct link interface
1584 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1585 #ifdef QOS_DLS_SUPPORT
1586 BOOLEAN bDLSFrame = FALSE;
1587 INT DlsEntryIndex = 0;
1589 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1590 if (DlsEntryIndex >= 0)
1594 #endif // QOS_DLS_SUPPORT //
1596 // The addr3 of normal packet send from DS is Dest Mac address.
1597 #ifdef QOS_DLS_SUPPORT
1600 COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
1601 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1602 pHeader80211->FC.ToDs = 0;
1605 #endif // QOS_DLS_SUPPORT //
1607 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1609 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1612 // -----------------------------------------------------------------
1613 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1614 // -----------------------------------------------------------------
1615 if (pAd->CommonCfg.bAPSDForcePowerSave)
1616 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1618 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1620 #endif // DOT11_N_SUPPORT //
1622 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1623 IN RTMP_ADAPTER *pAd,
1626 PUCHAR pHeaderBufPtr;
1627 HEADER_802_11 *pHeader_802_11;
1628 PNDIS_PACKET pNextPacket;
1630 PQUEUE_ENTRY pQEntry;
1632 STAFindCipherAlgorithm(pAd, pTxBlk);
1633 STABuildCommon802_11Header(pAd, pTxBlk);
1636 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1637 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1639 // steal "order" bit to mark "aggregation"
1640 pHeader_802_11->FC.Order = 1;
1642 // skip common header
1643 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1645 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1648 // build QOS Control bytes
1650 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1652 *(pHeaderBufPtr+1) = 0;
1654 pTxBlk->MpduHeaderLen += 2;
1657 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1658 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1659 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1660 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1662 // For RA Aggregation,
1663 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1664 pQEntry = pTxBlk->TxPacketList.Head;
1665 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1666 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1667 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1668 nextBufLen -= LENGTH_802_1Q;
1670 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1671 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1674 pTxBlk->MpduHeaderLen += 2;
1676 return pHeaderBufPtr;
1680 #ifdef DOT11_N_SUPPORT
1681 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1682 IN RTMP_ADAPTER *pAd,
1685 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1686 HEADER_802_11 *pHeader_802_11;
1689 STAFindCipherAlgorithm(pAd, pTxBlk);
1690 STABuildCommon802_11Header(pAd, pTxBlk);
1692 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1693 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1695 // skip common header
1696 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1699 // build QOS Control bytes
1701 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1706 *pHeaderBufPtr |= 0x80;
1708 *(pHeaderBufPtr+1) = 0;
1710 pTxBlk->MpduHeaderLen += 2;
1712 //pSaveBufPtr = pHeaderBufPtr;
1715 // padding at front of LLC header
1716 // LLC header should locate at 4-octets aligment
1718 // @@@ MpduHeaderLen excluding padding @@@
1720 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1721 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1722 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1724 return pHeaderBufPtr;
1729 VOID STA_AMPDU_Frame_Tx(
1730 IN PRTMP_ADAPTER pAd,
1733 HEADER_802_11 *pHeader_802_11;
1734 PUCHAR pHeaderBufPtr;
1736 MAC_TABLE_ENTRY *pMacEntry;
1738 PQUEUE_ENTRY pQEntry;
1742 while(pTxBlk->TxPacketList.Head)
1744 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1745 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1746 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1748 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1752 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1754 pMacEntry = pTxBlk->pMacEntry;
1755 if (pMacEntry->isCached)
1757 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1758 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1759 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1760 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1764 STAFindCipherAlgorithm(pAd, pTxBlk);
1765 STABuildCommon802_11Header(pAd, pTxBlk);
1767 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1771 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1773 // skip common header
1774 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1777 // build QOS Control bytes
1779 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1780 *(pHeaderBufPtr+1) = 0;
1782 pTxBlk->MpduHeaderLen += 2;
1786 // HTC control filed following QoS field
1788 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1790 if (pMacEntry->isCached == FALSE)
1793 pHeader_802_11->FC.Order = 1;
1795 NdisZeroMemory(pHeaderBufPtr, 4);
1796 *(pHeaderBufPtr+3) |= 0x80;
1799 pTxBlk->MpduHeaderLen += 4;
1802 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1803 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1805 // skip 802.3 header
1806 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1807 pTxBlk->SrcBufLen -= LENGTH_802_3;
1812 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1813 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1817 // padding at front of LLC header
1818 // LLC header should locate at 4-octets aligment
1820 // @@@ MpduHeaderLen excluding padding @@@
1822 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1823 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1824 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1829 // Insert LLC-SNAP encapsulation - 8 octets
1831 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1832 if (pTxBlk->pExtraLlcSnapEncap)
1834 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1836 // get 2 octets (TypeofLen)
1837 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1839 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1844 if (pMacEntry->isCached)
1846 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1850 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1852 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1853 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1854 pMacEntry->isCached = TRUE;
1857 // calculate Transmitted AMPDU count and ByteCount
1859 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1860 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1863 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1865 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1870 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1872 pAd->RalinkCounters.KickTxCount++;
1873 pAd->RalinkCounters.OneSecTxDoneCount++;
1879 VOID STA_AMSDU_Frame_Tx(
1880 IN PRTMP_ADAPTER pAd,
1883 PUCHAR pHeaderBufPtr;
1885 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1886 USHORT totalMPDUSize=0;
1887 UCHAR *subFrameHeader;
1889 USHORT FirstTx = 0, LastTxIdx = 0;
1892 PQUEUE_ENTRY pQEntry;
1897 ASSERT((pTxBlk->TxPacketList.Number > 1));
1899 while(pTxBlk->TxPacketList.Head)
1901 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1902 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1903 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1905 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1909 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1911 // skip 802.3 header
1912 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1913 pTxBlk->SrcBufLen -= LENGTH_802_3;
1918 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1919 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1924 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1926 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1927 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1931 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1932 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1933 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1934 pHeaderBufPtr += padding;
1935 pTxBlk->MpduHeaderLen = padding;
1940 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1942 subFrameHeader = pHeaderBufPtr;
1943 subFramePayloadLen = pTxBlk->SrcBufLen;
1945 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1948 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1949 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1953 // Insert LLC-SNAP encapsulation - 8 octets
1955 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1957 subFramePayloadLen = pTxBlk->SrcBufLen;
1959 if (pTxBlk->pExtraLlcSnapEncap)
1961 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1963 // get 2 octets (TypeofLen)
1964 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1966 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1967 subFramePayloadLen += LENGTH_802_1_H;
1970 // update subFrame Length field
1971 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1972 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1974 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1977 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1979 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1983 pAd->RalinkCounters.KickTxCount++;
1984 pAd->RalinkCounters.OneSecTxDoneCount++;
1986 // calculate Transmitted AMSDU Count and ByteCount
1988 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1989 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1994 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1995 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2000 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2002 #endif // DOT11_N_SUPPORT //
2004 VOID STA_Legacy_Frame_Tx(
2005 IN PRTMP_ADAPTER pAd,
2008 HEADER_802_11 *pHeader_802_11;
2009 PUCHAR pHeaderBufPtr;
2012 PQUEUE_ENTRY pQEntry;
2017 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2018 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2019 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2021 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2025 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
2027 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
2030 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
2031 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
2033 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
2035 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2037 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
2038 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
2040 STAFindCipherAlgorithm(pAd, pTxBlk);
2041 STABuildCommon802_11Header(pAd, pTxBlk);
2044 // skip 802.3 header
2045 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2046 pTxBlk->SrcBufLen -= LENGTH_802_3;
2051 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2052 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2055 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2056 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
2058 // skip common header
2059 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2061 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2064 // build QOS Control bytes
2066 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2067 *(pHeaderBufPtr+1) = 0;
2069 pTxBlk->MpduHeaderLen += 2;
2072 // The remaining content of MPDU header should locate at 4-octets aligment
2073 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2074 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2075 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2080 // Insert LLC-SNAP encapsulation - 8 octets
2083 // if original Ethernet frame contains no LLC/SNAP,
2084 // then an extra LLC/SNAP encap is required
2086 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2087 if (pTxBlk->pExtraLlcSnapEncap)
2091 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2094 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2095 // get 2 octets (TypeofLen)
2096 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2098 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2105 // use Wcid as Key Index
2108 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2110 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2112 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2114 pAd->RalinkCounters.KickTxCount++;
2115 pAd->RalinkCounters.OneSecTxDoneCount++;
2120 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2124 VOID STA_ARalink_Frame_Tx(
2125 IN PRTMP_ADAPTER pAd,
2128 PUCHAR pHeaderBufPtr;
2130 USHORT totalMPDUSize=0;
2131 USHORT FirstTx, LastTxIdx;
2134 PQUEUE_ENTRY pQEntry;
2139 ASSERT((pTxBlk->TxPacketList.Number== 2));
2142 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2143 while(pTxBlk->TxPacketList.Head)
2145 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2146 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2148 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2150 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2154 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2156 // skip 802.3 header
2157 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2158 pTxBlk->SrcBufLen -= LENGTH_802_3;
2163 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2164 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2168 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2170 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2172 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2173 // will be updated after final frame was handled.
2174 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2178 // Insert LLC-SNAP encapsulation - 8 octets
2180 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2182 if (pTxBlk->pExtraLlcSnapEncap)
2184 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2186 // get 2 octets (TypeofLen)
2187 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2189 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2193 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2195 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2196 pTxBlk->MpduHeaderLen = 0;
2198 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2199 // DA(6)+SA(6)+FrameType(2)
2200 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2201 pHeaderBufPtr += 12;
2202 // get 2 octets (TypeofLen)
2203 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2205 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2208 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2210 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2212 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2214 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2218 pAd->RalinkCounters.OneSecTxAggregationCount++;
2219 pAd->RalinkCounters.KickTxCount++;
2220 pAd->RalinkCounters.OneSecTxDoneCount++;
2224 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2225 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2230 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2235 VOID STA_Fragment_Frame_Tx(
2236 IN RTMP_ADAPTER *pAd,
2239 HEADER_802_11 *pHeader_802_11;
2240 PUCHAR pHeaderBufPtr;
2243 PACKET_INFO PacketInfo;
2244 USHORT EncryptionOverhead = 0;
2245 UINT32 FreeMpduSize, SrcRemainingBytes;
2249 PQUEUE_ENTRY pQEntry;
2254 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2255 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2256 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2258 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2262 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2263 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2265 STAFindCipherAlgorithm(pAd, pTxBlk);
2266 STABuildCommon802_11Header(pAd, pTxBlk);
2268 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2270 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2271 if (pTxBlk->pPacket == NULL)
2273 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2276 // skip 802.3 header
2277 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2278 pTxBlk->SrcBufLen -= LENGTH_802_3;
2284 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2285 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2288 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2289 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2292 // skip common header
2293 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2295 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2298 // build QOS Control bytes
2300 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2302 *(pHeaderBufPtr+1) = 0;
2304 pTxBlk->MpduHeaderLen += 2;
2308 // padding at front of LLC header
2309 // LLC header should locate at 4-octets aligment
2311 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2312 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2313 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2318 // Insert LLC-SNAP encapsulation - 8 octets
2321 // if original Ethernet frame contains no LLC/SNAP,
2322 // then an extra LLC/SNAP encap is required
2324 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2325 if (pTxBlk->pExtraLlcSnapEncap)
2329 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2332 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2333 // get 2 octets (TypeofLen)
2334 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2336 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2340 // If TKIP is used and fragmentation is required. Driver has to
2341 // append TKIP MIC at tail of the scatter buffer
2342 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2343 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2346 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2347 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2348 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2349 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2350 pTxBlk->SrcBufLen += 8;
2351 pTxBlk->TotalFrameLen += 8;
2352 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2356 // calcuate the overhead bytes that encryption algorithm may add. This
2357 // affects the calculate of "duration" field
2359 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2360 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2361 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2362 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2363 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2364 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2365 else if (pTxBlk->CipherAlg == CIPHER_AES)
2366 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2368 EncryptionOverhead = 0;
2370 // decide how much time an ACK/CTS frame will consume in the air
2371 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2373 // Init the total payload length of this frame.
2374 SrcRemainingBytes = pTxBlk->SrcBufLen;
2376 pTxBlk->TotalFragNum = 0xff;
2380 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2382 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2384 if (SrcRemainingBytes <= FreeMpduSize)
2385 { // this is the last or only fragment
2387 pTxBlk->SrcBufLen = SrcRemainingBytes;
2389 pHeader_802_11->FC.MoreFrag = 0;
2390 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2392 // Indicate the lower layer that this's the last fragment.
2393 pTxBlk->TotalFragNum = fragNum;
2396 { // more fragment is required
2398 pTxBlk->SrcBufLen = FreeMpduSize;
2400 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2401 pHeader_802_11->FC.MoreFrag = 1;
2402 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2406 pTxBlk->FrameGap = IFS_HTTXOP;
2408 pTxBlk->FrameGap = IFS_SIFS;
2410 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2412 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2414 pAd->RalinkCounters.KickTxCount++;
2415 pAd->RalinkCounters.OneSecTxDoneCount++;
2417 // Update the frame number, remaining size of the NDIS packet payload.
2419 // space for 802.11 header.
2420 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2421 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2424 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2425 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2427 pHeader_802_11->Frag++; // increase Frag #
2429 }while(SrcRemainingBytes > 0);
2434 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2438 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2439 while(_pTxBlk->TxPacketList.Head) \
2441 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2442 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2447 ========================================================================
2449 Routine Description:
2450 Copy frame from waiting queue into relative ring buffer and set
2451 appropriate ASIC register to kick hardware encryption before really
2455 pAd Pointer to our adapter
2456 PNDIS_PACKET Pointer to outgoing Ndis frame
2457 NumberOfFrag Number of fragment required
2462 IRQL = DISPATCH_LEVEL
2466 ========================================================================
2468 NDIS_STATUS STAHardTransmit(
2469 IN PRTMP_ADAPTER pAd,
2473 NDIS_PACKET *pPacket;
2474 PQUEUE_ENTRY pQEntry;
2476 // ---------------------------------------------
2477 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2478 // ---------------------------------------------
2480 ASSERT(pTxBlk->TxPacketList.Number);
2481 if (pTxBlk->TxPacketList.Head == NULL)
2483 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2484 return NDIS_STATUS_FAILURE;
2487 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2489 #if 0 //def CARRIER_DETECTION_SUPPORT // Roger sync Carrier
2490 if ((pAd->CommonCfg.CarrierDetect.Enable == TRUE) && (isCarrierDetectExist(pAd) == TRUE))
2492 DBGPRINT(RT_DEBUG_INFO,("STAHardTransmit --> radar detect not in normal mode !!!\n"));
2493 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2494 return (NDIS_STATUS_FAILURE);
2496 #endif // CARRIER_DETECTION_SUPPORT //
2498 // ------------------------------------------------------------------
2499 // STEP 1. WAKE UP PHY
2500 // outgoing frame always wakeup PHY to prevent frame lost and
2501 // turn off PSM bit to improve performance
2502 // ------------------------------------------------------------------
2503 // not to change PSM bit, just send this frame out?
2504 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2506 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2507 AsicForceWakeup(pAd, TRUE);
2510 // It should not change PSM bit, when APSD turn on.
2511 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2512 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2513 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2515 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2516 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2517 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2520 switch (pTxBlk->TxFrameType)
2522 #ifdef DOT11_N_SUPPORT
2523 case TX_AMPDU_FRAME:
2524 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2526 case TX_AMSDU_FRAME:
2527 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2529 #endif // DOT11_N_SUPPORT //
2530 case TX_LEGACY_FRAME:
2531 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2533 case TX_MCAST_FRAME:
2534 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2536 case TX_RALINK_FRAME:
2537 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2540 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2544 // It should not happened!
2545 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2546 while(pTxBlk->TxPacketList.Number)
2548 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2549 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2551 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2557 return (NDIS_STATUS_SUCCESS);
2561 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2563 unsigned char *word = value;
2564 unsigned int ret = 0;
2567 for(i=0; i < len; i++)
2570 ret ^=(unsigned int) (word[i]) << mod;
2571 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2576 VOID Sta_Announce_or_Forward_802_3_Packet(
2577 IN PRTMP_ADAPTER pAd,
2578 IN PNDIS_PACKET pPacket,
2579 IN UCHAR FromWhichBSSID)
2584 announce_802_3_packet(pAd, pPacket);
2589 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);