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 if (pAd->StaCfg.WpaSupplicantUP)
55 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
56 // TBD : process fragmented EAPol frames
58 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
59 if ( pAd->StaCfg.IEEE8021X == TRUE &&
60 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
66 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
67 STA_PORT_SECURED(pAd);
69 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
71 idx = pAd->StaCfg.DesireSharedKeyId;
72 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
73 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
75 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
78 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
80 // Set key material and cipherAlg to Asic
81 AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
83 // Assign group key info
84 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
86 // Assign pairwise key info
87 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
89 pAd->IndicateMediaState = NdisMediaStateConnected;
90 pAd->ExtraInfo = GENERAL_LINK_UP;
95 char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
96 NDIS_802_11_WEP keyinfo;
101 NdisZeroMemory(&WepKey, sizeof(WepKey));
102 len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
104 NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
105 pAd->StaCfg.DesireSharedKey[idx].Key,
106 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
108 WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
109 WepKey.keyinfo.KeyLength = len;
110 pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
112 pAd->IndicateMediaState = NdisMediaStateConnected;
113 pAd->ExtraInfo = GENERAL_LINK_UP;
114 // need to enqueue cmd to thread
115 RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
117 // For Preventing ShardKey Table is cleared by remove key procedure.
118 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
119 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
120 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
121 pAd->StaCfg.DesireSharedKey[idx].Key,
122 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
127 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
133 // Special DATA frame that has to pass to MLME
134 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
135 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
137 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
138 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
139 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
140 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
144 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
149 VOID STARxDataFrameAnnounce(
150 IN PRTMP_ADAPTER pAd,
151 IN MAC_TABLE_ENTRY *pEntry,
153 IN UCHAR FromWhichBSSID)
157 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_TRACE,("bAPSDCapable\n"));
315 pData = (PUCHAR)pHeader + LENGTH_802_11;
316 if ((*pData >> 4) & 0x01)
318 DBGPRINT(RT_DEBUG_TRACE,("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 MlmeSetPsmBit(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 // 3. Order bit: A-Ralink or HTC+
446 if (pHeader->FC.Order)
448 #ifdef AGGREGATION_SUPPORT
449 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
451 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
456 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
457 // skip HTC contorl field
459 pRxBlk->DataSize -= 4;
463 // 4. skip HW padding
466 // just move pData pointer
467 // because DataSize excluding HW padding
468 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
474 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
478 // Case I Process Broadcast & Multicast data frame
480 if (pRxD->Bcast || pRxD->Mcast)
482 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
484 // Drop Mcast/Bcast frame with fragment bit on
485 if (pHeader->FC.MoreFrag)
488 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
492 // Filter out Bcast frame which AP relayed for us
493 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
496 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
500 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
505 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
509 pEntry = MacTableLookup(pAd, pHeader->Addr2);
511 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
515 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
517 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
518 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
520 pAd->RalinkCounters.OneSecRxOkDataCnt++;
523 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
525 // re-assemble the fragmented packets
526 // return complete frame (pRxPacket) or NULL
528 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
533 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
535 // process complete frame
536 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
539 pRxBlk->DataSize -= 8;
541 // For TKIP frame, calculate the MIC value
542 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
548 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
554 // because RTMPDeFragmentDataFrame() will release rx packet,
555 // if packet is fragmented
562 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
565 VOID STAHandleRxMgmtFrame(
566 IN PRTMP_ADAPTER pAd,
569 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
570 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
571 PHEADER_802_11 pHeader = pRxBlk->pHeader;
572 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
577 // We should collect RSSI not only U2M data but also my beacon
579 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))
580 && (pAd->RxAnt.EvaluatePeriod == 0))
583 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
586 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
588 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
589 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
593 // collect rssi information for antenna diversity
594 if (pAd->NicConfig2.field.AntDiversity)
596 if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))))
598 COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxWI->RSSI0, RSSI_0), 0); //Note: RSSI2 not used on RT73
599 pAd->StaCfg.NumOfAvgRssiSample ++;
604 // First check the size, it MUST not exceed the mlme queue size
605 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
607 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
611 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
612 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
615 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
618 VOID STAHandleRxControlFrame(
619 IN PRTMP_ADAPTER pAd,
622 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
623 PHEADER_802_11 pHeader = pRxBlk->pHeader;
624 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
626 switch (pHeader->FC.SubType)
628 case SUBTYPE_BLOCK_ACK_REQ:
630 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
633 case SUBTYPE_BLOCK_ACK:
639 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
644 ========================================================================
647 Process RxDone interrupt, running in DPC level
650 pAd Pointer to our adapter
655 IRQL = DISPATCH_LEVEL
658 This routine has to maintain Rx ring read pointer.
659 Need to consider QOS DATA format when converting to 802.3
660 ========================================================================
662 BOOLEAN STARxDoneInterruptHandle(
663 IN PRTMP_ADAPTER pAd,
667 UINT32 RxProcessed, RxPending;
668 BOOLEAN bReschedule = FALSE;
669 RT28XX_RXD_STRUC *pRxD;
672 PNDIS_PACKET pRxPacket;
673 PHEADER_802_11 pHeader;
676 RxProcessed = RxPending = 0;
678 // process whole rx ring
682 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
683 fRTMP_ADAPTER_RESET_IN_PROGRESS |
684 fRTMP_ADAPTER_HALT_IN_PROGRESS |
685 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
686 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
692 if (RxProcessed++ > MAX_RX_PROCESS_CNT)
694 // need to reschedule rx handle
700 RxProcessed ++; // test
702 // 1. allocate a new data packet into rx ring to replace received packet
703 // then processing the received packet
704 // 2. the callee must take charge of release of packet
705 // 3. As far as driver is concerned ,
706 // the rx packet must
707 // a. be indicated to upper layer or
708 // b. be released if it is discarded
709 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
710 if (pRxPacket == NULL)
712 // no more packet to process
716 // get rx ring descriptor
717 pRxD = &(RxCell.RxD);
718 // get rx data buffer
719 pData = GET_OS_PKT_DATAPTR(pRxPacket);
720 pRxWI = (PRXWI_STRUC) pData;
721 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
724 RxCell.pRxWI = pRxWI;
725 RxCell.pHeader = pHeader;
726 RxCell.pRxPacket = pRxPacket;
727 RxCell.pData = (UCHAR *) pHeader;
728 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
731 // Increase Total receive byte counter after real data received no mater any error or not
732 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
733 pAd->RalinkCounters.RxCount ++;
735 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
737 if (pRxWI->MPDUtotalByteCount < 14)
738 Status = NDIS_STATUS_FAILURE;
742 send_monitor_packets(pAd, &RxCell);
745 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
747 // Check for all RxD errors
748 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
750 // Handle the received frame
751 if (Status == NDIS_STATUS_SUCCESS)
753 switch (pHeader->FC.Type)
755 // CASE I, receive a DATA frame
758 // process DATA frame
759 STAHandleRxDataFrame(pAd, &RxCell);
762 // CASE II, receive a MGMT frame
765 STAHandleRxMgmtFrame(pAd, &RxCell);
768 // CASE III. receive a CNTL frame
771 STAHandleRxControlFrame(pAd, &RxCell);
774 // discard other type
776 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
782 pAd->Counters8023.RxErrors++;
783 // discard this frame
784 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
789 // fRTMP_PS_GO_TO_SLEEP_NOW is set if receiving beacon.
790 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW) && (INFRA_ON(pAd)))
792 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
793 AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp);
801 ========================================================================
805 pAd Pointer to our adapter
807 IRQL = DISPATCH_LEVEL
809 ========================================================================
811 VOID RTMPHandleTwakeupInterrupt(
812 IN PRTMP_ADAPTER pAd)
815 AsicForceWakeup(pAd, DOT11POWERSAVE);
818 AsicForceWakeup(pAd, FALSE);
823 ========================================================================
825 Early checking and OS-depened parsing for Tx packet send to our STA driver.
828 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
829 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
830 UINT NumberOfPackets Number of packet in packet array.
836 This function do early checking and classification for send-out packet.
837 You only can put OS-depened & STA related code in here.
838 ========================================================================
841 IN NDIS_HANDLE MiniportAdapterContext,
842 IN PPNDIS_PACKET ppPacketArray,
843 IN UINT NumberOfPackets)
846 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
847 PNDIS_PACKET pPacket;
848 BOOLEAN allowToSend = FALSE;
851 for (Index = 0; Index < NumberOfPackets; Index++)
853 pPacket = ppPacketArray[Index];
857 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
858 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
859 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
861 // Drop send request since hardware is in reset state
864 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
866 // Drop send request since there are no physical connection yet
871 // Record that orignal packet source is from NDIS layer,so that
872 // later on driver knows how to release this NDIS PACKET
873 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
874 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
875 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
876 pAd->RalinkCounters.PendingNdisPacketCount++;
882 if (allowToSend == TRUE)
883 STASendPacket(pAd, pPacket);
885 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
888 // Dequeue outgoing frames from TxSwQueue[] and process it
889 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
895 ========================================================================
897 This routine is used to do packet parsing and classification for Tx packet
898 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
902 pAd Pointer to our adapter
903 pPacket Pointer to send packet
906 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
907 NDIS_STATUS_FAILURE If failed to do en-queue.
910 You only can put OS-indepened & STA related code in here.
911 ========================================================================
913 NDIS_STATUS STASendPacket(
914 IN PRTMP_ADAPTER pAd,
915 IN PNDIS_PACKET pPacket)
917 PACKET_INFO PacketInfo;
922 UCHAR QueIdx, UserPriority;
923 MAC_TABLE_ENTRY *pEntry = NULL;
924 unsigned int IrqFlags;
928 // Prepare packet information structure for buffer descriptor
929 // chained within a single NDIS packet.
930 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
932 if (pSrcBufVA == NULL)
934 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
935 // Resourece is low, system did not allocate virtual address
936 // return NDIS_STATUS_FAILURE directly to upper layer
937 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
938 return NDIS_STATUS_FAILURE;
944 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
945 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
946 return (NDIS_STATUS_FAILURE);
949 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
950 // Note multicast packets in adhoc also use BSSID_WCID index.
955 pEntry = &pAd->MacTab.Content[BSSID_WCID];
956 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
957 Rate = pAd->CommonCfg.TxRate;
960 else if (ADHOC_ON(pAd))
962 if (*pSrcBufVA & 0x01)
964 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
965 pEntry = &pAd->MacTab.Content[MCAST_WCID];
969 pEntry = MacTableLookup(pAd, pSrcBufVA);
971 Rate = pAd->CommonCfg.TxRate;
977 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
978 // Resourece is low, system did not allocate virtual address
979 // return NDIS_STATUS_FAILURE directly to upper layer
980 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
981 return NDIS_STATUS_FAILURE;
987 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
991 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
992 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
993 RTMPCheckEtherType(pAd, pPacket);
998 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
1000 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1001 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1002 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1003 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1004 || (pAd->StaCfg.IEEE8021X == TRUE)
1006 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1007 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1010 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1011 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1013 return (NDIS_STATUS_FAILURE);
1017 // STEP 1. Decide number of fragments required to deliver this MSDU.
1018 // The estimation here is not very accurate because difficult to
1019 // take encryption overhead into consideration here. The result
1020 // "NumberOfFrag" is then just used to pre-check if enough free
1021 // TXD are available to hold this MSDU.
1024 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1026 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1027 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1028 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1029 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1030 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1031 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1034 // The calculated "NumberOfFrag" is a rough estimation because of various
1035 // encryption/encapsulation overhead not taken into consideration. This number is just
1036 // used to make sure enough free TXD are available before fragmentation takes place.
1037 // In case the actual required number of fragments of an NDIS packet
1038 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1039 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1040 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1041 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1043 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1044 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1045 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1046 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1052 // Save fragment number to Ndis packet reserved field
1053 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1056 // STEP 2. Check the requirement of RTS:
1057 // If multiple fragment required, RTS is required only for the first fragment
1058 // if the fragment size large than RTS threshold
1059 // For RT28xx, Let ASIC send RTS/CTS
1060 RTMP_SET_PACKET_RTS(pPacket, 0);
1061 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1064 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1069 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1072 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1073 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1077 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1080 // get Ethernet protocol field
1081 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1082 if (Protocol <= 1500)
1084 // get Ethernet protocol field from LLC/SNAP
1085 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1088 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1092 // always AC_BE for non-IP packet
1093 if (Protocol != 0x0800)
1097 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1100 // return AC_BE if packet is not IPv4
1101 if ((Byte0 & 0xf0) != 0x40)
1105 UserPriority = (Byte1 & 0xe0) >> 5;
1106 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1108 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1109 // TODO: downgrade UP & QueIdx before passing ACM
1110 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1118 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1122 // Make sure SendTxWait queue resource won't be used by other threads
1123 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1124 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1126 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1127 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1129 return NDIS_STATUS_FAILURE;
1133 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1135 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1137 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1139 (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1145 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1146 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1147 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1148 // For IOT compatibility, if
1149 // 1. It is Ralink chip or
1150 // 2. It is OPEN or AES mode,
1151 // then BA session can be bulit.
1152 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1153 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1156 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1160 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1161 return NDIS_STATUS_SUCCESS;
1166 ========================================================================
1168 Routine Description:
1169 This subroutine will scan through releative ring descriptor to find
1170 out avaliable free ring descriptor and compare with request size.
1173 pAd Pointer to our adapter
1174 QueIdx Selected TX Ring
1177 NDIS_STATUS_FAILURE Not enough free descriptor
1178 NDIS_STATUS_SUCCESS Enough free descriptor
1180 IRQL = PASSIVE_LEVEL
1181 IRQL = DISPATCH_LEVEL
1185 ========================================================================
1190 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1191 If no frame need to send, go to sleep, else, still wake up.
1194 NDIS_STATUS RTMPFreeTXDRequest(
1195 IN PRTMP_ADAPTER pAd,
1197 IN UCHAR NumberRequired,
1198 IN PUCHAR FreeNumberIs)
1201 ULONG FreeNumber = 0;
1203 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1205 unsigned long IrqFlags;
1206 HT_TX_CONTEXT *pHTTXContext;
1217 if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1218 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1220 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1222 if (FreeNumber >= NumberRequired)
1223 Status = NDIS_STATUS_SUCCESS;
1227 pHTTXContext = &pAd->TxContext[QueIdx];
1228 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1229 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1230 (pHTTXContext->IRPPending == TRUE))
1232 Status = NDIS_STATUS_FAILURE;
1236 Status = NDIS_STATUS_SUCCESS;
1238 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1245 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1246 FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1248 FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1250 if (FreeNumber >= NumberRequired)
1251 Status = NDIS_STATUS_SUCCESS;
1254 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1255 Status = NDIS_STATUS_FAILURE;
1257 Status = NDIS_STATUS_SUCCESS;
1262 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1266 *FreeNumberIs = (UCHAR)FreeNumber;
1274 VOID RTMPSendDisassociationFrame(
1275 IN PRTMP_ADAPTER pAd)
1279 VOID RTMPSendNullFrame(
1280 IN PRTMP_ADAPTER pAd,
1282 IN BOOLEAN bQosNull)
1284 UCHAR NullFrame[48];
1286 PHEADER_802_11 pHeader_802_11;
1288 // WPA 802.1x secured port control
1289 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1290 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1291 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1292 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1293 || (pAd->StaCfg.IEEE8021X == TRUE)
1295 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1300 NdisZeroMemory(NullFrame, 48);
1301 Length = sizeof(HEADER_802_11);
1303 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1305 pHeader_802_11->FC.Type = BTYPE_DATA;
1306 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1307 pHeader_802_11->FC.ToDs = 1;
1308 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1309 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1310 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1312 if (pAd->CommonCfg.bAPSDForcePowerSave)
1314 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1318 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1320 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1323 pHeader_802_11->Sequence = pAd->Sequence;
1325 // Prepare QosNull function frame
1328 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1330 // copy QOS control bytes
1331 NullFrame[Length] = 0;
1332 NullFrame[Length+1] = 0;
1333 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1336 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1340 // IRQL = DISPATCH_LEVEL
1341 VOID RTMPSendRTSFrame(
1342 IN PRTMP_ADAPTER pAd,
1344 IN unsigned int NextMpduSize,
1347 IN USHORT AckDuration,
1355 // --------------------------------------------------------
1356 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1357 // Find the WPA key, either Group or Pairwise Key
1358 // LEAP + TKIP also use WPA key.
1359 // --------------------------------------------------------
1360 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1361 // In Cisco CCX 2.0 Leap Authentication
1362 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1363 // Instead of the SharedKey, SharedKey Length may be Zero.
1364 VOID STAFindCipherAlgorithm(
1365 IN PRTMP_ADAPTER pAd,
1368 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1369 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1370 UCHAR KeyIdx = 0xff;
1372 PCIPHER_KEY pKey = NULL;
1374 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1378 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1379 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1381 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1383 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1385 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1387 // 4-way handshaking frame must be clear
1388 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1389 (pAd->SharedKey[BSS0][0].KeyLen))
1391 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1395 else if (Cipher == Ndis802_11Encryption1Enabled)
1397 KeyIdx = pAd->StaCfg.DefaultKeyId;
1399 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1400 (Cipher == Ndis802_11Encryption3Enabled))
1402 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1403 KeyIdx = pAd->StaCfg.DefaultKeyId;
1404 else if (pAd->SharedKey[BSS0][0].KeyLen)
1407 KeyIdx = pAd->StaCfg.DefaultKeyId;
1411 CipherAlg = CIPHER_NONE;
1412 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1413 CipherAlg = CIPHER_NONE;
1414 else if ( pAd->StaCfg.WpaSupplicantUP &&
1415 (Cipher == Ndis802_11Encryption1Enabled) &&
1416 (pAd->StaCfg.IEEE8021X == TRUE) &&
1417 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1418 CipherAlg = CIPHER_NONE;
1421 //Header_802_11.FC.Wep = 1;
1422 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1423 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1427 pTxBlk->CipherAlg = CipherAlg;
1428 pTxBlk->pKey = pKey;
1432 VOID STABuildCommon802_11Header(
1433 IN PRTMP_ADAPTER pAd,
1436 HEADER_802_11 *pHeader_802_11;
1439 // MAKE A COMMON 802.11 HEADER
1442 // normal wlan header size : 24 octets
1443 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1445 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1447 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1449 pHeader_802_11->FC.FrDs = 0;
1450 pHeader_802_11->FC.Type = BTYPE_DATA;
1451 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1453 if (pTxBlk->pMacEntry)
1455 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1457 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1458 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1463 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1464 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1470 pHeader_802_11->Sequence = pAd->Sequence;
1471 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1474 pHeader_802_11->Frag = 0;
1476 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1482 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1483 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1484 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1485 pHeader_802_11->FC.ToDs = 1;
1488 else if (ADHOC_ON(pAd))
1490 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1491 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1492 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1493 pHeader_802_11->FC.ToDs = 0;
1497 if (pTxBlk->CipherAlg != CIPHER_NONE)
1498 pHeader_802_11->FC.Wep = 1;
1500 // -----------------------------------------------------------------
1501 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1502 // -----------------------------------------------------------------
1503 if (pAd->CommonCfg.bAPSDForcePowerSave)
1504 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1506 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1509 VOID STABuildCache802_11Header(
1510 IN RTMP_ADAPTER *pAd,
1514 MAC_TABLE_ENTRY *pMacEntry;
1515 PHEADER_802_11 pHeader80211;
1517 pHeader80211 = (PHEADER_802_11)pHeader;
1518 pMacEntry = pTxBlk->pMacEntry;
1521 // Update the cached 802.11 HEADER
1524 // normal wlan header size : 24 octets
1525 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1528 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1531 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1532 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1535 // The addr3 of normal packet send from DS is Dest Mac address.
1537 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1539 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1542 // -----------------------------------------------------------------
1543 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1544 // -----------------------------------------------------------------
1545 if (pAd->CommonCfg.bAPSDForcePowerSave)
1546 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1548 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1551 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1552 IN RTMP_ADAPTER *pAd,
1555 PUCHAR pHeaderBufPtr;
1556 HEADER_802_11 *pHeader_802_11;
1557 PNDIS_PACKET pNextPacket;
1559 PQUEUE_ENTRY pQEntry;
1561 STAFindCipherAlgorithm(pAd, pTxBlk);
1562 STABuildCommon802_11Header(pAd, pTxBlk);
1565 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1566 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1568 // steal "order" bit to mark "aggregation"
1569 pHeader_802_11->FC.Order = 1;
1571 // skip common header
1572 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1574 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1577 // build QOS Control bytes
1579 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1581 *(pHeaderBufPtr+1) = 0;
1583 pTxBlk->MpduHeaderLen += 2;
1586 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1587 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1588 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1589 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1591 // For RA Aggregation,
1592 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1593 pQEntry = pTxBlk->TxPacketList.Head;
1594 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1595 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1596 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1597 nextBufLen -= LENGTH_802_1Q;
1599 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1600 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1603 pTxBlk->MpduHeaderLen += 2;
1605 return pHeaderBufPtr;
1609 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1610 IN RTMP_ADAPTER *pAd,
1613 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1614 HEADER_802_11 *pHeader_802_11;
1617 STAFindCipherAlgorithm(pAd, pTxBlk);
1618 STABuildCommon802_11Header(pAd, pTxBlk);
1620 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1621 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1623 // skip common header
1624 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1627 // build QOS Control bytes
1629 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1634 *pHeaderBufPtr |= 0x80;
1636 *(pHeaderBufPtr+1) = 0;
1638 pTxBlk->MpduHeaderLen += 2;
1640 //pSaveBufPtr = pHeaderBufPtr;
1643 // padding at front of LLC header
1644 // LLC header should locate at 4-octets aligment
1646 // @@@ MpduHeaderLen excluding padding @@@
1648 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1649 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1650 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1652 return pHeaderBufPtr;
1657 VOID STA_AMPDU_Frame_Tx(
1658 IN PRTMP_ADAPTER pAd,
1661 HEADER_802_11 *pHeader_802_11;
1662 PUCHAR pHeaderBufPtr;
1664 MAC_TABLE_ENTRY *pMacEntry;
1666 PQUEUE_ENTRY pQEntry;
1670 while(pTxBlk->TxPacketList.Head)
1672 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1673 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1674 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1676 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1680 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1682 pMacEntry = pTxBlk->pMacEntry;
1683 if (pMacEntry->isCached)
1685 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1686 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1687 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1688 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1692 STAFindCipherAlgorithm(pAd, pTxBlk);
1693 STABuildCommon802_11Header(pAd, pTxBlk);
1695 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1699 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1701 // skip common header
1702 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1705 // build QOS Control bytes
1707 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1708 *(pHeaderBufPtr+1) = 0;
1710 pTxBlk->MpduHeaderLen += 2;
1714 // HTC control filed following QoS field
1716 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1718 if (pMacEntry->isCached == FALSE)
1721 pHeader_802_11->FC.Order = 1;
1723 NdisZeroMemory(pHeaderBufPtr, 4);
1724 *(pHeaderBufPtr+3) |= 0x80;
1727 pTxBlk->MpduHeaderLen += 4;
1730 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1731 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1733 // skip 802.3 header
1734 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1735 pTxBlk->SrcBufLen -= LENGTH_802_3;
1740 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1741 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1745 // padding at front of LLC header
1746 // LLC header should locate at 4-octets aligment
1748 // @@@ MpduHeaderLen excluding padding @@@
1750 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1751 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1752 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1757 // Insert LLC-SNAP encapsulation - 8 octets
1759 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1760 if (pTxBlk->pExtraLlcSnapEncap)
1762 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1764 // get 2 octets (TypeofLen)
1765 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1767 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1772 if (pMacEntry->isCached)
1774 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1778 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1780 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1781 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1782 pMacEntry->isCached = TRUE;
1785 // calculate Transmitted AMPDU count and ByteCount
1787 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1788 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1791 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1793 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1799 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1801 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1803 pAd->RalinkCounters.KickTxCount++;
1804 pAd->RalinkCounters.OneSecTxDoneCount++;
1810 VOID STA_AMSDU_Frame_Tx(
1811 IN PRTMP_ADAPTER pAd,
1814 PUCHAR pHeaderBufPtr;
1816 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1817 USHORT totalMPDUSize=0;
1818 UCHAR *subFrameHeader;
1820 USHORT FirstTx = 0, LastTxIdx = 0;
1823 PQUEUE_ENTRY pQEntry;
1828 ASSERT((pTxBlk->TxPacketList.Number > 1));
1830 while(pTxBlk->TxPacketList.Head)
1832 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1833 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1834 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1836 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1840 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1842 // skip 802.3 header
1843 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1844 pTxBlk->SrcBufLen -= LENGTH_802_3;
1849 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1850 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1855 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1857 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1858 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1862 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1863 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1864 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1865 pHeaderBufPtr += padding;
1866 pTxBlk->MpduHeaderLen = padding;
1871 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1873 subFrameHeader = pHeaderBufPtr;
1874 subFramePayloadLen = pTxBlk->SrcBufLen;
1876 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1879 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1880 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1884 // Insert LLC-SNAP encapsulation - 8 octets
1886 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1888 subFramePayloadLen = pTxBlk->SrcBufLen;
1890 if (pTxBlk->pExtraLlcSnapEncap)
1892 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1894 // get 2 octets (TypeofLen)
1895 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1897 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1898 subFramePayloadLen += LENGTH_802_1_H;
1901 // update subFrame Length field
1902 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1903 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1905 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1908 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1910 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1914 pAd->RalinkCounters.KickTxCount++;
1915 pAd->RalinkCounters.OneSecTxDoneCount++;
1917 // calculate Transmitted AMSDU Count and ByteCount
1919 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1920 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1925 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1926 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1932 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1934 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1937 VOID STA_Legacy_Frame_Tx(
1938 IN PRTMP_ADAPTER pAd,
1941 HEADER_802_11 *pHeader_802_11;
1942 PUCHAR pHeaderBufPtr;
1945 PQUEUE_ENTRY pQEntry;
1950 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1951 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1952 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1954 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1958 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1960 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1963 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1964 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1966 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1968 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1970 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1971 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1973 STAFindCipherAlgorithm(pAd, pTxBlk);
1974 STABuildCommon802_11Header(pAd, pTxBlk);
1977 // skip 802.3 header
1978 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1979 pTxBlk->SrcBufLen -= LENGTH_802_3;
1984 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1985 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1988 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1989 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1991 // skip common header
1992 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1994 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1997 // build QOS Control bytes
1999 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2000 *(pHeaderBufPtr+1) = 0;
2002 pTxBlk->MpduHeaderLen += 2;
2005 // The remaining content of MPDU header should locate at 4-octets aligment
2006 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2007 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2008 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2013 // Insert LLC-SNAP encapsulation - 8 octets
2016 // if original Ethernet frame contains no LLC/SNAP,
2017 // then an extra LLC/SNAP encap is required
2019 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2020 if (pTxBlk->pExtraLlcSnapEncap)
2024 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2027 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2028 // get 2 octets (TypeofLen)
2029 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2031 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2038 // use Wcid as Key Index
2041 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2043 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2045 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2047 pAd->RalinkCounters.KickTxCount++;
2048 pAd->RalinkCounters.OneSecTxDoneCount++;
2054 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2056 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2060 VOID STA_ARalink_Frame_Tx(
2061 IN PRTMP_ADAPTER pAd,
2064 PUCHAR pHeaderBufPtr;
2066 USHORT totalMPDUSize=0;
2067 USHORT FirstTx, LastTxIdx;
2070 PQUEUE_ENTRY pQEntry;
2075 ASSERT((pTxBlk->TxPacketList.Number== 2));
2078 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2079 while(pTxBlk->TxPacketList.Head)
2081 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2082 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2084 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2086 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2090 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2092 // skip 802.3 header
2093 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2094 pTxBlk->SrcBufLen -= LENGTH_802_3;
2099 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2100 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2104 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2106 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2108 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2109 // will be updated after final frame was handled.
2110 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2114 // Insert LLC-SNAP encapsulation - 8 octets
2116 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2118 if (pTxBlk->pExtraLlcSnapEncap)
2120 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2122 // get 2 octets (TypeofLen)
2123 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2125 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2129 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2131 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2132 pTxBlk->MpduHeaderLen = 0;
2134 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2135 // DA(6)+SA(6)+FrameType(2)
2136 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2137 pHeaderBufPtr += 12;
2138 // get 2 octets (TypeofLen)
2139 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2141 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2144 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2146 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2148 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2150 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2154 pAd->RalinkCounters.OneSecTxAggregationCount++;
2155 pAd->RalinkCounters.KickTxCount++;
2156 pAd->RalinkCounters.OneSecTxDoneCount++;
2160 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2161 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2167 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2169 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2174 VOID STA_Fragment_Frame_Tx(
2175 IN RTMP_ADAPTER *pAd,
2178 HEADER_802_11 *pHeader_802_11;
2179 PUCHAR pHeaderBufPtr;
2182 PACKET_INFO PacketInfo;
2183 USHORT EncryptionOverhead = 0;
2184 UINT32 FreeMpduSize, SrcRemainingBytes;
2188 PQUEUE_ENTRY pQEntry;
2193 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2194 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2195 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2197 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2201 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2202 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2204 STAFindCipherAlgorithm(pAd, pTxBlk);
2205 STABuildCommon802_11Header(pAd, pTxBlk);
2207 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2209 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2210 if (pTxBlk->pPacket == NULL)
2212 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2215 // skip 802.3 header
2216 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2217 pTxBlk->SrcBufLen -= LENGTH_802_3;
2223 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2224 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2227 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2228 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2231 // skip common header
2232 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2234 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2237 // build QOS Control bytes
2239 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2241 *(pHeaderBufPtr+1) = 0;
2243 pTxBlk->MpduHeaderLen += 2;
2247 // padding at front of LLC header
2248 // LLC header should locate at 4-octets aligment
2250 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2251 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2252 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2257 // Insert LLC-SNAP encapsulation - 8 octets
2260 // if original Ethernet frame contains no LLC/SNAP,
2261 // then an extra LLC/SNAP encap is required
2263 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2264 if (pTxBlk->pExtraLlcSnapEncap)
2268 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2271 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2272 // get 2 octets (TypeofLen)
2273 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2275 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2279 // If TKIP is used and fragmentation is required. Driver has to
2280 // append TKIP MIC at tail of the scatter buffer
2281 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2282 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2285 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2286 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2287 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2288 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2289 pTxBlk->SrcBufLen += 8;
2290 pTxBlk->TotalFrameLen += 8;
2291 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2295 // calcuate the overhead bytes that encryption algorithm may add. This
2296 // affects the calculate of "duration" field
2298 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2299 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2300 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2301 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2302 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2303 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2304 else if (pTxBlk->CipherAlg == CIPHER_AES)
2305 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2307 EncryptionOverhead = 0;
2309 // decide how much time an ACK/CTS frame will consume in the air
2310 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2312 // Init the total payload length of this frame.
2313 SrcRemainingBytes = pTxBlk->SrcBufLen;
2315 pTxBlk->TotalFragNum = 0xff;
2319 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2321 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2323 if (SrcRemainingBytes <= FreeMpduSize)
2324 { // this is the last or only fragment
2326 pTxBlk->SrcBufLen = SrcRemainingBytes;
2328 pHeader_802_11->FC.MoreFrag = 0;
2329 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2331 // Indicate the lower layer that this's the last fragment.
2332 pTxBlk->TotalFragNum = fragNum;
2335 { // more fragment is required
2337 pTxBlk->SrcBufLen = FreeMpduSize;
2339 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2340 pHeader_802_11->FC.MoreFrag = 1;
2341 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2345 pTxBlk->FrameGap = IFS_HTTXOP;
2347 pTxBlk->FrameGap = IFS_SIFS;
2349 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2351 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2353 pAd->RalinkCounters.KickTxCount++;
2354 pAd->RalinkCounters.OneSecTxDoneCount++;
2356 // Update the frame number, remaining size of the NDIS packet payload.
2358 // space for 802.11 header.
2359 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2360 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2363 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2364 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2366 pHeader_802_11->Frag++; // increase Frag #
2368 }while(SrcRemainingBytes > 0);
2373 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2377 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2378 while(_pTxBlk->TxPacketList.Head) \
2380 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2381 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2386 ========================================================================
2388 Routine Description:
2389 Copy frame from waiting queue into relative ring buffer and set
2390 appropriate ASIC register to kick hardware encryption before really
2394 pAd Pointer to our adapter
2395 PNDIS_PACKET Pointer to outgoing Ndis frame
2396 NumberOfFrag Number of fragment required
2401 IRQL = DISPATCH_LEVEL
2405 ========================================================================
2407 NDIS_STATUS STAHardTransmit(
2408 IN PRTMP_ADAPTER pAd,
2412 NDIS_PACKET *pPacket;
2413 PQUEUE_ENTRY pQEntry;
2415 // ---------------------------------------------
2416 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2417 // ---------------------------------------------
2419 ASSERT(pTxBlk->TxPacketList.Number);
2420 if (pTxBlk->TxPacketList.Head == NULL)
2422 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2423 return NDIS_STATUS_FAILURE;
2426 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2428 // ------------------------------------------------------------------
2429 // STEP 1. WAKE UP PHY
2430 // outgoing frame always wakeup PHY to prevent frame lost and
2431 // turn off PSM bit to improve performance
2432 // ------------------------------------------------------------------
2433 // not to change PSM bit, just send this frame out?
2434 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2436 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2438 AsicForceWakeup(pAd, FROM_TX);
2441 AsicForceWakeup(pAd, TRUE);
2445 // It should not change PSM bit, when APSD turn on.
2446 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2447 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2448 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2450 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2451 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2452 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2455 switch (pTxBlk->TxFrameType)
2457 case TX_AMPDU_FRAME:
2458 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2460 case TX_AMSDU_FRAME:
2461 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2463 case TX_LEGACY_FRAME:
2464 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2466 case TX_MCAST_FRAME:
2467 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2469 case TX_RALINK_FRAME:
2470 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2473 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2477 // It should not happened!
2478 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2479 while(pTxBlk->TxPacketList.Number)
2481 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2482 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2484 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2490 return (NDIS_STATUS_SUCCESS);
2494 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2496 unsigned char *word = value;
2497 unsigned int ret = 0;
2500 for(i=0; i < len; i++)
2503 ret ^=(unsigned int) (word[i]) << mod;
2504 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2509 VOID Sta_Announce_or_Forward_802_3_Packet(
2510 IN PRTMP_ADAPTER pAd,
2511 IN PNDIS_PACKET pPacket,
2512 IN UCHAR FromWhichBSSID)
2517 announce_802_3_packet(pAd, pPacket);
2522 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);