2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
35 -------- ---------- ----------------------------------------------
36 John Aug/17/04 major modification for RT2561/2661
37 Jan Lee Mar/17/06 major modification for RT2860 New Ring Design
39 #include "../rt_config.h"
43 VOID STARxEAPOLFrameIndicate(
45 IN MAC_TABLE_ENTRY *pEntry,
47 IN UCHAR FromWhichBSSID)
49 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
50 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
53 #ifdef WPA_SUPPLICANT_SUPPORT
54 if (pAd->StaCfg.WpaSupplicantUP)
56 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
57 // TBD : process fragmented EAPol frames
59 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
60 if ( pAd->StaCfg.IEEE8021X == TRUE &&
61 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
67 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
68 STA_PORT_SECURED(pAd);
70 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
72 idx = pAd->StaCfg.DesireSharedKeyId;
73 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
74 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
76 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
79 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
81 // Set key material and cipherAlg to Asic
82 AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
84 // Assign group key info
85 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
87 // Assign pairwise key info
88 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
90 pAd->IndicateMediaState = NdisMediaStateConnected;
91 pAd->ExtraInfo = GENERAL_LINK_UP;
93 // For Preventing ShardKey Table is cleared by remove key procedure.
94 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
95 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
96 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
97 pAd->StaCfg.DesireSharedKey[idx].Key,
98 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
103 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
108 #endif // WPA_SUPPLICANT_SUPPORT //
110 // Special DATA frame that has to pass to MLME
111 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
112 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
114 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
115 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
116 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
117 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
121 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
126 VOID STARxDataFrameAnnounce(
127 IN PRTMP_ADAPTER pAd,
128 IN MAC_TABLE_ENTRY *pEntry,
130 IN UCHAR FromWhichBSSID)
134 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
137 // drop all non-EAP DATA frame before
138 // this client's Port-Access-Control is secured
139 if (pRxBlk->pHeader->FC.Wep)
141 // unsupported cipher suite
142 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
145 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
151 // encryption in-use but receive a non-EAPOL clear text frame, drop it
152 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
153 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
156 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
161 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
162 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
164 // Normal legacy, AMPDU or AMSDU
165 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
171 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
173 #ifdef QOS_DLS_SUPPORT
174 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS);
175 #endif // QOS_DLS_SUPPORT //
179 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
180 #ifdef DOT11_N_SUPPORT
181 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
183 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
186 #endif // DOT11_N_SUPPORT //
188 // Determin the destination of the EAP frame
189 // to WPA state machine or upper layer
190 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
196 // For TKIP frame, calculate the MIC value
197 BOOLEAN STACheckTkipMICValue(
198 IN PRTMP_ADAPTER pAd,
199 IN MAC_TABLE_ENTRY *pEntry,
202 PHEADER_802_11 pHeader = pRxBlk->pHeader;
203 UCHAR *pData = pRxBlk->pData;
204 USHORT DataSize = pRxBlk->DataSize;
205 UCHAR UserPriority = pRxBlk->UserPriority;
209 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
211 pDA = pHeader->Addr1;
212 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
214 pSA = pHeader->Addr3;
218 pSA = pHeader->Addr2;
221 if (RTMPTkipCompareMICValue(pAd,
229 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
231 #ifdef WPA_SUPPLICANT_SUPPORT
232 if (pAd->StaCfg.WpaSupplicantUP)
234 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
237 #endif // WPA_SUPPLICANT_SUPPORT //
239 RTMPReportMicError(pAd, pWpaKey);
243 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
252 // All Rx routines use RX_BLK structure to hande rx events
253 // It is very important to build pRxBlk attributes
254 // 1. pHeader pointer to 802.11 Header
255 // 2. pData pointer to payload including LLC (just skip Header)
256 // 3. set payload size including LLC to DataSize
257 // 4. set some flags with RX_BLK_SET_FLAG()
259 VOID STAHandleRxDataFrame(
260 IN PRTMP_ADAPTER pAd,
263 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
264 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
265 PHEADER_802_11 pHeader = pRxBlk->pHeader;
266 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
267 BOOLEAN bFragment = FALSE;
268 MAC_TABLE_ENTRY *pEntry = NULL;
269 UCHAR FromWhichBSSID = BSS0;
270 UCHAR UserPriority = 0;
273 // before LINK UP, all DATA frames are rejected
274 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
277 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
281 #ifdef QOS_DLS_SUPPORT
282 //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
283 if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD))
287 #endif // QOS_DLS_SUPPORT //
289 // Drop not my BSS frames
290 if (pRxD->MyBss == 0)
294 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
299 pAd->RalinkCounters.RxCountSinceLastNULL++;
300 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
303 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
306 pData = (PUCHAR)pHeader + LENGTH_802_11;
307 if ((*pData >> 4) & 0x01)
309 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
310 pAd->CommonCfg.bInServicePeriod = FALSE;
312 // Force driver to fall into sleep mode when rcv EOSP frame
313 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
315 USHORT TbttNumToNextWakeUp;
316 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
319 NdisGetSystemUpTime(&Now);
320 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
322 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
323 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
324 TbttNumToNextWakeUp = NextDtim;
326 MlmeSetPsmBit(pAd, PWR_SAVE);
327 // if WMM-APSD is failed, try to disable following line
328 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
332 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
334 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
338 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
339 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
342 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
346 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
347 #ifdef QOS_DLS_SUPPORT
348 if (!pAd->CommonCfg.bDLSCapable)
350 #endif // QOS_DLS_SUPPORT //
353 // Infrastructure mode, check address 2 for BSSID
354 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
356 // Receive frame not my BSSID
358 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
362 else // Ad-Hoc mode or Not associated
364 // Ad-Hoc mode, check address 3 for BSSID
365 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
367 // Receive frame not my BSSID
369 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
373 #ifdef QOS_DLS_SUPPORT
375 #endif // QOS_DLS_SUPPORT //
380 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
382 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
386 // 1. release packet if infra mode
387 // 2. new a pEntry if ad-hoc mode
388 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
395 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
396 #ifdef QOS_DLS_SUPPORT
397 if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
398 RX_BLK_SET_FLAG(pRxBlk, fRX_DLS);
400 #endif // QOS_DLS_SUPPORT //
401 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
404 // check Atheros Client
405 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
407 pEntry->bIAmBadAtheros = TRUE;
408 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
409 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
410 if (!STA_AES_ON(pAd))
412 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
417 pRxBlk->pData = (UCHAR *)pHeader;
420 // update RxBlk->pData, DataSize
421 // 802.11 Header, QOS, HTC, Hw Padding
424 // 1. skip 802.11 HEADER
426 pRxBlk->pData += LENGTH_802_11;
427 pRxBlk->DataSize -= LENGTH_802_11;
431 if (pHeader->FC.SubType & 0x08)
433 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
434 UserPriority = *(pRxBlk->pData) & 0x0f;
435 // bit 7 in QoS Control field signals the HT A-MSDU format
436 if ((*pRxBlk->pData) & 0x80)
438 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
441 // skip QOS contorl field
443 pRxBlk->DataSize -=2;
445 pRxBlk->UserPriority = UserPriority;
447 // 3. Order bit: A-Ralink or HTC+
448 if (pHeader->FC.Order)
450 #ifdef AGGREGATION_SUPPORT
451 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
453 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
458 #ifdef DOT11_N_SUPPORT
459 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
460 // skip HTC contorl field
462 pRxBlk->DataSize -= 4;
463 #endif // DOT11_N_SUPPORT //
467 // 4. skip HW padding
470 // just move pData pointer
471 // because DataSize excluding HW padding
472 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
476 #ifdef DOT11_N_SUPPORT
479 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
481 #endif // DOT11_N_SUPPORT //
485 // Case I Process Broadcast & Multicast data frame
487 if (pRxD->Bcast || pRxD->Mcast)
489 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
491 // Drop Mcast/Bcast frame with fragment bit on
492 if (pHeader->FC.MoreFrag)
495 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
499 // Filter out Bcast frame which AP relayed for us
500 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
503 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
507 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
512 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
515 #ifdef QOS_DLS_SUPPORT
516 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS))
518 MAC_TABLE_ENTRY *pDlsEntry = NULL;
520 pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE);
522 Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI);
525 #endif // QOS_DLS_SUPPORT //
528 pEntry = MacTableLookup(pAd, pHeader->Addr2);
530 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
534 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
536 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
537 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
539 pAd->RalinkCounters.OneSecRxOkDataCnt++;
542 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
544 // re-assemble the fragmented packets
545 // return complete frame (pRxPacket) or NULL
547 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
552 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
554 // process complete frame
555 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
558 pRxBlk->DataSize -= 8;
560 // For TKIP frame, calculate the MIC value
561 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
567 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
573 // because RTMPDeFragmentDataFrame() will release rx packet,
574 // if packet is fragmented
581 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
584 VOID STAHandleRxMgmtFrame(
585 IN PRTMP_ADAPTER pAd,
588 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
589 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
590 PHEADER_802_11 pHeader = pRxBlk->pHeader;
591 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
596 // We should collect RSSI not only U2M data but also my beacon
597 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
599 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
601 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
602 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
605 // First check the size, it MUST not exceed the mlme queue size
606 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
608 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
612 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
613 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
616 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
619 VOID STAHandleRxControlFrame(
620 IN PRTMP_ADAPTER pAd,
623 #ifdef DOT11_N_SUPPORT
624 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
625 #endif // DOT11_N_SUPPORT //
626 PHEADER_802_11 pHeader = pRxBlk->pHeader;
627 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
629 switch (pHeader->FC.SubType)
631 case SUBTYPE_BLOCK_ACK_REQ:
632 #ifdef DOT11_N_SUPPORT
634 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
637 #endif // DOT11_N_SUPPORT //
638 case SUBTYPE_BLOCK_ACK:
644 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
649 ========================================================================
652 Process RxDone interrupt, running in DPC level
655 pAd Pointer to our adapter
660 IRQL = DISPATCH_LEVEL
663 This routine has to maintain Rx ring read pointer.
664 Need to consider QOS DATA format when converting to 802.3
665 ========================================================================
667 BOOLEAN STARxDoneInterruptHandle(
668 IN PRTMP_ADAPTER pAd,
672 UINT32 RxProcessed, RxPending;
673 BOOLEAN bReschedule = FALSE;
674 RT28XX_RXD_STRUC *pRxD;
677 PNDIS_PACKET pRxPacket;
678 PHEADER_802_11 pHeader;
681 RxProcessed = RxPending = 0;
683 // process whole rx ring
687 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
688 fRTMP_ADAPTER_RESET_IN_PROGRESS |
689 fRTMP_ADAPTER_HALT_IN_PROGRESS |
690 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
691 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
697 if (RxProcessed++ > MAX_RX_PROCESS_CNT)
699 // need to reschedule rx handle
705 RxProcessed ++; // test
707 // 1. allocate a new data packet into rx ring to replace received packet
708 // then processing the received packet
709 // 2. the callee must take charge of release of packet
710 // 3. As far as driver is concerned ,
711 // the rx packet must
712 // a. be indicated to upper layer or
713 // b. be released if it is discarded
714 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
715 if (pRxPacket == NULL)
717 // no more packet to process
721 // get rx ring descriptor
722 pRxD = &(RxCell.RxD);
723 // get rx data buffer
724 pData = GET_OS_PKT_DATAPTR(pRxPacket);
725 pRxWI = (PRXWI_STRUC) pData;
726 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
729 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE);
730 RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI);
734 RxCell.pRxWI = pRxWI;
735 RxCell.pHeader = pHeader;
736 RxCell.pRxPacket = pRxPacket;
737 RxCell.pData = (UCHAR *) pHeader;
738 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
741 // Increase Total receive byte counter after real data received no mater any error or not
742 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
743 pAd->RalinkCounters.RxCount ++;
745 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
747 if (pRxWI->MPDUtotalByteCount < 14)
748 Status = NDIS_STATUS_FAILURE;
752 send_monitor_packets(pAd, &RxCell);
755 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
759 pAd->ate.RxCntPerSec++;
760 ATESampleRssi(pAd, pRxWI);
761 #ifdef RALINK_28xx_QA
762 if (pAd->ate.bQARxStart == TRUE)
764 /* (*pRxD) has been swapped in GetPacketFromRxRing() */
765 ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader);
767 #endif // RALINK_28xx_QA //
768 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
771 #endif // RALINK_ATE //
773 // Check for all RxD errors
774 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
776 // Handle the received frame
777 if (Status == NDIS_STATUS_SUCCESS)
779 switch (pHeader->FC.Type)
781 // CASE I, receive a DATA frame
784 // process DATA frame
785 STAHandleRxDataFrame(pAd, &RxCell);
788 // CASE II, receive a MGMT frame
791 STAHandleRxMgmtFrame(pAd, &RxCell);
794 // CASE III. receive a CNTL frame
797 STAHandleRxControlFrame(pAd, &RxCell);
800 // discard other type
802 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
808 pAd->Counters8023.RxErrors++;
809 // discard this frame
810 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
818 ========================================================================
822 pAd Pointer to our adapter
824 IRQL = DISPATCH_LEVEL
826 ========================================================================
828 VOID RTMPHandleTwakeupInterrupt(
829 IN PRTMP_ADAPTER pAd)
831 AsicForceWakeup(pAd, FALSE);
835 ========================================================================
837 Early checking and OS-depened parsing for Tx packet send to our STA driver.
840 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
841 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
842 UINT NumberOfPackets Number of packet in packet array.
848 This function do early checking and classification for send-out packet.
849 You only can put OS-depened & STA related code in here.
850 ========================================================================
853 IN NDIS_HANDLE MiniportAdapterContext,
854 IN PPNDIS_PACKET ppPacketArray,
855 IN UINT NumberOfPackets)
858 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
859 PNDIS_PACKET pPacket;
860 BOOLEAN allowToSend = FALSE;
863 for (Index = 0; Index < NumberOfPackets; Index++)
865 pPacket = ppPacketArray[Index];
869 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
870 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
871 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
873 // Drop send request since hardware is in reset state
876 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
878 // Drop send request since there are no physical connection yet
883 // Record that orignal packet source is from NDIS layer,so that
884 // later on driver knows how to release this NDIS PACKET
885 #ifdef QOS_DLS_SUPPORT
886 MAC_TABLE_ENTRY *pEntry;
887 PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
889 pEntry = MacTableLookup(pAd, pSrcBufVA);
890 if (pEntry && (pEntry->ValidAsDls == TRUE))
892 RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
895 #endif // QOS_DLS_SUPPORT //
896 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
897 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
898 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
899 pAd->RalinkCounters.PendingNdisPacketCount++;
905 if (allowToSend == TRUE)
906 STASendPacket(pAd, pPacket);
908 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
911 // Dequeue outgoing frames from TxSwQueue[] and process it
912 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
918 ========================================================================
920 This routine is used to do packet parsing and classification for Tx packet
921 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
925 pAd Pointer to our adapter
926 pPacket Pointer to send packet
929 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
930 NDIS_STATUS_FAILURE If failed to do en-queue.
933 You only can put OS-indepened & STA related code in here.
934 ========================================================================
936 NDIS_STATUS STASendPacket(
937 IN PRTMP_ADAPTER pAd,
938 IN PNDIS_PACKET pPacket)
940 PACKET_INFO PacketInfo;
945 UCHAR QueIdx, UserPriority;
946 MAC_TABLE_ENTRY *pEntry = NULL;
947 unsigned int IrqFlags;
951 // Prepare packet information structure for buffer descriptor
952 // chained within a single NDIS packet.
953 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
955 if (pSrcBufVA == NULL)
957 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
958 // Resourece is low, system did not allocate virtual address
959 // return NDIS_STATUS_FAILURE directly to upper layer
960 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
961 return NDIS_STATUS_FAILURE;
967 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
968 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
969 return (NDIS_STATUS_FAILURE);
972 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
973 // Note multicast packets in adhoc also use BSSID_WCID index.
977 #ifdef QOS_DLS_SUPPORT
980 tmpWcid = RTMP_GET_PACKET_WCID(pPacket);
981 if (VALID_WCID(tmpWcid) &&
982 (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE))
984 pEntry = &pAd->MacTab.Content[tmpWcid];
985 Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate;
988 #endif // QOS_DLS_SUPPORT //
990 pEntry = &pAd->MacTab.Content[BSSID_WCID];
991 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
992 Rate = pAd->CommonCfg.TxRate;
995 else if (ADHOC_ON(pAd))
997 if (*pSrcBufVA & 0x01)
999 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
1000 pEntry = &pAd->MacTab.Content[MCAST_WCID];
1004 pEntry = MacTableLookup(pAd, pSrcBufVA);
1006 Rate = pAd->CommonCfg.TxRate;
1012 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
1013 // Resourece is low, system did not allocate virtual address
1014 // return NDIS_STATUS_FAILURE directly to upper layer
1015 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1016 return NDIS_STATUS_FAILURE;
1022 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
1026 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
1027 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
1028 RTMPCheckEtherType(pAd, pPacket);
1033 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
1035 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1036 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1037 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1038 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1039 #ifdef WPA_SUPPLICANT_SUPPORT
1040 || (pAd->StaCfg.IEEE8021X == TRUE)
1041 #endif // WPA_SUPPLICANT_SUPPORT //
1043 || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
1044 #endif // LEAP_SUPPORT //
1046 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1047 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1050 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1051 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1053 return (NDIS_STATUS_FAILURE);
1057 // STEP 1. Decide number of fragments required to deliver this MSDU.
1058 // The estimation here is not very accurate because difficult to
1059 // take encryption overhead into consideration here. The result
1060 // "NumberOfFrag" is then just used to pre-check if enough free
1061 // TXD are available to hold this MSDU.
1064 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1066 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1067 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1068 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1069 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1070 #ifdef DOT11_N_SUPPORT
1071 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1072 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1073 #endif // DOT11_N_SUPPORT //
1076 // The calculated "NumberOfFrag" is a rough estimation because of various
1077 // encryption/encapsulation overhead not taken into consideration. This number is just
1078 // used to make sure enough free TXD are available before fragmentation takes place.
1079 // In case the actual required number of fragments of an NDIS packet
1080 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1081 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1082 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1083 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1085 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1086 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1087 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1088 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1094 // Save fragment number to Ndis packet reserved field
1095 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1098 // STEP 2. Check the requirement of RTS:
1099 // If multiple fragment required, RTS is required only for the first fragment
1100 // if the fragment size large than RTS threshold
1101 // For RT28xx, Let ASIC send RTS/CTS
1102 RTMP_SET_PACKET_RTS(pPacket, 0);
1103 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1106 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1110 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1113 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1116 // get Ethernet protocol field
1117 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1118 if (Protocol <= 1500)
1120 // get Ethernet protocol field from LLC/SNAP
1121 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1124 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1128 // always AC_BE for non-IP packet
1129 if (Protocol != 0x0800)
1133 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1136 // return AC_BE if packet is not IPv4
1137 if ((Byte0 & 0xf0) != 0x40)
1141 UserPriority = (Byte1 & 0xe0) >> 5;
1142 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1144 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1145 // TODO: downgrade UP & QueIdx before passing ACM
1146 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1154 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1158 // Make sure SendTxWait queue resource won't be used by other threads
1159 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1160 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1162 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1164 StopNetIfQueue(pAd, QueIdx, pPacket);
1165 #endif // BLOCK_NET_IF //
1166 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1168 return NDIS_STATUS_FAILURE;
1172 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1174 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1176 #ifdef DOT11_N_SUPPORT
1177 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1178 (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1180 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1181 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1182 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1183 // For IOT compatibility, if
1184 // 1. It is Ralink chip or
1185 // 2. It is OPEN or AES mode,
1186 // then BA session can be bulit.
1187 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1188 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1191 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1194 #endif // DOT11_N_SUPPORT //
1196 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1197 return NDIS_STATUS_SUCCESS;
1202 ========================================================================
1204 Routine Description:
1205 This subroutine will scan through releative ring descriptor to find
1206 out avaliable free ring descriptor and compare with request size.
1209 pAd Pointer to our adapter
1210 QueIdx Selected TX Ring
1213 NDIS_STATUS_FAILURE Not enough free descriptor
1214 NDIS_STATUS_SUCCESS Enough free descriptor
1216 IRQL = PASSIVE_LEVEL
1217 IRQL = DISPATCH_LEVEL
1221 ========================================================================
1224 NDIS_STATUS RTMPFreeTXDRequest(
1225 IN PRTMP_ADAPTER pAd,
1227 IN UCHAR NumberRequired,
1228 IN PUCHAR FreeNumberIs)
1230 ULONG FreeNumber = 0;
1231 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1240 if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1241 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1243 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1245 if (FreeNumber >= NumberRequired)
1246 Status = NDIS_STATUS_SUCCESS;
1250 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1251 FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1253 FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1255 if (FreeNumber >= NumberRequired)
1256 Status = NDIS_STATUS_SUCCESS;
1260 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1263 *FreeNumberIs = (UCHAR)FreeNumber;
1271 VOID RTMPSendDisassociationFrame(
1272 IN PRTMP_ADAPTER pAd)
1276 VOID RTMPSendNullFrame(
1277 IN PRTMP_ADAPTER pAd,
1279 IN BOOLEAN bQosNull)
1281 UCHAR NullFrame[48];
1283 PHEADER_802_11 pHeader_802_11;
1291 #endif // RALINK_ATE //
1293 // WPA 802.1x secured port control
1294 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1295 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1296 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1297 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1298 #ifdef WPA_SUPPLICANT_SUPPORT
1299 || (pAd->StaCfg.IEEE8021X == TRUE)
1302 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1307 NdisZeroMemory(NullFrame, 48);
1308 Length = sizeof(HEADER_802_11);
1310 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1312 pHeader_802_11->FC.Type = BTYPE_DATA;
1313 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1314 pHeader_802_11->FC.ToDs = 1;
1315 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1316 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1317 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1319 if (pAd->CommonCfg.bAPSDForcePowerSave)
1321 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1325 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1327 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1330 pHeader_802_11->Sequence = pAd->Sequence;
1332 // Prepare QosNull function frame
1335 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1337 // copy QOS control bytes
1338 NullFrame[Length] = 0;
1339 NullFrame[Length+1] = 0;
1340 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1343 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1347 // IRQL = DISPATCH_LEVEL
1348 VOID RTMPSendRTSFrame(
1349 IN PRTMP_ADAPTER pAd,
1351 IN unsigned int NextMpduSize,
1354 IN USHORT AckDuration,
1362 // --------------------------------------------------------
1363 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1364 // Find the WPA key, either Group or Pairwise Key
1365 // LEAP + TKIP also use WPA key.
1366 // --------------------------------------------------------
1367 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1368 // In Cisco CCX 2.0 Leap Authentication
1369 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1370 // Instead of the SharedKey, SharedKey Length may be Zero.
1371 VOID STAFindCipherAlgorithm(
1372 IN PRTMP_ADAPTER pAd,
1375 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1376 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1377 UCHAR KeyIdx = 0xff;
1379 PCIPHER_KEY pKey = NULL;
1381 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1385 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1386 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1388 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1390 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1392 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1394 // 4-way handshaking frame must be clear
1395 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1396 (pAd->SharedKey[BSS0][0].KeyLen))
1398 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1402 else if (Cipher == Ndis802_11Encryption1Enabled)
1405 if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1407 if (LEAP_CCKM_ON(pAd))
1409 if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1415 KeyIdx = pAd->StaCfg.DefaultKeyId;
1417 else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1418 KeyIdx = pAd->StaCfg.DefaultKeyId;
1419 else if (LEAP_CCKM_ON(pAd))
1421 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1426 else // standard WEP64 or WEP128
1427 #endif // LEAP_SUPPORT //
1428 KeyIdx = pAd->StaCfg.DefaultKeyId;
1430 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1431 (Cipher == Ndis802_11Encryption3Enabled))
1433 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1434 KeyIdx = pAd->StaCfg.DefaultKeyId;
1435 else if (pAd->SharedKey[BSS0][0].KeyLen)
1438 KeyIdx = pAd->StaCfg.DefaultKeyId;
1442 CipherAlg = CIPHER_NONE;
1443 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1444 CipherAlg = CIPHER_NONE;
1445 #ifdef WPA_SUPPLICANT_SUPPORT
1446 else if ( pAd->StaCfg.WpaSupplicantUP &&
1447 (Cipher == Ndis802_11Encryption1Enabled) &&
1448 (pAd->StaCfg.IEEE8021X == TRUE) &&
1449 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1450 CipherAlg = CIPHER_NONE;
1451 #endif // WPA_SUPPLICANT_SUPPORT //
1454 //Header_802_11.FC.Wep = 1;
1455 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1456 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1460 pTxBlk->CipherAlg = CipherAlg;
1461 pTxBlk->pKey = pKey;
1465 VOID STABuildCommon802_11Header(
1466 IN PRTMP_ADAPTER pAd,
1470 HEADER_802_11 *pHeader_802_11;
1471 #ifdef QOS_DLS_SUPPORT
1472 BOOLEAN bDLSFrame = FALSE;
1473 INT DlsEntryIndex = 0;
1474 #endif // QOS_DLS_SUPPORT //
1477 // MAKE A COMMON 802.11 HEADER
1480 // normal wlan header size : 24 octets
1481 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1483 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1485 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1487 pHeader_802_11->FC.FrDs = 0;
1488 pHeader_802_11->FC.Type = BTYPE_DATA;
1489 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1491 #ifdef QOS_DLS_SUPPORT
1494 // Check if the frame can be sent through DLS direct link interface
1495 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1496 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1497 if (DlsEntryIndex >= 0)
1502 #endif // QOS_DLS_SUPPORT //
1504 if (pTxBlk->pMacEntry)
1506 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1508 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1509 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1513 #ifdef QOS_DLS_SUPPORT
1516 pHeader_802_11->Sequence = pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence;
1517 pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence = (pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence+1) & MAXSEQ;
1520 #endif // QOS_DLS_SUPPORT //
1522 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1523 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1529 pHeader_802_11->Sequence = pAd->Sequence;
1530 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1533 pHeader_802_11->Frag = 0;
1535 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1540 #ifdef QOS_DLS_SUPPORT
1543 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1544 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1545 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1546 pHeader_802_11->FC.ToDs = 0;
1549 #endif // QOS_DLS_SUPPORT //
1551 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1552 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1553 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1554 pHeader_802_11->FC.ToDs = 1;
1557 else if (ADHOC_ON(pAd))
1559 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1560 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1561 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1562 pHeader_802_11->FC.ToDs = 0;
1566 if (pTxBlk->CipherAlg != CIPHER_NONE)
1567 pHeader_802_11->FC.Wep = 1;
1569 // -----------------------------------------------------------------
1570 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1571 // -----------------------------------------------------------------
1572 if (pAd->CommonCfg.bAPSDForcePowerSave)
1573 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1575 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1578 #ifdef DOT11_N_SUPPORT
1579 VOID STABuildCache802_11Header(
1580 IN RTMP_ADAPTER *pAd,
1584 MAC_TABLE_ENTRY *pMacEntry;
1585 PHEADER_802_11 pHeader80211;
1587 pHeader80211 = (PHEADER_802_11)pHeader;
1588 pMacEntry = pTxBlk->pMacEntry;
1591 // Update the cached 802.11 HEADER
1594 // normal wlan header size : 24 octets
1595 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1598 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1601 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1602 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1605 // Check if the frame can be sent through DLS direct link interface
1606 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1607 #ifdef QOS_DLS_SUPPORT
1608 BOOLEAN bDLSFrame = FALSE;
1609 INT DlsEntryIndex = 0;
1611 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1612 if (DlsEntryIndex >= 0)
1616 #endif // QOS_DLS_SUPPORT //
1618 // The addr3 of normal packet send from DS is Dest Mac address.
1619 #ifdef QOS_DLS_SUPPORT
1622 COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
1623 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1624 pHeader80211->FC.ToDs = 0;
1627 #endif // QOS_DLS_SUPPORT //
1629 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1631 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1634 // -----------------------------------------------------------------
1635 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1636 // -----------------------------------------------------------------
1637 if (pAd->CommonCfg.bAPSDForcePowerSave)
1638 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1640 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1642 #endif // DOT11_N_SUPPORT //
1644 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1645 IN RTMP_ADAPTER *pAd,
1648 PUCHAR pHeaderBufPtr;
1649 HEADER_802_11 *pHeader_802_11;
1650 PNDIS_PACKET pNextPacket;
1652 PQUEUE_ENTRY pQEntry;
1654 STAFindCipherAlgorithm(pAd, pTxBlk);
1655 STABuildCommon802_11Header(pAd, pTxBlk);
1658 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1659 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1661 // steal "order" bit to mark "aggregation"
1662 pHeader_802_11->FC.Order = 1;
1664 // skip common header
1665 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1667 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1670 // build QOS Control bytes
1672 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1674 *(pHeaderBufPtr+1) = 0;
1676 pTxBlk->MpduHeaderLen += 2;
1679 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1680 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1681 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1682 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1684 // For RA Aggregation,
1685 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1686 pQEntry = pTxBlk->TxPacketList.Head;
1687 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1688 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1689 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1690 nextBufLen -= LENGTH_802_1Q;
1692 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1693 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1696 pTxBlk->MpduHeaderLen += 2;
1698 return pHeaderBufPtr;
1702 #ifdef DOT11_N_SUPPORT
1703 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1704 IN RTMP_ADAPTER *pAd,
1707 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1708 HEADER_802_11 *pHeader_802_11;
1711 STAFindCipherAlgorithm(pAd, pTxBlk);
1712 STABuildCommon802_11Header(pAd, pTxBlk);
1714 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1715 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1717 // skip common header
1718 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1721 // build QOS Control bytes
1723 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1728 *pHeaderBufPtr |= 0x80;
1730 *(pHeaderBufPtr+1) = 0;
1732 pTxBlk->MpduHeaderLen += 2;
1734 //pSaveBufPtr = pHeaderBufPtr;
1737 // padding at front of LLC header
1738 // LLC header should locate at 4-octets aligment
1740 // @@@ MpduHeaderLen excluding padding @@@
1742 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1743 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1744 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1746 return pHeaderBufPtr;
1751 VOID STA_AMPDU_Frame_Tx(
1752 IN PRTMP_ADAPTER pAd,
1755 HEADER_802_11 *pHeader_802_11;
1756 PUCHAR pHeaderBufPtr;
1758 MAC_TABLE_ENTRY *pMacEntry;
1760 PQUEUE_ENTRY pQEntry;
1764 while(pTxBlk->TxPacketList.Head)
1766 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1767 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1768 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1770 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1774 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1776 pMacEntry = pTxBlk->pMacEntry;
1777 if (pMacEntry->isCached)
1779 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1780 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1781 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1782 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1786 STAFindCipherAlgorithm(pAd, pTxBlk);
1787 STABuildCommon802_11Header(pAd, pTxBlk);
1789 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1793 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1795 // skip common header
1796 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1799 // build QOS Control bytes
1801 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1802 *(pHeaderBufPtr+1) = 0;
1804 pTxBlk->MpduHeaderLen += 2;
1808 // HTC control filed following QoS field
1810 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1812 if (pMacEntry->isCached == FALSE)
1815 pHeader_802_11->FC.Order = 1;
1817 NdisZeroMemory(pHeaderBufPtr, 4);
1818 *(pHeaderBufPtr+3) |= 0x80;
1821 pTxBlk->MpduHeaderLen += 4;
1824 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1825 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1827 // skip 802.3 header
1828 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1829 pTxBlk->SrcBufLen -= LENGTH_802_3;
1834 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1835 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1839 // padding at front of LLC header
1840 // LLC header should locate at 4-octets aligment
1842 // @@@ MpduHeaderLen excluding padding @@@
1844 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1845 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1846 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1851 // Insert LLC-SNAP encapsulation - 8 octets
1853 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1854 if (pTxBlk->pExtraLlcSnapEncap)
1856 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1858 // get 2 octets (TypeofLen)
1859 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1861 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1866 if (pMacEntry->isCached)
1868 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1872 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1874 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1875 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1876 pMacEntry->isCached = TRUE;
1879 // calculate Transmitted AMPDU count and ByteCount
1881 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1882 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1885 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1887 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1892 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1894 pAd->RalinkCounters.KickTxCount++;
1895 pAd->RalinkCounters.OneSecTxDoneCount++;
1901 VOID STA_AMSDU_Frame_Tx(
1902 IN PRTMP_ADAPTER pAd,
1905 PUCHAR pHeaderBufPtr;
1907 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1908 USHORT totalMPDUSize=0;
1909 UCHAR *subFrameHeader;
1911 USHORT FirstTx = 0, LastTxIdx = 0;
1914 PQUEUE_ENTRY pQEntry;
1919 ASSERT((pTxBlk->TxPacketList.Number > 1));
1921 while(pTxBlk->TxPacketList.Head)
1923 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1924 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1925 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1927 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1931 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1933 // skip 802.3 header
1934 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1935 pTxBlk->SrcBufLen -= LENGTH_802_3;
1940 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1941 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1946 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1948 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1949 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1953 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1954 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1955 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1956 pHeaderBufPtr += padding;
1957 pTxBlk->MpduHeaderLen = padding;
1962 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1964 subFrameHeader = pHeaderBufPtr;
1965 subFramePayloadLen = pTxBlk->SrcBufLen;
1967 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1970 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1971 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1975 // Insert LLC-SNAP encapsulation - 8 octets
1977 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1979 subFramePayloadLen = pTxBlk->SrcBufLen;
1981 if (pTxBlk->pExtraLlcSnapEncap)
1983 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1985 // get 2 octets (TypeofLen)
1986 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1988 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1989 subFramePayloadLen += LENGTH_802_1_H;
1992 // update subFrame Length field
1993 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1994 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1996 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1999 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2001 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2005 pAd->RalinkCounters.KickTxCount++;
2006 pAd->RalinkCounters.OneSecTxDoneCount++;
2008 // calculate Transmitted AMSDU Count and ByteCount
2010 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
2011 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
2016 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2017 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2022 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2024 #endif // DOT11_N_SUPPORT //
2026 VOID STA_Legacy_Frame_Tx(
2027 IN PRTMP_ADAPTER pAd,
2030 HEADER_802_11 *pHeader_802_11;
2031 PUCHAR pHeaderBufPtr;
2034 PQUEUE_ENTRY pQEntry;
2039 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2040 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2041 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2043 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2047 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
2049 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
2052 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
2053 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
2055 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
2057 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2059 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
2060 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
2062 STAFindCipherAlgorithm(pAd, pTxBlk);
2063 STABuildCommon802_11Header(pAd, pTxBlk);
2066 // skip 802.3 header
2067 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2068 pTxBlk->SrcBufLen -= LENGTH_802_3;
2073 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2074 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2077 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2078 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
2080 // skip common header
2081 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2083 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2086 // build QOS Control bytes
2088 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2089 *(pHeaderBufPtr+1) = 0;
2091 pTxBlk->MpduHeaderLen += 2;
2094 // The remaining content of MPDU header should locate at 4-octets aligment
2095 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2096 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2097 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2102 // Insert LLC-SNAP encapsulation - 8 octets
2105 // if original Ethernet frame contains no LLC/SNAP,
2106 // then an extra LLC/SNAP encap is required
2108 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2109 if (pTxBlk->pExtraLlcSnapEncap)
2113 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2116 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2117 // get 2 octets (TypeofLen)
2118 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2120 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2127 // use Wcid as Key Index
2130 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2132 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2134 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2136 pAd->RalinkCounters.KickTxCount++;
2137 pAd->RalinkCounters.OneSecTxDoneCount++;
2142 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2146 VOID STA_ARalink_Frame_Tx(
2147 IN PRTMP_ADAPTER pAd,
2150 PUCHAR pHeaderBufPtr;
2152 USHORT totalMPDUSize=0;
2153 USHORT FirstTx, LastTxIdx;
2156 PQUEUE_ENTRY pQEntry;
2161 ASSERT((pTxBlk->TxPacketList.Number== 2));
2164 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2165 while(pTxBlk->TxPacketList.Head)
2167 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2168 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2170 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2172 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2176 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2178 // skip 802.3 header
2179 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2180 pTxBlk->SrcBufLen -= LENGTH_802_3;
2185 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2186 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2190 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2192 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2194 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2195 // will be updated after final frame was handled.
2196 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2200 // Insert LLC-SNAP encapsulation - 8 octets
2202 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2204 if (pTxBlk->pExtraLlcSnapEncap)
2206 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2208 // get 2 octets (TypeofLen)
2209 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2211 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2215 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2217 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2218 pTxBlk->MpduHeaderLen = 0;
2220 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2221 // DA(6)+SA(6)+FrameType(2)
2222 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2223 pHeaderBufPtr += 12;
2224 // get 2 octets (TypeofLen)
2225 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2227 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2230 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2232 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2234 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2236 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2240 pAd->RalinkCounters.OneSecTxAggregationCount++;
2241 pAd->RalinkCounters.KickTxCount++;
2242 pAd->RalinkCounters.OneSecTxDoneCount++;
2246 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2247 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2252 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2257 VOID STA_Fragment_Frame_Tx(
2258 IN RTMP_ADAPTER *pAd,
2261 HEADER_802_11 *pHeader_802_11;
2262 PUCHAR pHeaderBufPtr;
2265 PACKET_INFO PacketInfo;
2266 USHORT EncryptionOverhead = 0;
2267 UINT32 FreeMpduSize, SrcRemainingBytes;
2271 PQUEUE_ENTRY pQEntry;
2276 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2277 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2278 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2280 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2284 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2285 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2287 STAFindCipherAlgorithm(pAd, pTxBlk);
2288 STABuildCommon802_11Header(pAd, pTxBlk);
2290 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2292 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2293 if (pTxBlk->pPacket == NULL)
2295 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2298 // skip 802.3 header
2299 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2300 pTxBlk->SrcBufLen -= LENGTH_802_3;
2306 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2307 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2310 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2311 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2314 // skip common header
2315 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2317 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2320 // build QOS Control bytes
2322 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2324 *(pHeaderBufPtr+1) = 0;
2326 pTxBlk->MpduHeaderLen += 2;
2330 // padding at front of LLC header
2331 // LLC header should locate at 4-octets aligment
2333 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2334 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2335 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2340 // Insert LLC-SNAP encapsulation - 8 octets
2343 // if original Ethernet frame contains no LLC/SNAP,
2344 // then an extra LLC/SNAP encap is required
2346 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2347 if (pTxBlk->pExtraLlcSnapEncap)
2351 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2354 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2355 // get 2 octets (TypeofLen)
2356 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2358 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2362 // If TKIP is used and fragmentation is required. Driver has to
2363 // append TKIP MIC at tail of the scatter buffer
2364 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2365 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2368 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2369 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2370 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2371 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2372 pTxBlk->SrcBufLen += 8;
2373 pTxBlk->TotalFrameLen += 8;
2374 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2378 // calcuate the overhead bytes that encryption algorithm may add. This
2379 // affects the calculate of "duration" field
2381 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2382 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2383 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2384 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2385 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2386 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2387 else if (pTxBlk->CipherAlg == CIPHER_AES)
2388 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2390 EncryptionOverhead = 0;
2392 // decide how much time an ACK/CTS frame will consume in the air
2393 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2395 // Init the total payload length of this frame.
2396 SrcRemainingBytes = pTxBlk->SrcBufLen;
2398 pTxBlk->TotalFragNum = 0xff;
2402 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2404 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2406 if (SrcRemainingBytes <= FreeMpduSize)
2407 { // this is the last or only fragment
2409 pTxBlk->SrcBufLen = SrcRemainingBytes;
2411 pHeader_802_11->FC.MoreFrag = 0;
2412 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2414 // Indicate the lower layer that this's the last fragment.
2415 pTxBlk->TotalFragNum = fragNum;
2418 { // more fragment is required
2420 pTxBlk->SrcBufLen = FreeMpduSize;
2422 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2423 pHeader_802_11->FC.MoreFrag = 1;
2424 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2428 pTxBlk->FrameGap = IFS_HTTXOP;
2430 pTxBlk->FrameGap = IFS_SIFS;
2432 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2434 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2436 pAd->RalinkCounters.KickTxCount++;
2437 pAd->RalinkCounters.OneSecTxDoneCount++;
2439 // Update the frame number, remaining size of the NDIS packet payload.
2441 // space for 802.11 header.
2442 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2443 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2446 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2447 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2449 pHeader_802_11->Frag++; // increase Frag #
2451 }while(SrcRemainingBytes > 0);
2456 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2460 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2461 while(_pTxBlk->TxPacketList.Head) \
2463 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2464 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2469 ========================================================================
2471 Routine Description:
2472 Copy frame from waiting queue into relative ring buffer and set
2473 appropriate ASIC register to kick hardware encryption before really
2477 pAd Pointer to our adapter
2478 PNDIS_PACKET Pointer to outgoing Ndis frame
2479 NumberOfFrag Number of fragment required
2484 IRQL = DISPATCH_LEVEL
2488 ========================================================================
2490 NDIS_STATUS STAHardTransmit(
2491 IN PRTMP_ADAPTER pAd,
2495 NDIS_PACKET *pPacket;
2496 PQUEUE_ENTRY pQEntry;
2498 // ---------------------------------------------
2499 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2500 // ---------------------------------------------
2502 ASSERT(pTxBlk->TxPacketList.Number);
2503 if (pTxBlk->TxPacketList.Head == NULL)
2505 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2506 return NDIS_STATUS_FAILURE;
2509 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2511 #if 0 //def CARRIER_DETECTION_SUPPORT // Roger sync Carrier
2512 if ((pAd->CommonCfg.CarrierDetect.Enable == TRUE) && (isCarrierDetectExist(pAd) == TRUE))
2514 DBGPRINT(RT_DEBUG_INFO,("STAHardTransmit --> radar detect not in normal mode !!!\n"));
2515 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2516 return (NDIS_STATUS_FAILURE);
2518 #endif // CARRIER_DETECTION_SUPPORT //
2520 // ------------------------------------------------------------------
2521 // STEP 1. WAKE UP PHY
2522 // outgoing frame always wakeup PHY to prevent frame lost and
2523 // turn off PSM bit to improve performance
2524 // ------------------------------------------------------------------
2525 // not to change PSM bit, just send this frame out?
2526 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2528 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2529 AsicForceWakeup(pAd, TRUE);
2532 // It should not change PSM bit, when APSD turn on.
2533 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2534 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2535 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2537 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2538 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2539 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2542 switch (pTxBlk->TxFrameType)
2544 #ifdef DOT11_N_SUPPORT
2545 case TX_AMPDU_FRAME:
2546 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2548 case TX_AMSDU_FRAME:
2549 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2551 #endif // DOT11_N_SUPPORT //
2552 case TX_LEGACY_FRAME:
2553 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2555 case TX_MCAST_FRAME:
2556 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2558 case TX_RALINK_FRAME:
2559 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2562 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2566 // It should not happened!
2567 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2568 while(pTxBlk->TxPacketList.Number)
2570 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2571 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2573 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2579 return (NDIS_STATUS_SUCCESS);
2583 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2585 unsigned char *word = value;
2586 unsigned int ret = 0;
2589 for(i=0; i < len; i++)
2592 ret ^=(unsigned int) (word[i]) << mod;
2593 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2598 VOID Sta_Announce_or_Forward_802_3_Packet(
2599 IN PRTMP_ADAPTER pAd,
2600 IN PNDIS_PACKET pPacket,
2601 IN UCHAR FromWhichBSSID)
2606 announce_802_3_packet(pAd, pPacket);
2611 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);