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 -------- ---------- ----------------------------------------------
37 #include "../rt_config.h"
41 VOID STARxEAPOLFrameIndicate(
43 IN MAC_TABLE_ENTRY *pEntry,
45 IN UCHAR FromWhichBSSID)
47 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
48 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
51 if (pAd->StaCfg.WpaSupplicantUP)
53 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
54 // TBD : process fragmented EAPol frames
56 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
57 if ( pAd->StaCfg.IEEE8021X == TRUE &&
58 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
64 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
65 //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
66 STA_PORT_SECURED(pAd);
68 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
70 idx = pAd->StaCfg.DesireSharedKeyId;
71 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
72 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
74 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
77 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
79 // Set key material and cipherAlg to Asic
80 AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
82 // Assign group key info
83 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
85 // Assign pairwise key info
86 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
88 pAd->IndicateMediaState = NdisMediaStateConnected;
89 pAd->ExtraInfo = GENERAL_LINK_UP;
90 #endif // RTMP_MAC_PCI //
94 char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
95 NDIS_802_11_WEP keyinfo;
100 NdisZeroMemory(&WepKey, sizeof(WepKey));
101 len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
103 NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
104 pAd->StaCfg.DesireSharedKey[idx].Key,
105 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
107 WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
108 WepKey.keyinfo.KeyLength = len;
109 pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
111 pAd->IndicateMediaState = NdisMediaStateConnected;
112 pAd->ExtraInfo = GENERAL_LINK_UP;
113 // need to enqueue cmd to thread
114 RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
115 #endif // RTMP_MAC_USB //
116 // For Preventing ShardKey Table is cleared by remove key procedure.
117 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
118 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
119 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
120 pAd->StaCfg.DesireSharedKey[idx].Key,
121 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
126 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
132 // Special DATA frame that has to pass to MLME
133 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
134 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
136 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
137 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
138 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
139 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
143 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
148 VOID STARxDataFrameAnnounce(
149 IN PRTMP_ADAPTER pAd,
150 IN MAC_TABLE_ENTRY *pEntry,
152 IN UCHAR FromWhichBSSID)
156 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
160 // drop all non-EAP DATA frame before
161 // this client's Port-Access-Control is secured
162 if (pRxBlk->pHeader->FC.Wep)
164 // unsupported cipher suite
165 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
168 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
174 // encryption in-use but receive a non-EAPOL clear text frame, drop it
175 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
176 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
179 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
184 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
185 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
187 // Normal legacy, AMPDU or AMSDU
188 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
194 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
199 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
201 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
203 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
207 // Determin the destination of the EAP frame
208 // to WPA state machine or upper layer
209 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
215 // For TKIP frame, calculate the MIC value
216 BOOLEAN STACheckTkipMICValue(
217 IN PRTMP_ADAPTER pAd,
218 IN MAC_TABLE_ENTRY *pEntry,
221 PHEADER_802_11 pHeader = pRxBlk->pHeader;
222 UCHAR *pData = pRxBlk->pData;
223 USHORT DataSize = pRxBlk->DataSize;
224 UCHAR UserPriority = pRxBlk->UserPriority;
228 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
230 pDA = pHeader->Addr1;
231 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
233 pSA = pHeader->Addr3;
237 pSA = pHeader->Addr2;
240 if (RTMPTkipCompareMICValue(pAd,
248 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
250 if (pAd->StaCfg.WpaSupplicantUP)
252 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
256 RTMPReportMicError(pAd, pWpaKey);
260 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
269 // All Rx routines use RX_BLK structure to hande rx events
270 // It is very important to build pRxBlk attributes
271 // 1. pHeader pointer to 802.11 Header
272 // 2. pData pointer to payload including LLC (just skip Header)
273 // 3. set payload size including LLC to DataSize
274 // 4. set some flags with RX_BLK_SET_FLAG()
276 VOID STAHandleRxDataFrame(
277 IN PRTMP_ADAPTER pAd,
280 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
281 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
282 PHEADER_802_11 pHeader = pRxBlk->pHeader;
283 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
284 BOOLEAN bFragment = FALSE;
285 MAC_TABLE_ENTRY *pEntry = NULL;
286 UCHAR FromWhichBSSID = BSS0;
287 UCHAR UserPriority = 0;
290 // before LINK UP, all DATA frames are rejected
291 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
294 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
298 // Drop not my BSS frames
299 if (pRxD->MyBss == 0)
303 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
308 pAd->RalinkCounters.RxCountSinceLastNULL++;
309 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
312 DBGPRINT(RT_DEBUG_INFO,("bAPSDCapable\n"));
315 pData = (PUCHAR)pHeader + LENGTH_802_11;
316 if ((*pData >> 4) & 0x01)
318 DBGPRINT(RT_DEBUG_INFO,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
319 pAd->CommonCfg.bInServicePeriod = FALSE;
321 // Force driver to fall into sleep mode when rcv EOSP frame
322 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
324 USHORT TbttNumToNextWakeUp;
325 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
328 NdisGetSystemUpTime(&Now);
329 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
331 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
332 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
333 TbttNumToNextWakeUp = NextDtim;
335 RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
336 // if WMM-APSD is failed, try to disable following line
337 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
341 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
343 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
347 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
348 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
351 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
355 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
359 // Infrastructure mode, check address 2 for BSSID
360 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
362 // Receive frame not my BSSID
364 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
368 else // Ad-Hoc mode or Not associated
370 // Ad-Hoc mode, check address 3 for BSSID
371 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
373 // Receive frame not my BSSID
375 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
383 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
385 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
389 // 1. release packet if infra mode
390 // 2. new a pEntry if ad-hoc mode
391 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
398 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
399 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
402 // check Atheros Client
403 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
405 pEntry->bIAmBadAtheros = TRUE;
406 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
407 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
408 if (!STA_AES_ON(pAd))
410 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
415 pRxBlk->pData = (UCHAR *)pHeader;
418 // update RxBlk->pData, DataSize
419 // 802.11 Header, QOS, HTC, Hw Padding
422 // 1. skip 802.11 HEADER
424 pRxBlk->pData += LENGTH_802_11;
425 pRxBlk->DataSize -= LENGTH_802_11;
429 if (pHeader->FC.SubType & 0x08)
431 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
432 UserPriority = *(pRxBlk->pData) & 0x0f;
433 // bit 7 in QoS Control field signals the HT A-MSDU format
434 if ((*pRxBlk->pData) & 0x80)
436 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
439 // skip QOS contorl field
441 pRxBlk->DataSize -=2;
443 pRxBlk->UserPriority = UserPriority;
445 /* check if need to resend PS Poll when received packet with MoreData = 1 */
446 if ((pAd->StaCfg.Psm == PWR_SAVE) && (pHeader->FC.MoreData == 1))
448 if ((((UserPriority == 0) || (UserPriority == 3)) &&
449 pAd->CommonCfg.bAPSDAC_BE == 0) ||
450 (((UserPriority == 1) || (UserPriority == 2)) &&
451 pAd->CommonCfg.bAPSDAC_BK == 0) ||
452 (((UserPriority == 4) || (UserPriority == 5)) &&
453 pAd->CommonCfg.bAPSDAC_VI == 0) ||
454 (((UserPriority == 6) || (UserPriority == 7)) &&
455 pAd->CommonCfg.bAPSDAC_VO == 0))
457 /* non-UAPSD delivery-enabled AC */
458 RTMP_PS_POLL_ENQUEUE(pAd);
462 // 3. Order bit: A-Ralink or HTC+
463 if (pHeader->FC.Order)
465 #ifdef AGGREGATION_SUPPORT
466 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
468 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
471 #endif // AGGREGATION_SUPPORT //
473 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
474 // skip HTC contorl field
476 pRxBlk->DataSize -= 4;
480 // 4. skip HW padding
483 // just move pData pointer
484 // because DataSize excluding HW padding
485 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
491 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
495 // Case I Process Broadcast & Multicast data frame
497 if (pRxD->Bcast || pRxD->Mcast)
499 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
501 // Drop Mcast/Bcast frame with fragment bit on
502 if (pHeader->FC.MoreFrag)
505 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
509 // Filter out Bcast frame which AP relayed for us
510 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
513 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
517 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
522 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
526 pEntry = MacTableLookup(pAd, pHeader->Addr2);
528 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
532 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
534 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
535 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
537 pAd->RalinkCounters.OneSecRxOkDataCnt++;
540 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
542 // re-assemble the fragmented packets
543 // return complete frame (pRxPacket) or NULL
545 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
550 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
552 // process complete frame
553 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
556 pRxBlk->DataSize -= 8;
558 // For TKIP frame, calculate the MIC value
559 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
565 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
571 // because RTMPDeFragmentDataFrame() will release rx packet,
572 // if packet is fragmented
579 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
582 VOID STAHandleRxMgmtFrame(
583 IN PRTMP_ADAPTER pAd,
586 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
587 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
588 PHEADER_802_11 pHeader = pRxBlk->pHeader;
589 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
595 /* check if need to resend PS Poll when received packet with MoreData = 1 */
596 if ((pAd->StaCfg.Psm == PWR_SAVE) && (pHeader->FC.MoreData == 1))
598 /* for UAPSD, all management frames will be VO priority */
599 if (pAd->CommonCfg.bAPSDAC_VO == 0)
601 /* non-UAPSD delivery-enabled AC */
602 RTMP_PS_POLL_ENQUEUE(pAd);
606 /* TODO: if MoreData == 0, station can go to sleep */
609 // We should collect RSSI not only U2M data but also my beacon
610 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))
611 && (pAd->RxAnt.EvaluatePeriod == 0))
613 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
615 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
616 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
620 // First check the size, it MUST not exceed the mlme queue size
621 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
623 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
627 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
628 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
631 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
634 VOID STAHandleRxControlFrame(
635 IN PRTMP_ADAPTER pAd,
638 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
639 PHEADER_802_11 pHeader = pRxBlk->pHeader;
640 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
642 switch (pHeader->FC.SubType)
644 case SUBTYPE_BLOCK_ACK_REQ:
646 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
649 case SUBTYPE_BLOCK_ACK:
655 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
660 ========================================================================
663 Process RxDone interrupt, running in DPC level
666 pAd Pointer to our adapter
671 IRQL = DISPATCH_LEVEL
674 This routine has to maintain Rx ring read pointer.
675 Need to consider QOS DATA format when converting to 802.3
676 ========================================================================
678 BOOLEAN STARxDoneInterruptHandle(
679 IN PRTMP_ADAPTER pAd,
683 UINT32 RxProcessed, RxPending;
684 BOOLEAN bReschedule = FALSE;
685 RT28XX_RXD_STRUC *pRxD;
688 PNDIS_PACKET pRxPacket;
689 PHEADER_802_11 pHeader;
692 RxProcessed = RxPending = 0;
694 // process whole rx ring
698 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
699 fRTMP_ADAPTER_RESET_IN_PROGRESS |
700 fRTMP_ADAPTER_HALT_IN_PROGRESS |
701 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
702 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
708 if (RxProcessed++ > MAX_RX_PROCESS_CNT)
710 // need to reschedule rx handle
714 #endif // RTMP_MAC_PCI //
716 RxProcessed ++; // test
718 // 1. allocate a new data packet into rx ring to replace received packet
719 // then processing the received packet
720 // 2. the callee must take charge of release of packet
721 // 3. As far as driver is concerned ,
722 // the rx packet must
723 // a. be indicated to upper layer or
724 // b. be released if it is discarded
725 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
726 if (pRxPacket == NULL)
728 // no more packet to process
732 // get rx ring descriptor
733 pRxD = &(RxCell.RxD);
734 // get rx data buffer
735 pData = GET_OS_PKT_DATAPTR(pRxPacket);
736 pRxWI = (PRXWI_STRUC) pData;
737 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
740 RxCell.pRxWI = pRxWI;
741 RxCell.pHeader = pHeader;
742 RxCell.pRxPacket = pRxPacket;
743 RxCell.pData = (UCHAR *) pHeader;
744 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
747 // Increase Total receive byte counter after real data received no mater any error or not
748 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
749 pAd->RalinkCounters.OneSecReceivedByteCount += pRxWI->MPDUtotalByteCount;
750 pAd->RalinkCounters.RxCount ++;
752 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
754 if (pRxWI->MPDUtotalByteCount < 14)
755 Status = NDIS_STATUS_FAILURE;
759 send_monitor_packets(pAd, &RxCell);
763 /* STARxDoneInterruptHandle() is called in rtusb_bulk.c */
765 // Check for all RxD errors
766 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
768 // Handle the received frame
769 if (Status == NDIS_STATUS_SUCCESS)
771 switch (pHeader->FC.Type)
773 // CASE I, receive a DATA frame
776 // process DATA frame
777 STAHandleRxDataFrame(pAd, &RxCell);
780 // CASE II, receive a MGMT frame
783 STAHandleRxMgmtFrame(pAd, &RxCell);
786 // CASE III. receive a CNTL frame
789 STAHandleRxControlFrame(pAd, &RxCell);
792 // discard other type
794 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
800 pAd->Counters8023.RxErrors++;
801 // discard this frame
802 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
810 ========================================================================
814 pAd Pointer to our adapter
816 IRQL = DISPATCH_LEVEL
818 ========================================================================
820 VOID RTMPHandleTwakeupInterrupt(
821 IN PRTMP_ADAPTER pAd)
823 AsicForceWakeup(pAd, FALSE);
827 ========================================================================
829 Early checking and OS-depened parsing for Tx packet send to our STA driver.
832 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
833 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
834 UINT NumberOfPackets Number of packet in packet array.
840 This function do early checking and classification for send-out packet.
841 You only can put OS-depened & STA related code in here.
842 ========================================================================
845 IN NDIS_HANDLE MiniportAdapterContext,
846 IN PPNDIS_PACKET ppPacketArray,
847 IN UINT NumberOfPackets)
850 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
851 PNDIS_PACKET pPacket;
852 BOOLEAN allowToSend = FALSE;
855 for (Index = 0; Index < NumberOfPackets; Index++)
857 pPacket = ppPacketArray[Index];
861 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
862 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
863 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
865 // Drop send request since hardware is in reset state
868 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
870 // Drop send request since there are no physical connection yet
875 // Record that orignal packet source is from NDIS layer,so that
876 // later on driver knows how to release this NDIS PACKET
877 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
878 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
879 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
880 pAd->RalinkCounters.PendingNdisPacketCount++;
886 if (allowToSend == TRUE)
887 STASendPacket(pAd, pPacket);
889 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
892 // Dequeue outgoing frames from TxSwQueue[] and process it
893 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
899 ========================================================================
901 This routine is used to do packet parsing and classification for Tx packet
902 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
906 pAd Pointer to our adapter
907 pPacket Pointer to send packet
910 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
911 NDIS_STATUS_FAILURE If failed to do en-queue.
914 You only can put OS-indepened & STA related code in here.
915 ========================================================================
917 NDIS_STATUS STASendPacket(
918 IN PRTMP_ADAPTER pAd,
919 IN PNDIS_PACKET pPacket)
921 PACKET_INFO PacketInfo;
927 UCHAR QueIdx, UserPriority;
928 MAC_TABLE_ENTRY *pEntry = NULL;
929 unsigned int IrqFlags;
933 // Prepare packet information structure for buffer descriptor
934 // chained within a single NDIS packet.
935 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
937 if (pSrcBufVA == NULL)
939 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
940 // Resourece is low, system did not allocate virtual address
941 // return NDIS_STATUS_FAILURE directly to upper layer
942 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
943 return NDIS_STATUS_FAILURE;
949 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
950 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
951 return (NDIS_STATUS_FAILURE);
954 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
955 // Note multicast packets in adhoc also use BSSID_WCID index.
960 pEntry = &pAd->MacTab.Content[BSSID_WCID];
961 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
962 Rate = pAd->CommonCfg.TxRate;
965 else if (ADHOC_ON(pAd))
967 if (*pSrcBufVA & 0x01)
969 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
970 pEntry = &pAd->MacTab.Content[MCAST_WCID];
974 pEntry = MacTableLookup(pAd, pSrcBufVA);
976 Rate = pAd->CommonCfg.TxRate;
982 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
983 // Resourece is low, system did not allocate virtual address
984 // return NDIS_STATUS_FAILURE directly to upper layer
985 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
986 return NDIS_STATUS_FAILURE;
992 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
996 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
997 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
998 RTMPCheckEtherType(pAd, pPacket);
1003 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
1005 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1006 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1007 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1008 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1009 || (pAd->StaCfg.IEEE8021X == TRUE)
1011 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1012 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1015 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1016 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1018 return (NDIS_STATUS_FAILURE);
1022 // STEP 1. Decide number of fragments required to deliver this MSDU.
1023 // The estimation here is not very accurate because difficult to
1024 // take encryption overhead into consideration here. The result
1025 // "NumberOfFrag" is then just used to pre-check if enough free
1026 // TXD are available to hold this MSDU.
1029 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1031 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1032 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1033 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1034 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1035 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1036 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1039 // The calculated "NumberOfFrag" is a rough estimation because of various
1040 // encryption/encapsulation overhead not taken into consideration. This number is just
1041 // used to make sure enough free TXD are available before fragmentation takes place.
1042 // In case the actual required number of fragments of an NDIS packet
1043 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1044 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1045 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1046 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1048 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1049 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1050 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1051 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1057 // Save fragment number to Ndis packet reserved field
1058 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1061 // STEP 2. Check the requirement of RTS:
1062 // If multiple fragment required, RTS is required only for the first fragment
1063 // if the fragment size large than RTS threshold
1064 // For RT28xx, Let ASIC send RTS/CTS
1065 // RTMP_SET_PACKET_RTS(pPacket, 0);
1066 if (NumberOfFrag > 1)
1067 RTSRequired = (pAd->CommonCfg.FragmentThreshold > pAd->CommonCfg.RtsThreshold) ? 1 : 0;
1069 RTSRequired = (PacketInfo.TotalPacketLength > pAd->CommonCfg.RtsThreshold) ? 1 : 0;
1071 // Save RTS requirement to Ndis packet reserved field
1072 RTMP_SET_PACKET_RTS(pPacket, RTSRequired);
1073 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1076 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1080 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1081 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1084 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1087 // get Ethernet protocol field
1088 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1089 if (Protocol <= 1500)
1091 // get Ethernet protocol field from LLC/SNAP
1092 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1095 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1099 // always AC_BE for non-IP packet
1100 if (Protocol != 0x0800)
1104 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1107 // return AC_BE if packet is not IPv4
1108 if ((Byte0 & 0xf0) != 0x40)
1112 UserPriority = (Byte1 & 0xe0) >> 5;
1113 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1115 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1116 // TODO: downgrade UP & QueIdx before passing ACM
1118 Under WMM ACM control, we dont need to check the bit;
1119 Or when a TSPEC is built for VO but we will change to issue
1120 BA session for BE here, so we will not use BA to send VO packets.
1122 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1130 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1134 // Make sure SendTxWait queue resource won't be used by other threads
1135 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1136 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1138 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1139 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1141 return NDIS_STATUS_FAILURE;
1145 InsertTailQueueAc(pAd, pEntry, &pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1147 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1149 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1152 //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID];
1153 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1154 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1155 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1156 // For IOT compatibility, if
1157 // 1. It is Ralink chip or
1158 // 2. It is OPEN or AES mode,
1159 // then BA session can be bulit.
1160 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1161 (pEntry->WepStatus != Ndis802_11WEPEnabled && pEntry->WepStatus != Ndis802_11Encryption2Enabled))
1164 BAOriSessionSetUp(pAd, pEntry, UserPriority, 0, 10, FALSE);
1168 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1169 return NDIS_STATUS_SUCCESS;
1174 ========================================================================
1176 Routine Description:
1177 This subroutine will scan through releative ring descriptor to find
1178 out avaliable free ring descriptor and compare with request size.
1181 pAd Pointer to our adapter
1182 QueIdx Selected TX Ring
1185 NDIS_STATUS_FAILURE Not enough free descriptor
1186 NDIS_STATUS_SUCCESS Enough free descriptor
1188 IRQL = PASSIVE_LEVEL
1189 IRQL = DISPATCH_LEVEL
1193 ========================================================================
1196 NDIS_STATUS RTMPFreeTXDRequest(
1197 IN PRTMP_ADAPTER pAd,
1199 IN UCHAR NumberRequired,
1200 IN PUCHAR FreeNumberIs)
1202 ULONG FreeNumber = 0;
1203 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1212 if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1213 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1215 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1217 if (FreeNumber >= NumberRequired)
1218 Status = NDIS_STATUS_SUCCESS;
1222 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1223 FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1225 FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1227 if (FreeNumber >= NumberRequired)
1228 Status = NDIS_STATUS_SUCCESS;
1232 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1235 *FreeNumberIs = (UCHAR)FreeNumber;
1239 #endif // RTMP_MAC_PCI //
1242 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1243 If no frame need to send, go to sleep, else, still wake up.
1245 NDIS_STATUS RTMPFreeTXDRequest(
1246 IN PRTMP_ADAPTER pAd,
1248 IN UCHAR NumberRequired,
1249 IN PUCHAR FreeNumberIs)
1251 //ULONG FreeNumber = 0;
1252 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1253 unsigned long IrqFlags;
1254 HT_TX_CONTEXT *pHTTXContext;
1263 pHTTXContext = &pAd->TxContext[QueIdx];
1264 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1265 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1266 (pHTTXContext->IRPPending == TRUE))
1268 Status = NDIS_STATUS_FAILURE;
1272 Status = NDIS_STATUS_SUCCESS;
1274 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1278 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1279 Status = NDIS_STATUS_FAILURE;
1281 Status = NDIS_STATUS_SUCCESS;
1284 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1290 #endif // RTMP_MAC_USB //
1292 VOID RTMPSendDisassociationFrame(
1293 IN PRTMP_ADAPTER pAd)
1297 VOID RTMPSendNullFrame(
1298 IN PRTMP_ADAPTER pAd,
1300 IN BOOLEAN bQosNull)
1302 UCHAR NullFrame[48];
1304 PHEADER_802_11 pHeader_802_11;
1306 // WPA 802.1x secured port control
1307 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1308 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1309 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1310 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1311 || (pAd->StaCfg.IEEE8021X == TRUE)
1313 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1318 NdisZeroMemory(NullFrame, 48);
1319 Length = sizeof(HEADER_802_11);
1321 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1323 pHeader_802_11->FC.Type = BTYPE_DATA;
1324 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1325 pHeader_802_11->FC.ToDs = 1;
1326 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1327 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1328 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1330 if (pAd->CommonCfg.bAPSDForcePowerSave)
1332 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1336 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1338 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1341 pHeader_802_11->Sequence = pAd->Sequence;
1343 // Prepare QosNull function frame
1346 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1348 // copy QOS control bytes
1349 NullFrame[Length] = 0;
1350 NullFrame[Length+1] = 0;
1351 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1354 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1358 // IRQL = DISPATCH_LEVEL
1359 VOID RTMPSendRTSFrame(
1360 IN PRTMP_ADAPTER pAd,
1362 IN unsigned int NextMpduSize,
1365 IN USHORT AckDuration,
1373 // --------------------------------------------------------
1374 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1375 // Find the WPA key, either Group or Pairwise Key
1376 // LEAP + TKIP also use WPA key.
1377 // --------------------------------------------------------
1378 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1379 // In Cisco CCX 2.0 Leap Authentication
1380 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1381 // Instead of the SharedKey, SharedKey Length may be Zero.
1382 VOID STAFindCipherAlgorithm(
1383 IN PRTMP_ADAPTER pAd,
1386 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1387 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1388 UCHAR KeyIdx = 0xff;
1390 PCIPHER_KEY pKey = NULL;
1392 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1396 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1397 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1399 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1401 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1403 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1405 // 4-way handshaking frame must be clear
1406 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1407 (pAd->SharedKey[BSS0][0].KeyLen))
1409 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1413 else if (Cipher == Ndis802_11Encryption1Enabled)
1415 KeyIdx = pAd->StaCfg.DefaultKeyId;
1417 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1418 (Cipher == Ndis802_11Encryption3Enabled))
1420 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1421 KeyIdx = pAd->StaCfg.DefaultKeyId;
1422 else if (pAd->SharedKey[BSS0][0].KeyLen)
1425 KeyIdx = pAd->StaCfg.DefaultKeyId;
1429 CipherAlg = CIPHER_NONE;
1430 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1431 CipherAlg = CIPHER_NONE;
1432 else if ( pAd->StaCfg.WpaSupplicantUP &&
1433 (Cipher == Ndis802_11Encryption1Enabled) &&
1434 (pAd->StaCfg.IEEE8021X == TRUE) &&
1435 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1436 CipherAlg = CIPHER_NONE;
1439 //Header_802_11.FC.Wep = 1;
1440 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1441 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1445 pTxBlk->CipherAlg = CipherAlg;
1446 pTxBlk->pKey = pKey;
1450 VOID STABuildCommon802_11Header(
1451 IN PRTMP_ADAPTER pAd,
1454 HEADER_802_11 *pHeader_802_11;
1457 // MAKE A COMMON 802.11 HEADER
1460 // normal wlan header size : 24 octets
1461 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1463 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1465 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1467 pHeader_802_11->FC.FrDs = 0;
1468 pHeader_802_11->FC.Type = BTYPE_DATA;
1469 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1471 if (pTxBlk->pMacEntry)
1473 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1475 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1476 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1481 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1482 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1488 pHeader_802_11->Sequence = pAd->Sequence;
1489 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1492 pHeader_802_11->Frag = 0;
1494 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1500 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1501 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1502 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1503 pHeader_802_11->FC.ToDs = 1;
1506 else if (ADHOC_ON(pAd))
1508 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1509 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1510 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1511 pHeader_802_11->FC.ToDs = 0;
1515 if (pTxBlk->CipherAlg != CIPHER_NONE)
1516 pHeader_802_11->FC.Wep = 1;
1518 // -----------------------------------------------------------------
1519 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1520 // -----------------------------------------------------------------
1521 if (pAd->CommonCfg.bAPSDForcePowerSave)
1522 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1524 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1527 VOID STABuildCache802_11Header(
1528 IN RTMP_ADAPTER *pAd,
1532 MAC_TABLE_ENTRY *pMacEntry;
1533 PHEADER_802_11 pHeader80211;
1535 pHeader80211 = (PHEADER_802_11)pHeader;
1536 pMacEntry = pTxBlk->pMacEntry;
1539 // Update the cached 802.11 HEADER
1542 // normal wlan header size : 24 octets
1543 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1546 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1549 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1550 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1553 // Check if the frame can be sent through DLS direct link interface
1554 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1556 // The addr3 of normal packet send from DS is Dest Mac address.
1558 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1560 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1563 // -----------------------------------------------------------------
1564 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1565 // -----------------------------------------------------------------
1566 if (pAd->CommonCfg.bAPSDForcePowerSave)
1567 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1569 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1572 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1573 IN RTMP_ADAPTER *pAd,
1576 PUCHAR pHeaderBufPtr;
1577 HEADER_802_11 *pHeader_802_11;
1578 PNDIS_PACKET pNextPacket;
1580 PQUEUE_ENTRY pQEntry;
1582 STAFindCipherAlgorithm(pAd, pTxBlk);
1583 STABuildCommon802_11Header(pAd, pTxBlk);
1586 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1587 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1589 // steal "order" bit to mark "aggregation"
1590 pHeader_802_11->FC.Order = 1;
1592 // skip common header
1593 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1595 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1598 // build QOS Control bytes
1600 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1602 *(pHeaderBufPtr+1) = 0;
1604 pTxBlk->MpduHeaderLen += 2;
1607 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1608 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1609 pHeaderBufPtr = (PUCHAR)ROUND_UP(pHeaderBufPtr, 4);
1610 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1612 // For RA Aggregation,
1613 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1614 pQEntry = pTxBlk->TxPacketList.Head;
1615 pNextPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1616 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1617 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1618 nextBufLen -= LENGTH_802_1Q;
1620 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1621 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1624 pTxBlk->MpduHeaderLen += 2;
1626 return pHeaderBufPtr;
1630 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1631 IN RTMP_ADAPTER *pAd,
1634 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1635 HEADER_802_11 *pHeader_802_11;
1638 STAFindCipherAlgorithm(pAd, pTxBlk);
1639 STABuildCommon802_11Header(pAd, pTxBlk);
1641 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1642 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1644 // skip common header
1645 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1648 // build QOS Control bytes
1650 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1655 *pHeaderBufPtr |= 0x80;
1657 *(pHeaderBufPtr+1) = 0;
1659 pTxBlk->MpduHeaderLen += 2;
1661 //pSaveBufPtr = pHeaderBufPtr;
1664 // padding at front of LLC header
1665 // LLC header should locate at 4-octets aligment
1667 // @@@ MpduHeaderLen excluding padding @@@
1669 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1670 pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4);
1671 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1673 return pHeaderBufPtr;
1678 VOID STA_AMPDU_Frame_Tx(
1679 IN PRTMP_ADAPTER pAd,
1682 HEADER_802_11 *pHeader_802_11;
1683 PUCHAR pHeaderBufPtr;
1685 MAC_TABLE_ENTRY *pMacEntry;
1687 PQUEUE_ENTRY pQEntry;
1691 while(pTxBlk->TxPacketList.Head)
1693 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1694 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1695 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1697 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1701 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1703 pMacEntry = pTxBlk->pMacEntry;
1704 if (pMacEntry->isCached)
1706 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1707 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1708 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1709 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1713 STAFindCipherAlgorithm(pAd, pTxBlk);
1714 STABuildCommon802_11Header(pAd, pTxBlk);
1716 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1720 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1722 // skip common header
1723 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1726 // build QOS Control bytes
1728 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1729 *(pHeaderBufPtr+1) = 0;
1731 pTxBlk->MpduHeaderLen += 2;
1735 // HTC control filed following QoS field
1737 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1739 if (pMacEntry->isCached == FALSE)
1742 pHeader_802_11->FC.Order = 1;
1744 NdisZeroMemory(pHeaderBufPtr, 4);
1745 *(pHeaderBufPtr+3) |= 0x80;
1748 pTxBlk->MpduHeaderLen += 4;
1751 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1752 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1754 // skip 802.3 header
1755 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1756 pTxBlk->SrcBufLen -= LENGTH_802_3;
1761 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1762 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1766 // padding at front of LLC header
1767 // LLC header should locate at 4-octets aligment
1769 // @@@ MpduHeaderLen excluding padding @@@
1771 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1772 pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4);
1773 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1778 // Insert LLC-SNAP encapsulation - 8 octets
1780 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1781 if (pTxBlk->pExtraLlcSnapEncap)
1783 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1785 // get 2 octets (TypeofLen)
1786 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1788 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1793 if (pMacEntry->isCached)
1795 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1799 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1801 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1802 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1803 pMacEntry->isCached = TRUE;
1806 // calculate Transmitted AMPDU count and ByteCount
1808 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1809 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1812 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1814 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1819 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1820 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1822 pAd->RalinkCounters.KickTxCount++;
1823 pAd->RalinkCounters.OneSecTxDoneCount++;
1829 VOID STA_AMSDU_Frame_Tx(
1830 IN PRTMP_ADAPTER pAd,
1833 PUCHAR pHeaderBufPtr;
1835 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1836 USHORT totalMPDUSize=0;
1837 UCHAR *subFrameHeader;
1839 USHORT FirstTx = 0, LastTxIdx = 0;
1842 PQUEUE_ENTRY pQEntry;
1847 ASSERT((pTxBlk->TxPacketList.Number > 1));
1849 while(pTxBlk->TxPacketList.Head)
1851 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1852 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1853 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1855 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1859 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1861 // skip 802.3 header
1862 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1863 pTxBlk->SrcBufLen -= LENGTH_802_3;
1868 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1869 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1874 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1876 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1877 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1881 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1882 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1883 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1884 pHeaderBufPtr += padding;
1885 pTxBlk->MpduHeaderLen = padding;
1890 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1892 subFrameHeader = pHeaderBufPtr;
1893 subFramePayloadLen = pTxBlk->SrcBufLen;
1895 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1898 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1899 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1903 // Insert LLC-SNAP encapsulation - 8 octets
1905 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1907 subFramePayloadLen = pTxBlk->SrcBufLen;
1909 if (pTxBlk->pExtraLlcSnapEncap)
1911 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1913 // get 2 octets (TypeofLen)
1914 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1916 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1917 subFramePayloadLen += LENGTH_802_1_H;
1920 // update subFrame Length field
1921 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1922 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1924 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1927 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1929 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1933 pAd->RalinkCounters.KickTxCount++;
1934 pAd->RalinkCounters.OneSecTxDoneCount++;
1936 // calculate Transmitted AMSDU Count and ByteCount
1938 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1939 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1944 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1945 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1950 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1951 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1954 VOID STA_Legacy_Frame_Tx(
1955 IN PRTMP_ADAPTER pAd,
1958 HEADER_802_11 *pHeader_802_11;
1959 PUCHAR pHeaderBufPtr;
1962 PQUEUE_ENTRY pQEntry;
1967 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1968 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1969 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1971 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1975 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1977 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1980 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1981 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1983 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1985 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1987 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1988 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1990 STAFindCipherAlgorithm(pAd, pTxBlk);
1991 STABuildCommon802_11Header(pAd, pTxBlk);
1994 // skip 802.3 header
1995 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1996 pTxBlk->SrcBufLen -= LENGTH_802_3;
2001 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2002 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2005 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2006 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
2008 // skip common header
2009 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2011 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2014 // build QOS Control bytes
2016 *(pHeaderBufPtr) = ((pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx]<<5));
2017 *(pHeaderBufPtr+1) = 0;
2019 pTxBlk->MpduHeaderLen += 2;
2022 // The remaining content of MPDU header should locate at 4-octets aligment
2023 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2024 pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4);
2025 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2030 // Insert LLC-SNAP encapsulation - 8 octets
2033 // if original Ethernet frame contains no LLC/SNAP,
2034 // then an extra LLC/SNAP encap is required
2036 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2037 if (pTxBlk->pExtraLlcSnapEncap)
2041 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2044 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2045 // get 2 octets (TypeofLen)
2046 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2048 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2055 // use Wcid as Key Index
2058 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2060 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2062 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2064 pAd->RalinkCounters.KickTxCount++;
2065 pAd->RalinkCounters.OneSecTxDoneCount++;
2070 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2071 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2075 VOID STA_ARalink_Frame_Tx(
2076 IN PRTMP_ADAPTER pAd,
2079 PUCHAR pHeaderBufPtr;
2081 USHORT totalMPDUSize=0;
2082 USHORT FirstTx, LastTxIdx;
2085 PQUEUE_ENTRY pQEntry;
2090 ASSERT((pTxBlk->TxPacketList.Number== 2));
2093 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2094 while(pTxBlk->TxPacketList.Head)
2096 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2097 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2099 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2101 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2105 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2107 // skip 802.3 header
2108 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2109 pTxBlk->SrcBufLen -= LENGTH_802_3;
2114 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2115 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2119 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2121 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2123 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2124 // will be updated after final frame was handled.
2125 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2129 // Insert LLC-SNAP encapsulation - 8 octets
2131 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2133 if (pTxBlk->pExtraLlcSnapEncap)
2135 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2137 // get 2 octets (TypeofLen)
2138 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2140 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2144 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2146 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2147 pTxBlk->MpduHeaderLen = 0;
2149 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2150 // DA(6)+SA(6)+FrameType(2)
2151 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2152 pHeaderBufPtr += 12;
2153 // get 2 octets (TypeofLen)
2154 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2156 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2159 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2161 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2163 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2165 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2169 pAd->RalinkCounters.OneSecTxAggregationCount++;
2170 pAd->RalinkCounters.KickTxCount++;
2171 pAd->RalinkCounters.OneSecTxDoneCount++;
2175 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2176 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2181 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2182 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2187 VOID STA_Fragment_Frame_Tx(
2188 IN RTMP_ADAPTER *pAd,
2191 HEADER_802_11 *pHeader_802_11;
2192 PUCHAR pHeaderBufPtr;
2195 PACKET_INFO PacketInfo;
2196 USHORT EncryptionOverhead = 0;
2197 UINT32 FreeMpduSize, SrcRemainingBytes;
2201 PQUEUE_ENTRY pQEntry;
2202 HTTRANSMIT_SETTING *pTransmit;
2207 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2208 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2209 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2211 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2215 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2216 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2218 STAFindCipherAlgorithm(pAd, pTxBlk);
2219 STABuildCommon802_11Header(pAd, pTxBlk);
2221 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2223 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2224 if (pTxBlk->pPacket == NULL)
2226 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2229 // skip 802.3 header
2230 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2231 pTxBlk->SrcBufLen -= LENGTH_802_3;
2237 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2238 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2241 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2242 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2245 // skip common header
2246 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2248 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2251 // build QOS Control bytes
2253 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2255 *(pHeaderBufPtr+1) = 0;
2257 pTxBlk->MpduHeaderLen += 2;
2261 // padding at front of LLC header
2262 // LLC header should locate at 4-octets aligment
2264 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2265 pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4);
2266 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2271 // Insert LLC-SNAP encapsulation - 8 octets
2274 // if original Ethernet frame contains no LLC/SNAP,
2275 // then an extra LLC/SNAP encap is required
2277 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2278 if (pTxBlk->pExtraLlcSnapEncap)
2282 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2285 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2286 // get 2 octets (TypeofLen)
2287 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2289 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2293 // If TKIP is used and fragmentation is required. Driver has to
2294 // append TKIP MIC at tail of the scatter buffer
2295 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2296 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2298 RTMPCalculateMICValue(pAd, pTxBlk->pPacket, pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey, 0);
2300 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2301 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2302 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2303 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2304 pTxBlk->SrcBufLen += 8;
2305 pTxBlk->TotalFrameLen += 8;
2306 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2310 // calcuate the overhead bytes that encryption algorithm may add. This
2311 // affects the calculate of "duration" field
2313 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2314 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2315 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2316 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2317 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2318 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2319 else if (pTxBlk->CipherAlg == CIPHER_AES)
2320 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2322 EncryptionOverhead = 0;
2324 pTransmit = pTxBlk->pTransmit;
2325 // Decide the TX rate
2326 if (pTransmit->field.MODE == MODE_CCK)
2327 pTxBlk->TxRate = pTransmit->field.MCS;
2328 else if (pTransmit->field.MODE == MODE_OFDM)
2329 pTxBlk->TxRate = pTransmit->field.MCS + RATE_FIRST_OFDM_RATE;
2331 pTxBlk->TxRate = RATE_6_5;
2333 // decide how much time an ACK/CTS frame will consume in the air
2334 if (pTxBlk->TxRate <= RATE_LAST_OFDM_RATE)
2335 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2337 AckDuration = RTMPCalcDuration(pAd, RATE_6_5, 14);
2339 // Init the total payload length of this frame.
2340 SrcRemainingBytes = pTxBlk->SrcBufLen;
2342 pTxBlk->TotalFragNum = 0xff;
2346 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2348 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2350 if (SrcRemainingBytes <= FreeMpduSize)
2351 { // this is the last or only fragment
2353 pTxBlk->SrcBufLen = SrcRemainingBytes;
2355 pHeader_802_11->FC.MoreFrag = 0;
2356 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2358 // Indicate the lower layer that this's the last fragment.
2359 pTxBlk->TotalFragNum = fragNum;
2362 { // more fragment is required
2364 pTxBlk->SrcBufLen = FreeMpduSize;
2366 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2367 pHeader_802_11->FC.MoreFrag = 1;
2368 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2372 pTxBlk->FrameGap = IFS_HTTXOP;
2374 pTxBlk->FrameGap = IFS_SIFS;
2376 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2378 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2380 pAd->RalinkCounters.KickTxCount++;
2381 pAd->RalinkCounters.OneSecTxDoneCount++;
2383 // Update the frame number, remaining size of the NDIS packet payload.
2385 // space for 802.11 header.
2386 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2387 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2390 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2391 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2393 pHeader_802_11->Frag++; // increase Frag #
2395 }while(SrcRemainingBytes > 0);
2400 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2401 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2405 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2406 while(_pTxBlk->TxPacketList.Head) \
2408 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2409 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2414 ========================================================================
2416 Routine Description:
2417 Copy frame from waiting queue into relative ring buffer and set
2418 appropriate ASIC register to kick hardware encryption before really
2422 pAd Pointer to our adapter
2423 PNDIS_PACKET Pointer to outgoing Ndis frame
2424 NumberOfFrag Number of fragment required
2429 IRQL = DISPATCH_LEVEL
2433 ========================================================================
2435 NDIS_STATUS STAHardTransmit(
2436 IN PRTMP_ADAPTER pAd,
2440 NDIS_PACKET *pPacket;
2441 PQUEUE_ENTRY pQEntry;
2443 // ---------------------------------------------
2444 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2445 // ---------------------------------------------
2447 ASSERT(pTxBlk->TxPacketList.Number);
2448 if (pTxBlk->TxPacketList.Head == NULL)
2450 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2451 return NDIS_STATUS_FAILURE;
2454 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2456 // ------------------------------------------------------------------
2457 // STEP 1. WAKE UP PHY
2458 // outgoing frame always wakeup PHY to prevent frame lost and
2459 // turn off PSM bit to improve performance
2460 // ------------------------------------------------------------------
2461 // not to change PSM bit, just send this frame out?
2462 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2464 DBGPRINT_RAW(RT_DEBUG_INFO, ("AsicForceWakeup At HardTx\n"));
2466 AsicForceWakeup(pAd, TRUE);
2467 #endif // RTMP_MAC_PCI //
2469 RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_FORCE_WAKE_UP, NULL, 0);
2470 #endif // RTMP_MAC_USB //
2473 // It should not change PSM bit, when APSD turn on.
2474 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2475 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2476 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2478 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2479 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2480 RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE);
2483 switch (pTxBlk->TxFrameType)
2485 case TX_AMPDU_FRAME:
2486 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2488 case TX_AMSDU_FRAME:
2489 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2491 case TX_LEGACY_FRAME:
2492 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2494 case TX_MCAST_FRAME:
2495 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2497 case TX_RALINK_FRAME:
2498 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2501 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2505 // It should not happened!
2506 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2507 while(pTxBlk->TxPacketList.Number)
2509 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2510 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2512 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2518 return (NDIS_STATUS_SUCCESS);
2522 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2524 unsigned char *word = value;
2525 unsigned int ret = 0;
2528 for(i=0; i < len; i++)
2531 ret ^=(unsigned int) (word[i]) << mod;
2532 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2537 VOID Sta_Announce_or_Forward_802_3_Packet(
2538 IN PRTMP_ADAPTER pAd,
2539 IN PNDIS_PACKET pPacket,
2540 IN UCHAR FromWhichBSSID)
2545 announce_802_3_packet(pAd, pPacket);
2550 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);