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);
814 // fRTMP_PS_GO_TO_SLEEP_NOW is set if receiving beacon.
815 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW) && (INFRA_ON(pAd)))
817 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
818 AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp);
825 ========================================================================
829 pAd Pointer to our adapter
831 IRQL = DISPATCH_LEVEL
833 ========================================================================
835 VOID RTMPHandleTwakeupInterrupt(
836 IN PRTMP_ADAPTER pAd)
838 AsicForceWakeup(pAd, DOT11POWERSAVE);
842 ========================================================================
844 Early checking and OS-depened parsing for Tx packet send to our STA driver.
847 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
848 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
849 UINT NumberOfPackets Number of packet in packet array.
855 This function do early checking and classification for send-out packet.
856 You only can put OS-depened & STA related code in here.
857 ========================================================================
860 IN NDIS_HANDLE MiniportAdapterContext,
861 IN PPNDIS_PACKET ppPacketArray,
862 IN UINT NumberOfPackets)
865 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
866 PNDIS_PACKET pPacket;
867 BOOLEAN allowToSend = FALSE;
870 for (Index = 0; Index < NumberOfPackets; Index++)
872 pPacket = ppPacketArray[Index];
876 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
877 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
878 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
880 // Drop send request since hardware is in reset state
883 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
885 // Drop send request since there are no physical connection yet
890 // Record that orignal packet source is from NDIS layer,so that
891 // later on driver knows how to release this NDIS PACKET
892 #ifdef QOS_DLS_SUPPORT
893 MAC_TABLE_ENTRY *pEntry;
894 PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
896 pEntry = MacTableLookup(pAd, pSrcBufVA);
897 if (pEntry && (pEntry->ValidAsDls == TRUE))
899 RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
902 #endif // QOS_DLS_SUPPORT //
903 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
904 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
905 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
906 pAd->RalinkCounters.PendingNdisPacketCount++;
912 if (allowToSend == TRUE)
913 STASendPacket(pAd, pPacket);
915 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
918 // Dequeue outgoing frames from TxSwQueue[] and process it
919 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
925 ========================================================================
927 This routine is used to do packet parsing and classification for Tx packet
928 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
932 pAd Pointer to our adapter
933 pPacket Pointer to send packet
936 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
937 NDIS_STATUS_FAILURE If failed to do en-queue.
940 You only can put OS-indepened & STA related code in here.
941 ========================================================================
943 NDIS_STATUS STASendPacket(
944 IN PRTMP_ADAPTER pAd,
945 IN PNDIS_PACKET pPacket)
947 PACKET_INFO PacketInfo;
952 UCHAR QueIdx, UserPriority;
953 MAC_TABLE_ENTRY *pEntry = NULL;
954 unsigned int IrqFlags;
958 // Prepare packet information structure for buffer descriptor
959 // chained within a single NDIS packet.
960 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
962 if (pSrcBufVA == NULL)
964 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
965 // Resourece is low, system did not allocate virtual address
966 // return NDIS_STATUS_FAILURE directly to upper layer
967 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
968 return NDIS_STATUS_FAILURE;
974 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
975 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
976 return (NDIS_STATUS_FAILURE);
979 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
980 // Note multicast packets in adhoc also use BSSID_WCID index.
984 #ifdef QOS_DLS_SUPPORT
987 tmpWcid = RTMP_GET_PACKET_WCID(pPacket);
988 if (VALID_WCID(tmpWcid) &&
989 (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE))
991 pEntry = &pAd->MacTab.Content[tmpWcid];
992 Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate;
995 #endif // QOS_DLS_SUPPORT //
997 pEntry = &pAd->MacTab.Content[BSSID_WCID];
998 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
999 Rate = pAd->CommonCfg.TxRate;
1002 else if (ADHOC_ON(pAd))
1004 if (*pSrcBufVA & 0x01)
1006 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
1007 pEntry = &pAd->MacTab.Content[MCAST_WCID];
1011 pEntry = MacTableLookup(pAd, pSrcBufVA);
1013 Rate = pAd->CommonCfg.TxRate;
1019 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
1020 // Resourece is low, system did not allocate virtual address
1021 // return NDIS_STATUS_FAILURE directly to upper layer
1022 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1023 return NDIS_STATUS_FAILURE;
1029 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
1033 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
1034 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
1035 RTMPCheckEtherType(pAd, pPacket);
1040 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
1042 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1043 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1044 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1045 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1046 #ifdef WPA_SUPPLICANT_SUPPORT
1047 || (pAd->StaCfg.IEEE8021X == TRUE)
1048 #endif // WPA_SUPPLICANT_SUPPORT //
1050 || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
1051 #endif // LEAP_SUPPORT //
1053 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1054 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1057 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1058 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1060 return (NDIS_STATUS_FAILURE);
1064 // STEP 1. Decide number of fragments required to deliver this MSDU.
1065 // The estimation here is not very accurate because difficult to
1066 // take encryption overhead into consideration here. The result
1067 // "NumberOfFrag" is then just used to pre-check if enough free
1068 // TXD are available to hold this MSDU.
1071 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1073 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1074 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1075 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1076 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1077 #ifdef DOT11_N_SUPPORT
1078 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1079 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1080 #endif // DOT11_N_SUPPORT //
1083 // The calculated "NumberOfFrag" is a rough estimation because of various
1084 // encryption/encapsulation overhead not taken into consideration. This number is just
1085 // used to make sure enough free TXD are available before fragmentation takes place.
1086 // In case the actual required number of fragments of an NDIS packet
1087 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1088 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1089 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1090 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1092 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1093 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1094 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1095 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1101 // Save fragment number to Ndis packet reserved field
1102 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1105 // STEP 2. Check the requirement of RTS:
1106 // If multiple fragment required, RTS is required only for the first fragment
1107 // if the fragment size large than RTS threshold
1108 // For RT28xx, Let ASIC send RTS/CTS
1109 RTMP_SET_PACKET_RTS(pPacket, 0);
1110 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1113 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1117 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1120 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1123 // get Ethernet protocol field
1124 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1125 if (Protocol <= 1500)
1127 // get Ethernet protocol field from LLC/SNAP
1128 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1131 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1135 // always AC_BE for non-IP packet
1136 if (Protocol != 0x0800)
1140 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1143 // return AC_BE if packet is not IPv4
1144 if ((Byte0 & 0xf0) != 0x40)
1148 UserPriority = (Byte1 & 0xe0) >> 5;
1149 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1151 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1152 // TODO: downgrade UP & QueIdx before passing ACM
1153 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1161 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1165 // Make sure SendTxWait queue resource won't be used by other threads
1166 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1167 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1169 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1171 StopNetIfQueue(pAd, QueIdx, pPacket);
1172 #endif // BLOCK_NET_IF //
1173 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1175 return NDIS_STATUS_FAILURE;
1179 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1181 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1183 #ifdef DOT11_N_SUPPORT
1184 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1185 (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1187 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1188 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1189 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1190 // For IOT compatibility, if
1191 // 1. It is Ralink chip or
1192 // 2. It is OPEN or AES mode,
1193 // then BA session can be bulit.
1194 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1195 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1198 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1201 #endif // DOT11_N_SUPPORT //
1203 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1204 return NDIS_STATUS_SUCCESS;
1209 ========================================================================
1211 Routine Description:
1212 This subroutine will scan through releative ring descriptor to find
1213 out avaliable free ring descriptor and compare with request size.
1216 pAd Pointer to our adapter
1217 QueIdx Selected TX Ring
1220 NDIS_STATUS_FAILURE Not enough free descriptor
1221 NDIS_STATUS_SUCCESS Enough free descriptor
1223 IRQL = PASSIVE_LEVEL
1224 IRQL = DISPATCH_LEVEL
1228 ========================================================================
1231 NDIS_STATUS RTMPFreeTXDRequest(
1232 IN PRTMP_ADAPTER pAd,
1234 IN UCHAR NumberRequired,
1235 IN PUCHAR FreeNumberIs)
1237 ULONG FreeNumber = 0;
1238 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1247 if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1248 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1250 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1252 if (FreeNumber >= NumberRequired)
1253 Status = NDIS_STATUS_SUCCESS;
1257 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1258 FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1260 FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1262 if (FreeNumber >= NumberRequired)
1263 Status = NDIS_STATUS_SUCCESS;
1267 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1270 *FreeNumberIs = (UCHAR)FreeNumber;
1278 VOID RTMPSendDisassociationFrame(
1279 IN PRTMP_ADAPTER pAd)
1283 VOID RTMPSendNullFrame(
1284 IN PRTMP_ADAPTER pAd,
1286 IN BOOLEAN bQosNull)
1288 UCHAR NullFrame[48];
1290 PHEADER_802_11 pHeader_802_11;
1298 #endif // RALINK_ATE //
1300 // WPA 802.1x secured port control
1301 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1302 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1303 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1304 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1305 #ifdef WPA_SUPPLICANT_SUPPORT
1306 || (pAd->StaCfg.IEEE8021X == TRUE)
1309 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1314 NdisZeroMemory(NullFrame, 48);
1315 Length = sizeof(HEADER_802_11);
1317 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1319 pHeader_802_11->FC.Type = BTYPE_DATA;
1320 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1321 pHeader_802_11->FC.ToDs = 1;
1322 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1323 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1324 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1326 if (pAd->CommonCfg.bAPSDForcePowerSave)
1328 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1332 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1334 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1337 pHeader_802_11->Sequence = pAd->Sequence;
1339 // Prepare QosNull function frame
1342 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1344 // copy QOS control bytes
1345 NullFrame[Length] = 0;
1346 NullFrame[Length+1] = 0;
1347 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1350 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1354 // IRQL = DISPATCH_LEVEL
1355 VOID RTMPSendRTSFrame(
1356 IN PRTMP_ADAPTER pAd,
1358 IN unsigned int NextMpduSize,
1361 IN USHORT AckDuration,
1369 // --------------------------------------------------------
1370 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1371 // Find the WPA key, either Group or Pairwise Key
1372 // LEAP + TKIP also use WPA key.
1373 // --------------------------------------------------------
1374 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1375 // In Cisco CCX 2.0 Leap Authentication
1376 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1377 // Instead of the SharedKey, SharedKey Length may be Zero.
1378 VOID STAFindCipherAlgorithm(
1379 IN PRTMP_ADAPTER pAd,
1382 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1383 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1384 UCHAR KeyIdx = 0xff;
1386 PCIPHER_KEY pKey = NULL;
1388 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1392 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1393 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1395 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1397 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1399 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1401 // 4-way handshaking frame must be clear
1402 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1403 (pAd->SharedKey[BSS0][0].KeyLen))
1405 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1409 else if (Cipher == Ndis802_11Encryption1Enabled)
1412 if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1414 if (LEAP_CCKM_ON(pAd))
1416 if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1422 KeyIdx = pAd->StaCfg.DefaultKeyId;
1424 else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1425 KeyIdx = pAd->StaCfg.DefaultKeyId;
1426 else if (LEAP_CCKM_ON(pAd))
1428 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1433 else // standard WEP64 or WEP128
1434 #endif // LEAP_SUPPORT //
1435 KeyIdx = pAd->StaCfg.DefaultKeyId;
1437 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1438 (Cipher == Ndis802_11Encryption3Enabled))
1440 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1441 KeyIdx = pAd->StaCfg.DefaultKeyId;
1442 else if (pAd->SharedKey[BSS0][0].KeyLen)
1445 KeyIdx = pAd->StaCfg.DefaultKeyId;
1449 CipherAlg = CIPHER_NONE;
1450 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1451 CipherAlg = CIPHER_NONE;
1452 #ifdef WPA_SUPPLICANT_SUPPORT
1453 else if ( pAd->StaCfg.WpaSupplicantUP &&
1454 (Cipher == Ndis802_11Encryption1Enabled) &&
1455 (pAd->StaCfg.IEEE8021X == TRUE) &&
1456 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1457 CipherAlg = CIPHER_NONE;
1458 #endif // WPA_SUPPLICANT_SUPPORT //
1461 //Header_802_11.FC.Wep = 1;
1462 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1463 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1467 pTxBlk->CipherAlg = CipherAlg;
1468 pTxBlk->pKey = pKey;
1472 VOID STABuildCommon802_11Header(
1473 IN PRTMP_ADAPTER pAd,
1477 HEADER_802_11 *pHeader_802_11;
1478 #ifdef QOS_DLS_SUPPORT
1479 BOOLEAN bDLSFrame = FALSE;
1480 INT DlsEntryIndex = 0;
1481 #endif // QOS_DLS_SUPPORT //
1484 // MAKE A COMMON 802.11 HEADER
1487 // normal wlan header size : 24 octets
1488 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1490 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1492 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1494 pHeader_802_11->FC.FrDs = 0;
1495 pHeader_802_11->FC.Type = BTYPE_DATA;
1496 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1498 #ifdef QOS_DLS_SUPPORT
1501 // Check if the frame can be sent through DLS direct link interface
1502 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1503 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1504 if (DlsEntryIndex >= 0)
1509 #endif // QOS_DLS_SUPPORT //
1511 if (pTxBlk->pMacEntry)
1513 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1515 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1516 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1520 #ifdef QOS_DLS_SUPPORT
1523 pHeader_802_11->Sequence = pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence;
1524 pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence = (pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence+1) & MAXSEQ;
1527 #endif // QOS_DLS_SUPPORT //
1529 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1530 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1536 pHeader_802_11->Sequence = pAd->Sequence;
1537 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1540 pHeader_802_11->Frag = 0;
1542 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1547 #ifdef QOS_DLS_SUPPORT
1550 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1551 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1552 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1553 pHeader_802_11->FC.ToDs = 0;
1556 #endif // QOS_DLS_SUPPORT //
1558 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1559 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1560 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1561 pHeader_802_11->FC.ToDs = 1;
1564 else if (ADHOC_ON(pAd))
1566 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1567 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1568 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1569 pHeader_802_11->FC.ToDs = 0;
1573 if (pTxBlk->CipherAlg != CIPHER_NONE)
1574 pHeader_802_11->FC.Wep = 1;
1576 // -----------------------------------------------------------------
1577 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1578 // -----------------------------------------------------------------
1579 if (pAd->CommonCfg.bAPSDForcePowerSave)
1580 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1582 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1585 #ifdef DOT11_N_SUPPORT
1586 VOID STABuildCache802_11Header(
1587 IN RTMP_ADAPTER *pAd,
1591 MAC_TABLE_ENTRY *pMacEntry;
1592 PHEADER_802_11 pHeader80211;
1594 pHeader80211 = (PHEADER_802_11)pHeader;
1595 pMacEntry = pTxBlk->pMacEntry;
1598 // Update the cached 802.11 HEADER
1601 // normal wlan header size : 24 octets
1602 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1605 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1608 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1609 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1612 // Check if the frame can be sent through DLS direct link interface
1613 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1614 #ifdef QOS_DLS_SUPPORT
1615 BOOLEAN bDLSFrame = FALSE;
1616 INT DlsEntryIndex = 0;
1618 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1619 if (DlsEntryIndex >= 0)
1623 #endif // QOS_DLS_SUPPORT //
1625 // The addr3 of normal packet send from DS is Dest Mac address.
1626 #ifdef QOS_DLS_SUPPORT
1629 COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
1630 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1631 pHeader80211->FC.ToDs = 0;
1634 #endif // QOS_DLS_SUPPORT //
1636 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1638 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1641 // -----------------------------------------------------------------
1642 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1643 // -----------------------------------------------------------------
1644 if (pAd->CommonCfg.bAPSDForcePowerSave)
1645 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1647 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1649 #endif // DOT11_N_SUPPORT //
1651 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1652 IN RTMP_ADAPTER *pAd,
1655 PUCHAR pHeaderBufPtr;
1656 HEADER_802_11 *pHeader_802_11;
1657 PNDIS_PACKET pNextPacket;
1659 PQUEUE_ENTRY pQEntry;
1661 STAFindCipherAlgorithm(pAd, pTxBlk);
1662 STABuildCommon802_11Header(pAd, pTxBlk);
1665 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1666 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1668 // steal "order" bit to mark "aggregation"
1669 pHeader_802_11->FC.Order = 1;
1671 // skip common header
1672 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1674 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1677 // build QOS Control bytes
1679 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1681 *(pHeaderBufPtr+1) = 0;
1683 pTxBlk->MpduHeaderLen += 2;
1686 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1687 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1688 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1689 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1691 // For RA Aggregation,
1692 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1693 pQEntry = pTxBlk->TxPacketList.Head;
1694 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1695 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1696 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1697 nextBufLen -= LENGTH_802_1Q;
1699 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1700 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1703 pTxBlk->MpduHeaderLen += 2;
1705 return pHeaderBufPtr;
1709 #ifdef DOT11_N_SUPPORT
1710 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1711 IN RTMP_ADAPTER *pAd,
1714 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1715 HEADER_802_11 *pHeader_802_11;
1718 STAFindCipherAlgorithm(pAd, pTxBlk);
1719 STABuildCommon802_11Header(pAd, pTxBlk);
1721 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1722 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1724 // skip common header
1725 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1728 // build QOS Control bytes
1730 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1735 *pHeaderBufPtr |= 0x80;
1737 *(pHeaderBufPtr+1) = 0;
1739 pTxBlk->MpduHeaderLen += 2;
1741 //pSaveBufPtr = pHeaderBufPtr;
1744 // padding at front of LLC header
1745 // LLC header should locate at 4-octets aligment
1747 // @@@ MpduHeaderLen excluding padding @@@
1749 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1750 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1751 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1753 return pHeaderBufPtr;
1758 VOID STA_AMPDU_Frame_Tx(
1759 IN PRTMP_ADAPTER pAd,
1762 HEADER_802_11 *pHeader_802_11;
1763 PUCHAR pHeaderBufPtr;
1765 MAC_TABLE_ENTRY *pMacEntry;
1767 PQUEUE_ENTRY pQEntry;
1771 while(pTxBlk->TxPacketList.Head)
1773 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1774 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1775 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1777 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1781 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1783 pMacEntry = pTxBlk->pMacEntry;
1784 if (pMacEntry->isCached)
1786 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1787 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1788 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1789 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1793 STAFindCipherAlgorithm(pAd, pTxBlk);
1794 STABuildCommon802_11Header(pAd, pTxBlk);
1796 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1800 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1802 // skip common header
1803 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1806 // build QOS Control bytes
1808 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1809 *(pHeaderBufPtr+1) = 0;
1811 pTxBlk->MpduHeaderLen += 2;
1815 // HTC control filed following QoS field
1817 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1819 if (pMacEntry->isCached == FALSE)
1822 pHeader_802_11->FC.Order = 1;
1824 NdisZeroMemory(pHeaderBufPtr, 4);
1825 *(pHeaderBufPtr+3) |= 0x80;
1828 pTxBlk->MpduHeaderLen += 4;
1831 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1832 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1834 // skip 802.3 header
1835 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1836 pTxBlk->SrcBufLen -= LENGTH_802_3;
1841 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1842 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1846 // padding at front of LLC header
1847 // LLC header should locate at 4-octets aligment
1849 // @@@ MpduHeaderLen excluding padding @@@
1851 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1852 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1853 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1858 // Insert LLC-SNAP encapsulation - 8 octets
1860 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1861 if (pTxBlk->pExtraLlcSnapEncap)
1863 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1865 // get 2 octets (TypeofLen)
1866 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1868 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1873 if (pMacEntry->isCached)
1875 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1879 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1881 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1882 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1883 pMacEntry->isCached = TRUE;
1886 // calculate Transmitted AMPDU count and ByteCount
1888 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1889 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1892 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1894 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1899 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1900 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1902 pAd->RalinkCounters.KickTxCount++;
1903 pAd->RalinkCounters.OneSecTxDoneCount++;
1909 VOID STA_AMSDU_Frame_Tx(
1910 IN PRTMP_ADAPTER pAd,
1913 PUCHAR pHeaderBufPtr;
1915 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1916 USHORT totalMPDUSize=0;
1917 UCHAR *subFrameHeader;
1919 USHORT FirstTx = 0, LastTxIdx = 0;
1922 PQUEUE_ENTRY pQEntry;
1927 ASSERT((pTxBlk->TxPacketList.Number > 1));
1929 while(pTxBlk->TxPacketList.Head)
1931 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1932 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1933 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1935 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1939 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1941 // skip 802.3 header
1942 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1943 pTxBlk->SrcBufLen -= LENGTH_802_3;
1948 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1949 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1954 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1956 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1957 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1961 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1962 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1963 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1964 pHeaderBufPtr += padding;
1965 pTxBlk->MpduHeaderLen = padding;
1970 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1972 subFrameHeader = pHeaderBufPtr;
1973 subFramePayloadLen = pTxBlk->SrcBufLen;
1975 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1978 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1979 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1983 // Insert LLC-SNAP encapsulation - 8 octets
1985 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1987 subFramePayloadLen = pTxBlk->SrcBufLen;
1989 if (pTxBlk->pExtraLlcSnapEncap)
1991 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1993 // get 2 octets (TypeofLen)
1994 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1996 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1997 subFramePayloadLen += LENGTH_802_1_H;
2000 // update subFrame Length field
2001 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
2002 subFrameHeader[13] = subFramePayloadLen & 0xFF;
2004 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2007 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2009 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2013 pAd->RalinkCounters.KickTxCount++;
2014 pAd->RalinkCounters.OneSecTxDoneCount++;
2016 // calculate Transmitted AMSDU Count and ByteCount
2018 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
2019 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
2024 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2025 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2030 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2031 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2033 #endif // DOT11_N_SUPPORT //
2035 VOID STA_Legacy_Frame_Tx(
2036 IN PRTMP_ADAPTER pAd,
2039 HEADER_802_11 *pHeader_802_11;
2040 PUCHAR pHeaderBufPtr;
2043 PQUEUE_ENTRY pQEntry;
2048 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2049 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2050 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2052 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2056 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
2058 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
2061 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
2062 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
2064 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
2066 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2068 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
2069 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
2071 STAFindCipherAlgorithm(pAd, pTxBlk);
2072 STABuildCommon802_11Header(pAd, pTxBlk);
2075 // skip 802.3 header
2076 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2077 pTxBlk->SrcBufLen -= LENGTH_802_3;
2082 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2083 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2086 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2087 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
2089 // skip common header
2090 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2092 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2095 // build QOS Control bytes
2097 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2098 *(pHeaderBufPtr+1) = 0;
2100 pTxBlk->MpduHeaderLen += 2;
2103 // The remaining content of MPDU header should locate at 4-octets aligment
2104 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2105 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2106 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2111 // Insert LLC-SNAP encapsulation - 8 octets
2114 // if original Ethernet frame contains no LLC/SNAP,
2115 // then an extra LLC/SNAP encap is required
2117 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2118 if (pTxBlk->pExtraLlcSnapEncap)
2122 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2125 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2126 // get 2 octets (TypeofLen)
2127 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2129 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2136 // use Wcid as Key Index
2139 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2141 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2143 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2145 pAd->RalinkCounters.KickTxCount++;
2146 pAd->RalinkCounters.OneSecTxDoneCount++;
2151 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2152 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2156 VOID STA_ARalink_Frame_Tx(
2157 IN PRTMP_ADAPTER pAd,
2160 PUCHAR pHeaderBufPtr;
2162 USHORT totalMPDUSize=0;
2163 USHORT FirstTx, LastTxIdx;
2166 PQUEUE_ENTRY pQEntry;
2171 ASSERT((pTxBlk->TxPacketList.Number== 2));
2174 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2175 while(pTxBlk->TxPacketList.Head)
2177 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2178 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2180 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2182 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2186 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2188 // skip 802.3 header
2189 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2190 pTxBlk->SrcBufLen -= LENGTH_802_3;
2195 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2196 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2200 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2202 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2204 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2205 // will be updated after final frame was handled.
2206 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2210 // Insert LLC-SNAP encapsulation - 8 octets
2212 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2214 if (pTxBlk->pExtraLlcSnapEncap)
2216 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2218 // get 2 octets (TypeofLen)
2219 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2221 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2225 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2227 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2228 pTxBlk->MpduHeaderLen = 0;
2230 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2231 // DA(6)+SA(6)+FrameType(2)
2232 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2233 pHeaderBufPtr += 12;
2234 // get 2 octets (TypeofLen)
2235 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2237 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2240 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2242 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2244 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2246 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2250 pAd->RalinkCounters.OneSecTxAggregationCount++;
2251 pAd->RalinkCounters.KickTxCount++;
2252 pAd->RalinkCounters.OneSecTxDoneCount++;
2256 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2257 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2262 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2263 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2268 VOID STA_Fragment_Frame_Tx(
2269 IN RTMP_ADAPTER *pAd,
2272 HEADER_802_11 *pHeader_802_11;
2273 PUCHAR pHeaderBufPtr;
2276 PACKET_INFO PacketInfo;
2277 USHORT EncryptionOverhead = 0;
2278 UINT32 FreeMpduSize, SrcRemainingBytes;
2282 PQUEUE_ENTRY pQEntry;
2287 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2288 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2289 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2291 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2295 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2296 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2298 STAFindCipherAlgorithm(pAd, pTxBlk);
2299 STABuildCommon802_11Header(pAd, pTxBlk);
2301 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2303 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2304 if (pTxBlk->pPacket == NULL)
2306 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2309 // skip 802.3 header
2310 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2311 pTxBlk->SrcBufLen -= LENGTH_802_3;
2317 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2318 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2321 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2322 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2325 // skip common header
2326 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2328 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2331 // build QOS Control bytes
2333 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2335 *(pHeaderBufPtr+1) = 0;
2337 pTxBlk->MpduHeaderLen += 2;
2341 // padding at front of LLC header
2342 // LLC header should locate at 4-octets aligment
2344 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2345 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2346 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2351 // Insert LLC-SNAP encapsulation - 8 octets
2354 // if original Ethernet frame contains no LLC/SNAP,
2355 // then an extra LLC/SNAP encap is required
2357 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2358 if (pTxBlk->pExtraLlcSnapEncap)
2362 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2365 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2366 // get 2 octets (TypeofLen)
2367 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2369 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2373 // If TKIP is used and fragmentation is required. Driver has to
2374 // append TKIP MIC at tail of the scatter buffer
2375 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2376 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2379 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2380 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2381 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2382 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2383 pTxBlk->SrcBufLen += 8;
2384 pTxBlk->TotalFrameLen += 8;
2385 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2389 // calcuate the overhead bytes that encryption algorithm may add. This
2390 // affects the calculate of "duration" field
2392 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2393 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2394 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2395 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2396 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2397 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2398 else if (pTxBlk->CipherAlg == CIPHER_AES)
2399 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2401 EncryptionOverhead = 0;
2403 // decide how much time an ACK/CTS frame will consume in the air
2404 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2406 // Init the total payload length of this frame.
2407 SrcRemainingBytes = pTxBlk->SrcBufLen;
2409 pTxBlk->TotalFragNum = 0xff;
2413 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2415 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2417 if (SrcRemainingBytes <= FreeMpduSize)
2418 { // this is the last or only fragment
2420 pTxBlk->SrcBufLen = SrcRemainingBytes;
2422 pHeader_802_11->FC.MoreFrag = 0;
2423 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2425 // Indicate the lower layer that this's the last fragment.
2426 pTxBlk->TotalFragNum = fragNum;
2429 { // more fragment is required
2431 pTxBlk->SrcBufLen = FreeMpduSize;
2433 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2434 pHeader_802_11->FC.MoreFrag = 1;
2435 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2439 pTxBlk->FrameGap = IFS_HTTXOP;
2441 pTxBlk->FrameGap = IFS_SIFS;
2443 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2445 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2447 pAd->RalinkCounters.KickTxCount++;
2448 pAd->RalinkCounters.OneSecTxDoneCount++;
2450 // Update the frame number, remaining size of the NDIS packet payload.
2452 // space for 802.11 header.
2453 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2454 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2457 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2458 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2460 pHeader_802_11->Frag++; // increase Frag #
2462 }while(SrcRemainingBytes > 0);
2467 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2471 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2472 while(_pTxBlk->TxPacketList.Head) \
2474 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2475 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2480 ========================================================================
2482 Routine Description:
2483 Copy frame from waiting queue into relative ring buffer and set
2484 appropriate ASIC register to kick hardware encryption before really
2488 pAd Pointer to our adapter
2489 PNDIS_PACKET Pointer to outgoing Ndis frame
2490 NumberOfFrag Number of fragment required
2495 IRQL = DISPATCH_LEVEL
2499 ========================================================================
2501 NDIS_STATUS STAHardTransmit(
2502 IN PRTMP_ADAPTER pAd,
2506 NDIS_PACKET *pPacket;
2507 PQUEUE_ENTRY pQEntry;
2509 // ---------------------------------------------
2510 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2511 // ---------------------------------------------
2513 ASSERT(pTxBlk->TxPacketList.Number);
2514 if (pTxBlk->TxPacketList.Head == NULL)
2516 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2517 return NDIS_STATUS_FAILURE;
2520 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2522 #if 0 //def CARRIER_DETECTION_SUPPORT // Roger sync Carrier
2523 if ((pAd->CommonCfg.CarrierDetect.Enable == TRUE) && (isCarrierDetectExist(pAd) == TRUE))
2525 DBGPRINT(RT_DEBUG_INFO,("STAHardTransmit --> radar detect not in normal mode !!!\n"));
2526 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2527 return (NDIS_STATUS_FAILURE);
2529 #endif // CARRIER_DETECTION_SUPPORT //
2531 // ------------------------------------------------------------------
2532 // STEP 1. WAKE UP PHY
2533 // outgoing frame always wakeup PHY to prevent frame lost and
2534 // turn off PSM bit to improve performance
2535 // ------------------------------------------------------------------
2536 // not to change PSM bit, just send this frame out?
2537 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2539 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2540 AsicForceWakeup(pAd, FROM_TX);
2543 // It should not change PSM bit, when APSD turn on.
2544 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2545 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2546 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2548 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2549 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2550 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2553 switch (pTxBlk->TxFrameType)
2555 #ifdef DOT11_N_SUPPORT
2556 case TX_AMPDU_FRAME:
2557 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2559 case TX_AMSDU_FRAME:
2560 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2562 #endif // DOT11_N_SUPPORT //
2563 case TX_LEGACY_FRAME:
2564 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2566 case TX_MCAST_FRAME:
2567 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2569 case TX_RALINK_FRAME:
2570 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2573 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2577 // It should not happened!
2578 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2579 while(pTxBlk->TxPacketList.Number)
2581 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2582 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2584 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2590 return (NDIS_STATUS_SUCCESS);
2594 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2596 unsigned char *word = value;
2597 unsigned int ret = 0;
2600 for(i=0; i < len; i++)
2603 ret ^=(unsigned int) (word[i]) << mod;
2604 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2609 VOID Sta_Announce_or_Forward_802_3_Packet(
2610 IN PRTMP_ADAPTER pAd,
2611 IN PNDIS_PACKET pPacket,
2612 IN UCHAR FromWhichBSSID)
2617 announce_802_3_packet(pAd, pPacket);
2622 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);