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;
54 if (pAd->StaCfg.WpaSupplicantUP)
56 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
57 // TBD : process fragmented EAPol frames
59 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
60 if ( pAd->StaCfg.IEEE8021X == TRUE &&
61 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
67 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
68 STA_PORT_SECURED(pAd);
70 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
72 idx = pAd->StaCfg.DesireSharedKeyId;
73 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
74 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
76 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
81 char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
82 NDIS_802_11_WEP keyinfo;
87 NdisZeroMemory(&WepKey, sizeof(WepKey));
88 len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
90 NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
91 pAd->StaCfg.DesireSharedKey[idx].Key,
92 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
94 WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
95 WepKey.keyinfo.KeyLength = len;
96 pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
98 pAd->IndicateMediaState = NdisMediaStateConnected;
99 pAd->ExtraInfo = GENERAL_LINK_UP;
100 // need to enqueue cmd to thread
101 RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
103 // For Preventing ShardKey Table is cleared by remove key procedure.
104 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
105 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
106 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
107 pAd->StaCfg.DesireSharedKey[idx].Key,
108 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
113 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
119 // Special DATA frame that has to pass to MLME
120 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
121 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
123 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
124 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
125 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
126 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
130 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
135 VOID STARxDataFrameAnnounce(
136 IN PRTMP_ADAPTER pAd,
137 IN MAC_TABLE_ENTRY *pEntry,
139 IN UCHAR FromWhichBSSID)
143 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
147 // drop all non-EAP DATA frame before
148 // this client's Port-Access-Control is secured
149 if (pRxBlk->pHeader->FC.Wep)
151 // unsupported cipher suite
152 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
155 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
161 // encryption in-use but receive a non-EAPOL clear text frame, drop it
162 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
163 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
166 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
171 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
172 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
174 // Normal legacy, AMPDU or AMSDU
175 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
181 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
186 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
188 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
190 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
194 // Determin the destination of the EAP frame
195 // to WPA state machine or upper layer
196 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
202 // For TKIP frame, calculate the MIC value
203 BOOLEAN STACheckTkipMICValue(
204 IN PRTMP_ADAPTER pAd,
205 IN MAC_TABLE_ENTRY *pEntry,
208 PHEADER_802_11 pHeader = pRxBlk->pHeader;
209 UCHAR *pData = pRxBlk->pData;
210 USHORT DataSize = pRxBlk->DataSize;
211 UCHAR UserPriority = pRxBlk->UserPriority;
215 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
217 pDA = pHeader->Addr1;
218 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
220 pSA = pHeader->Addr3;
224 pSA = pHeader->Addr2;
227 if (RTMPTkipCompareMICValue(pAd,
235 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
237 if (pAd->StaCfg.WpaSupplicantUP)
239 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
243 RTMPReportMicError(pAd, pWpaKey);
247 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
256 // All Rx routines use RX_BLK structure to hande rx events
257 // It is very important to build pRxBlk attributes
258 // 1. pHeader pointer to 802.11 Header
259 // 2. pData pointer to payload including LLC (just skip Header)
260 // 3. set payload size including LLC to DataSize
261 // 4. set some flags with RX_BLK_SET_FLAG()
263 VOID STAHandleRxDataFrame(
264 IN PRTMP_ADAPTER pAd,
267 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
268 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
269 PHEADER_802_11 pHeader = pRxBlk->pHeader;
270 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
271 BOOLEAN bFragment = FALSE;
272 MAC_TABLE_ENTRY *pEntry = NULL;
273 UCHAR FromWhichBSSID = BSS0;
274 UCHAR UserPriority = 0;
277 // before LINK UP, all DATA frames are rejected
278 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
281 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
285 // Drop not my BSS frames
286 if (pRxD->MyBss == 0)
290 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
295 pAd->RalinkCounters.RxCountSinceLastNULL++;
296 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
299 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
302 pData = (PUCHAR)pHeader + LENGTH_802_11;
303 if ((*pData >> 4) & 0x01)
305 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
306 pAd->CommonCfg.bInServicePeriod = FALSE;
308 // Force driver to fall into sleep mode when rcv EOSP frame
309 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
311 USHORT TbttNumToNextWakeUp;
312 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
315 NdisGetSystemUpTime(&Now);
316 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
318 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
319 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
320 TbttNumToNextWakeUp = NextDtim;
322 MlmeSetPsmBit(pAd, PWR_SAVE);
323 // if WMM-APSD is failed, try to disable following line
324 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
328 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
330 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
334 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
335 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
338 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
342 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
346 // Infrastructure mode, check address 2 for BSSID
347 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
349 // Receive frame not my BSSID
351 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
355 else // Ad-Hoc mode or Not associated
357 // Ad-Hoc mode, check address 3 for BSSID
358 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
360 // Receive frame not my BSSID
362 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
370 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
372 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
376 // 1. release packet if infra mode
377 // 2. new a pEntry if ad-hoc mode
378 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
385 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
386 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
389 // check Atheros Client
390 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
392 pEntry->bIAmBadAtheros = TRUE;
393 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
394 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
395 if (!STA_AES_ON(pAd))
397 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
402 pRxBlk->pData = (UCHAR *)pHeader;
405 // update RxBlk->pData, DataSize
406 // 802.11 Header, QOS, HTC, Hw Padding
409 // 1. skip 802.11 HEADER
411 pRxBlk->pData += LENGTH_802_11;
412 pRxBlk->DataSize -= LENGTH_802_11;
416 if (pHeader->FC.SubType & 0x08)
418 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
419 UserPriority = *(pRxBlk->pData) & 0x0f;
420 // bit 7 in QoS Control field signals the HT A-MSDU format
421 if ((*pRxBlk->pData) & 0x80)
423 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
426 // skip QOS contorl field
428 pRxBlk->DataSize -=2;
430 pRxBlk->UserPriority = UserPriority;
432 // 3. Order bit: A-Ralink or HTC+
433 if (pHeader->FC.Order)
435 #ifdef AGGREGATION_SUPPORT
436 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
438 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
443 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
444 // skip HTC contorl field
446 pRxBlk->DataSize -= 4;
450 // 4. skip HW padding
453 // just move pData pointer
454 // because DataSize excluding HW padding
455 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
461 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
465 // Case I Process Broadcast & Multicast data frame
467 if (pRxD->Bcast || pRxD->Mcast)
469 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
471 // Drop Mcast/Bcast frame with fragment bit on
472 if (pHeader->FC.MoreFrag)
475 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
479 // Filter out Bcast frame which AP relayed for us
480 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
483 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
487 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
492 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
496 pEntry = MacTableLookup(pAd, pHeader->Addr2);
498 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
502 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
504 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
505 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
507 pAd->RalinkCounters.OneSecRxOkDataCnt++;
510 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
512 // re-assemble the fragmented packets
513 // return complete frame (pRxPacket) or NULL
515 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
520 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
522 // process complete frame
523 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
526 pRxBlk->DataSize -= 8;
528 // For TKIP frame, calculate the MIC value
529 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
535 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
541 // because RTMPDeFragmentDataFrame() will release rx packet,
542 // if packet is fragmented
549 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
552 VOID STAHandleRxMgmtFrame(
553 IN PRTMP_ADAPTER pAd,
556 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
557 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
558 PHEADER_802_11 pHeader = pRxBlk->pHeader;
559 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
564 // We should collect RSSI not only U2M data but also my beacon
565 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))
566 && (pAd->RxAnt.EvaluatePeriod == 0))
568 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
570 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
571 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
575 // collect rssi information for antenna diversity
576 if (pAd->NicConfig2.field.AntDiversity)
578 if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))))
580 COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxWI->RSSI0, RSSI_0), 0); //Note: RSSI2 not used on RT73
581 pAd->StaCfg.NumOfAvgRssiSample ++;
586 // First check the size, it MUST not exceed the mlme queue size
587 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
589 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
593 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
594 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
597 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
600 VOID STAHandleRxControlFrame(
601 IN PRTMP_ADAPTER pAd,
604 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
605 PHEADER_802_11 pHeader = pRxBlk->pHeader;
606 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
608 switch (pHeader->FC.SubType)
610 case SUBTYPE_BLOCK_ACK_REQ:
612 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
615 case SUBTYPE_BLOCK_ACK:
621 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
626 ========================================================================
629 Process RxDone interrupt, running in DPC level
632 pAd Pointer to our adapter
637 IRQL = DISPATCH_LEVEL
640 This routine has to maintain Rx ring read pointer.
641 Need to consider QOS DATA format when converting to 802.3
642 ========================================================================
644 BOOLEAN STARxDoneInterruptHandle(
645 IN PRTMP_ADAPTER pAd,
649 UINT32 RxProcessed, RxPending;
650 BOOLEAN bReschedule = FALSE;
651 RT28XX_RXD_STRUC *pRxD;
654 PNDIS_PACKET pRxPacket;
655 PHEADER_802_11 pHeader;
658 RxProcessed = RxPending = 0;
660 // process whole rx ring
664 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
665 fRTMP_ADAPTER_RESET_IN_PROGRESS |
666 fRTMP_ADAPTER_HALT_IN_PROGRESS |
667 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
668 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
674 RxProcessed ++; // test
676 // 1. allocate a new data packet into rx ring to replace received packet
677 // then processing the received packet
678 // 2. the callee must take charge of release of packet
679 // 3. As far as driver is concerned ,
680 // the rx packet must
681 // a. be indicated to upper layer or
682 // b. be released if it is discarded
683 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
684 if (pRxPacket == NULL)
686 // no more packet to process
690 // get rx ring descriptor
691 pRxD = &(RxCell.RxD);
692 // get rx data buffer
693 pData = GET_OS_PKT_DATAPTR(pRxPacket);
694 pRxWI = (PRXWI_STRUC) pData;
695 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
698 RxCell.pRxWI = pRxWI;
699 RxCell.pHeader = pHeader;
700 RxCell.pRxPacket = pRxPacket;
701 RxCell.pData = (UCHAR *) pHeader;
702 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
705 // Increase Total receive byte counter after real data received no mater any error or not
706 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
707 pAd->RalinkCounters.RxCount ++;
709 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
711 if (pRxWI->MPDUtotalByteCount < 14)
712 Status = NDIS_STATUS_FAILURE;
716 send_monitor_packets(pAd, &RxCell);
719 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
721 // Check for all RxD errors
722 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
724 // Handle the received frame
725 if (Status == NDIS_STATUS_SUCCESS)
727 switch (pHeader->FC.Type)
729 // CASE I, receive a DATA frame
732 // process DATA frame
733 STAHandleRxDataFrame(pAd, &RxCell);
736 // CASE II, receive a MGMT frame
739 STAHandleRxMgmtFrame(pAd, &RxCell);
742 // CASE III. receive a CNTL frame
745 STAHandleRxControlFrame(pAd, &RxCell);
748 // discard other type
750 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
756 pAd->Counters8023.RxErrors++;
757 // discard this frame
758 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
766 ========================================================================
770 pAd Pointer to our adapter
772 IRQL = DISPATCH_LEVEL
774 ========================================================================
776 VOID RTMPHandleTwakeupInterrupt(
777 IN PRTMP_ADAPTER pAd)
779 AsicForceWakeup(pAd, FALSE);
783 ========================================================================
785 Early checking and OS-depened parsing for Tx packet send to our STA driver.
788 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
789 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
790 UINT NumberOfPackets Number of packet in packet array.
796 This function do early checking and classification for send-out packet.
797 You only can put OS-depened & STA related code in here.
798 ========================================================================
801 IN NDIS_HANDLE MiniportAdapterContext,
802 IN PPNDIS_PACKET ppPacketArray,
803 IN UINT NumberOfPackets)
806 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
807 PNDIS_PACKET pPacket;
808 BOOLEAN allowToSend = FALSE;
811 for (Index = 0; Index < NumberOfPackets; Index++)
813 pPacket = ppPacketArray[Index];
818 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
819 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
820 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
822 // Drop send request since hardware is in reset state
825 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
827 // Drop send request since there are no physical connection yet
832 // Record that orignal packet source is from NDIS layer,so that
833 // later on driver knows how to release this NDIS PACKET
834 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
835 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
836 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
837 pAd->RalinkCounters.PendingNdisPacketCount++;
843 if (allowToSend == TRUE)
844 STASendPacket(pAd, pPacket);
846 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
849 // Dequeue outgoing frames from TxSwQueue[] and process it
850 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
856 ========================================================================
858 This routine is used to do packet parsing and classification for Tx packet
859 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
863 pAd Pointer to our adapter
864 pPacket Pointer to send packet
867 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
868 NDIS_STATUS_FAILURE If failed to do en-queue.
871 You only can put OS-indepened & STA related code in here.
872 ========================================================================
874 NDIS_STATUS STASendPacket(
875 IN PRTMP_ADAPTER pAd,
876 IN PNDIS_PACKET pPacket)
878 PACKET_INFO PacketInfo;
883 UCHAR QueIdx, UserPriority;
884 MAC_TABLE_ENTRY *pEntry = NULL;
885 unsigned int IrqFlags;
889 // Prepare packet information structure for buffer descriptor
890 // chained within a single NDIS packet.
891 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
893 if (pSrcBufVA == NULL)
895 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
896 // Resourece is low, system did not allocate virtual address
897 // return NDIS_STATUS_FAILURE directly to upper layer
898 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
899 return NDIS_STATUS_FAILURE;
905 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
906 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
907 return (NDIS_STATUS_FAILURE);
910 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
911 // Note multicast packets in adhoc also use BSSID_WCID index.
916 pEntry = &pAd->MacTab.Content[BSSID_WCID];
917 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
918 Rate = pAd->CommonCfg.TxRate;
921 else if (ADHOC_ON(pAd))
923 if (*pSrcBufVA & 0x01)
925 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
926 pEntry = &pAd->MacTab.Content[MCAST_WCID];
930 pEntry = MacTableLookup(pAd, pSrcBufVA);
932 Rate = pAd->CommonCfg.TxRate;
938 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
939 // Resourece is low, system did not allocate virtual address
940 // return NDIS_STATUS_FAILURE directly to upper layer
941 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
942 return NDIS_STATUS_FAILURE;
948 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
952 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
953 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
954 RTMPCheckEtherType(pAd, pPacket);
959 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
961 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
962 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
963 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
964 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
965 || (pAd->StaCfg.IEEE8021X == TRUE)
967 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
968 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
971 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
972 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
974 return (NDIS_STATUS_FAILURE);
978 // STEP 1. Decide number of fragments required to deliver this MSDU.
979 // The estimation here is not very accurate because difficult to
980 // take encryption overhead into consideration here. The result
981 // "NumberOfFrag" is then just used to pre-check if enough free
982 // TXD are available to hold this MSDU.
985 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
987 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
988 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
989 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
990 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
991 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
992 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
995 // The calculated "NumberOfFrag" is a rough estimation because of various
996 // encryption/encapsulation overhead not taken into consideration. This number is just
997 // used to make sure enough free TXD are available before fragmentation takes place.
998 // In case the actual required number of fragments of an NDIS packet
999 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1000 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1001 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1002 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1004 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1005 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1006 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1007 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1013 // Save fragment number to Ndis packet reserved field
1014 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1017 // STEP 2. Check the requirement of RTS:
1018 // If multiple fragment required, RTS is required only for the first fragment
1019 // if the fragment size large than RTS threshold
1020 // For RT28xx, Let ASIC send RTS/CTS
1021 RTMP_SET_PACKET_RTS(pPacket, 0);
1022 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1025 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1029 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1030 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1033 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1036 // get Ethernet protocol field
1037 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1038 if (Protocol <= 1500)
1040 // get Ethernet protocol field from LLC/SNAP
1041 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1044 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1048 // always AC_BE for non-IP packet
1049 if (Protocol != 0x0800)
1053 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1056 // return AC_BE if packet is not IPv4
1057 if ((Byte0 & 0xf0) != 0x40)
1061 UserPriority = (Byte1 & 0xe0) >> 5;
1062 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1064 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1065 // TODO: downgrade UP & QueIdx before passing ACM
1066 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1074 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1078 // Make sure SendTxWait queue resource won't be used by other threads
1079 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1080 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1082 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1083 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1085 return NDIS_STATUS_FAILURE;
1089 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1091 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1093 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1096 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1097 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1098 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1099 // For IOT compatibility, if
1100 // 1. It is Ralink chip or
1101 // 2. It is OPEN or AES mode,
1102 // then BA session can be bulit.
1103 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1104 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1107 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1111 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1112 return NDIS_STATUS_SUCCESS;
1117 ========================================================================
1119 Routine Description:
1120 This subroutine will scan through releative ring descriptor to find
1121 out avaliable free ring descriptor and compare with request size.
1124 pAd Pointer to our adapter
1125 QueIdx Selected TX Ring
1128 NDIS_STATUS_FAILURE Not enough free descriptor
1129 NDIS_STATUS_SUCCESS Enough free descriptor
1131 IRQL = PASSIVE_LEVEL
1132 IRQL = DISPATCH_LEVEL
1136 ========================================================================
1141 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1142 If no frame need to send, go to sleep, else, still wake up.
1144 NDIS_STATUS RTMPFreeTXDRequest(
1145 IN PRTMP_ADAPTER pAd,
1147 IN UCHAR NumberRequired,
1148 IN PUCHAR FreeNumberIs)
1150 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1151 unsigned long IrqFlags;
1152 HT_TX_CONTEXT *pHTTXContext;
1162 pHTTXContext = &pAd->TxContext[QueIdx];
1163 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1164 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1165 (pHTTXContext->IRPPending == TRUE))
1167 Status = NDIS_STATUS_FAILURE;
1171 Status = NDIS_STATUS_SUCCESS;
1173 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1178 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1179 Status = NDIS_STATUS_FAILURE;
1181 Status = NDIS_STATUS_SUCCESS;
1185 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1195 VOID RTMPSendDisassociationFrame(
1196 IN PRTMP_ADAPTER pAd)
1200 VOID RTMPSendNullFrame(
1201 IN PRTMP_ADAPTER pAd,
1203 IN BOOLEAN bQosNull)
1205 UCHAR NullFrame[48];
1207 PHEADER_802_11 pHeader_802_11;
1209 // WPA 802.1x secured port control
1210 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1211 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1212 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1213 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1214 || (pAd->StaCfg.IEEE8021X == TRUE)
1216 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1221 NdisZeroMemory(NullFrame, 48);
1222 Length = sizeof(HEADER_802_11);
1224 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1226 pHeader_802_11->FC.Type = BTYPE_DATA;
1227 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1228 pHeader_802_11->FC.ToDs = 1;
1229 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1230 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1231 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1233 if (pAd->CommonCfg.bAPSDForcePowerSave)
1235 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1239 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1241 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1244 pHeader_802_11->Sequence = pAd->Sequence;
1246 // Prepare QosNull function frame
1249 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1251 // copy QOS control bytes
1252 NullFrame[Length] = 0;
1253 NullFrame[Length+1] = 0;
1254 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1257 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1261 // IRQL = DISPATCH_LEVEL
1262 VOID RTMPSendRTSFrame(
1263 IN PRTMP_ADAPTER pAd,
1265 IN unsigned int NextMpduSize,
1268 IN USHORT AckDuration,
1276 // --------------------------------------------------------
1277 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1278 // Find the WPA key, either Group or Pairwise Key
1279 // LEAP + TKIP also use WPA key.
1280 // --------------------------------------------------------
1281 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1282 // In Cisco CCX 2.0 Leap Authentication
1283 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1284 // Instead of the SharedKey, SharedKey Length may be Zero.
1285 VOID STAFindCipherAlgorithm(
1286 IN PRTMP_ADAPTER pAd,
1289 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1290 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1291 UCHAR KeyIdx = 0xff;
1293 PCIPHER_KEY pKey = NULL;
1295 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1299 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1300 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1302 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1304 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1306 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1308 // 4-way handshaking frame must be clear
1309 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1310 (pAd->SharedKey[BSS0][0].KeyLen))
1312 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1316 else if (Cipher == Ndis802_11Encryption1Enabled)
1318 KeyIdx = pAd->StaCfg.DefaultKeyId;
1320 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1321 (Cipher == Ndis802_11Encryption3Enabled))
1323 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1324 KeyIdx = pAd->StaCfg.DefaultKeyId;
1325 else if (pAd->SharedKey[BSS0][0].KeyLen)
1328 KeyIdx = pAd->StaCfg.DefaultKeyId;
1332 CipherAlg = CIPHER_NONE;
1333 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1334 CipherAlg = CIPHER_NONE;
1335 else if ( pAd->StaCfg.WpaSupplicantUP &&
1336 (Cipher == Ndis802_11Encryption1Enabled) &&
1337 (pAd->StaCfg.IEEE8021X == TRUE) &&
1338 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1339 CipherAlg = CIPHER_NONE;
1342 //Header_802_11.FC.Wep = 1;
1343 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1344 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1348 pTxBlk->CipherAlg = CipherAlg;
1349 pTxBlk->pKey = pKey;
1353 VOID STABuildCommon802_11Header(
1354 IN PRTMP_ADAPTER pAd,
1357 HEADER_802_11 *pHeader_802_11;
1360 // MAKE A COMMON 802.11 HEADER
1363 // normal wlan header size : 24 octets
1364 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1366 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1368 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1370 pHeader_802_11->FC.FrDs = 0;
1371 pHeader_802_11->FC.Type = BTYPE_DATA;
1372 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1374 if (pTxBlk->pMacEntry)
1376 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1378 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1379 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1384 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1385 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1391 pHeader_802_11->Sequence = pAd->Sequence;
1392 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1395 pHeader_802_11->Frag = 0;
1397 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1403 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1404 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1405 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1406 pHeader_802_11->FC.ToDs = 1;
1409 else if (ADHOC_ON(pAd))
1411 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1412 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1413 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1414 pHeader_802_11->FC.ToDs = 0;
1418 if (pTxBlk->CipherAlg != CIPHER_NONE)
1419 pHeader_802_11->FC.Wep = 1;
1421 // -----------------------------------------------------------------
1422 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1423 // -----------------------------------------------------------------
1424 if (pAd->CommonCfg.bAPSDForcePowerSave)
1425 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1427 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1430 VOID STABuildCache802_11Header(
1431 IN RTMP_ADAPTER *pAd,
1435 MAC_TABLE_ENTRY *pMacEntry;
1436 PHEADER_802_11 pHeader80211;
1438 pHeader80211 = (PHEADER_802_11)pHeader;
1439 pMacEntry = pTxBlk->pMacEntry;
1442 // Update the cached 802.11 HEADER
1445 // normal wlan header size : 24 octets
1446 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1449 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1452 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1453 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1456 // The addr3 of normal packet send from DS is Dest Mac address.
1458 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1460 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1463 // -----------------------------------------------------------------
1464 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1465 // -----------------------------------------------------------------
1466 if (pAd->CommonCfg.bAPSDForcePowerSave)
1467 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1469 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1472 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1473 IN RTMP_ADAPTER *pAd,
1476 PUCHAR pHeaderBufPtr;
1477 HEADER_802_11 *pHeader_802_11;
1478 PNDIS_PACKET pNextPacket;
1480 PQUEUE_ENTRY pQEntry;
1482 STAFindCipherAlgorithm(pAd, pTxBlk);
1483 STABuildCommon802_11Header(pAd, pTxBlk);
1486 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1487 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1489 // steal "order" bit to mark "aggregation"
1490 pHeader_802_11->FC.Order = 1;
1492 // skip common header
1493 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1495 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1498 // build QOS Control bytes
1500 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1502 *(pHeaderBufPtr+1) = 0;
1504 pTxBlk->MpduHeaderLen += 2;
1507 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1508 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1509 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1510 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1512 // For RA Aggregation,
1513 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1514 pQEntry = pTxBlk->TxPacketList.Head;
1515 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1516 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1517 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1518 nextBufLen -= LENGTH_802_1Q;
1520 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1521 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1524 pTxBlk->MpduHeaderLen += 2;
1526 return pHeaderBufPtr;
1530 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1531 IN RTMP_ADAPTER *pAd,
1534 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1535 HEADER_802_11 *pHeader_802_11;
1538 STAFindCipherAlgorithm(pAd, pTxBlk);
1539 STABuildCommon802_11Header(pAd, pTxBlk);
1541 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1542 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1544 // skip common header
1545 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1548 // build QOS Control bytes
1550 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1555 *pHeaderBufPtr |= 0x80;
1557 *(pHeaderBufPtr+1) = 0;
1559 pTxBlk->MpduHeaderLen += 2;
1561 //pSaveBufPtr = pHeaderBufPtr;
1564 // padding at front of LLC header
1565 // LLC header should locate at 4-octets aligment
1567 // @@@ MpduHeaderLen excluding padding @@@
1569 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1570 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1571 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1573 return pHeaderBufPtr;
1578 VOID STA_AMPDU_Frame_Tx(
1579 IN PRTMP_ADAPTER pAd,
1582 HEADER_802_11 *pHeader_802_11;
1583 PUCHAR pHeaderBufPtr;
1585 MAC_TABLE_ENTRY *pMacEntry;
1587 PQUEUE_ENTRY pQEntry;
1591 while(pTxBlk->TxPacketList.Head)
1593 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1594 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1595 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1597 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1601 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1603 pMacEntry = pTxBlk->pMacEntry;
1604 if (pMacEntry->isCached)
1606 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1607 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1608 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1609 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1613 STAFindCipherAlgorithm(pAd, pTxBlk);
1614 STABuildCommon802_11Header(pAd, pTxBlk);
1616 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1620 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1622 // skip common header
1623 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1626 // build QOS Control bytes
1628 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1629 *(pHeaderBufPtr+1) = 0;
1631 pTxBlk->MpduHeaderLen += 2;
1635 // HTC control filed following QoS field
1637 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1639 if (pMacEntry->isCached == FALSE)
1642 pHeader_802_11->FC.Order = 1;
1644 NdisZeroMemory(pHeaderBufPtr, 4);
1645 *(pHeaderBufPtr+3) |= 0x80;
1648 pTxBlk->MpduHeaderLen += 4;
1651 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1652 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1654 // skip 802.3 header
1655 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1656 pTxBlk->SrcBufLen -= LENGTH_802_3;
1661 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1662 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1666 // padding at front of LLC header
1667 // LLC header should locate at 4-octets aligment
1669 // @@@ MpduHeaderLen excluding padding @@@
1671 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1672 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1673 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1678 // Insert LLC-SNAP encapsulation - 8 octets
1680 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1681 if (pTxBlk->pExtraLlcSnapEncap)
1683 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1685 // get 2 octets (TypeofLen)
1686 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1688 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1693 if (pMacEntry->isCached)
1695 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1699 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1701 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1702 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1703 pMacEntry->isCached = TRUE;
1706 // calculate Transmitted AMPDU count and ByteCount
1708 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1709 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1712 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1714 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1719 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1721 pAd->RalinkCounters.KickTxCount++;
1722 pAd->RalinkCounters.OneSecTxDoneCount++;
1728 VOID STA_AMSDU_Frame_Tx(
1729 IN PRTMP_ADAPTER pAd,
1732 PUCHAR pHeaderBufPtr;
1734 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1735 USHORT totalMPDUSize=0;
1736 UCHAR *subFrameHeader;
1738 USHORT FirstTx = 0, LastTxIdx = 0;
1741 PQUEUE_ENTRY pQEntry;
1746 ASSERT((pTxBlk->TxPacketList.Number > 1));
1748 while(pTxBlk->TxPacketList.Head)
1750 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1751 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1752 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1754 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1758 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1760 // skip 802.3 header
1761 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1762 pTxBlk->SrcBufLen -= LENGTH_802_3;
1767 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1768 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1773 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1775 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1776 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1780 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1781 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1782 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1783 pHeaderBufPtr += padding;
1784 pTxBlk->MpduHeaderLen = padding;
1789 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1791 subFrameHeader = pHeaderBufPtr;
1792 subFramePayloadLen = pTxBlk->SrcBufLen;
1794 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1797 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1798 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1802 // Insert LLC-SNAP encapsulation - 8 octets
1804 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1806 subFramePayloadLen = pTxBlk->SrcBufLen;
1808 if (pTxBlk->pExtraLlcSnapEncap)
1810 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1812 // get 2 octets (TypeofLen)
1813 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1815 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1816 subFramePayloadLen += LENGTH_802_1_H;
1819 // update subFrame Length field
1820 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1821 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1823 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1826 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1828 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1832 pAd->RalinkCounters.KickTxCount++;
1833 pAd->RalinkCounters.OneSecTxDoneCount++;
1835 // calculate Transmitted AMSDU Count and ByteCount
1837 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1838 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1843 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1844 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1849 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1852 VOID STA_Legacy_Frame_Tx(
1853 IN PRTMP_ADAPTER pAd,
1856 HEADER_802_11 *pHeader_802_11;
1857 PUCHAR pHeaderBufPtr;
1860 PQUEUE_ENTRY pQEntry;
1865 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1866 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1867 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1869 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1873 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1875 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1878 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1879 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1881 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1883 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1885 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1886 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1888 STAFindCipherAlgorithm(pAd, pTxBlk);
1889 STABuildCommon802_11Header(pAd, pTxBlk);
1892 // skip 802.3 header
1893 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1894 pTxBlk->SrcBufLen -= LENGTH_802_3;
1899 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1900 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1903 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1904 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1906 // skip common header
1907 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1909 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1912 // build QOS Control bytes
1914 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1915 *(pHeaderBufPtr+1) = 0;
1917 pTxBlk->MpduHeaderLen += 2;
1920 // The remaining content of MPDU header should locate at 4-octets aligment
1921 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1922 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1923 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1928 // Insert LLC-SNAP encapsulation - 8 octets
1931 // if original Ethernet frame contains no LLC/SNAP,
1932 // then an extra LLC/SNAP encap is required
1934 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
1935 if (pTxBlk->pExtraLlcSnapEncap)
1939 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1942 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
1943 // get 2 octets (TypeofLen)
1944 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
1946 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1953 // use Wcid as Key Index
1956 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1958 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1960 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1962 pAd->RalinkCounters.KickTxCount++;
1963 pAd->RalinkCounters.OneSecTxDoneCount++;
1968 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1972 VOID STA_ARalink_Frame_Tx(
1973 IN PRTMP_ADAPTER pAd,
1976 PUCHAR pHeaderBufPtr;
1978 USHORT totalMPDUSize=0;
1979 USHORT FirstTx, LastTxIdx;
1982 PQUEUE_ENTRY pQEntry;
1987 ASSERT((pTxBlk->TxPacketList.Number== 2));
1990 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
1991 while(pTxBlk->TxPacketList.Head)
1993 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1994 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1996 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1998 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2002 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2004 // skip 802.3 header
2005 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2006 pTxBlk->SrcBufLen -= LENGTH_802_3;
2011 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2012 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2016 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2018 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2020 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2021 // will be updated after final frame was handled.
2022 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2026 // Insert LLC-SNAP encapsulation - 8 octets
2028 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2030 if (pTxBlk->pExtraLlcSnapEncap)
2032 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2034 // get 2 octets (TypeofLen)
2035 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2037 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2041 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2043 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2044 pTxBlk->MpduHeaderLen = 0;
2046 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2047 // DA(6)+SA(6)+FrameType(2)
2048 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2049 pHeaderBufPtr += 12;
2050 // get 2 octets (TypeofLen)
2051 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2053 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2056 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2058 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2060 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2062 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2066 pAd->RalinkCounters.OneSecTxAggregationCount++;
2067 pAd->RalinkCounters.KickTxCount++;
2068 pAd->RalinkCounters.OneSecTxDoneCount++;
2072 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2073 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2078 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2083 VOID STA_Fragment_Frame_Tx(
2084 IN RTMP_ADAPTER *pAd,
2087 HEADER_802_11 *pHeader_802_11;
2088 PUCHAR pHeaderBufPtr;
2091 PACKET_INFO PacketInfo;
2092 USHORT EncryptionOverhead = 0;
2093 UINT32 FreeMpduSize, SrcRemainingBytes;
2097 PQUEUE_ENTRY pQEntry;
2102 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2103 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2104 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2106 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2110 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2111 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2113 STAFindCipherAlgorithm(pAd, pTxBlk);
2114 STABuildCommon802_11Header(pAd, pTxBlk);
2116 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2118 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2119 if (pTxBlk->pPacket == NULL)
2121 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2124 // skip 802.3 header
2125 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2126 pTxBlk->SrcBufLen -= LENGTH_802_3;
2132 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2133 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2136 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2137 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2140 // skip common header
2141 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2143 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2146 // build QOS Control bytes
2148 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2150 *(pHeaderBufPtr+1) = 0;
2152 pTxBlk->MpduHeaderLen += 2;
2156 // padding at front of LLC header
2157 // LLC header should locate at 4-octets aligment
2159 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2160 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2161 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2166 // Insert LLC-SNAP encapsulation - 8 octets
2169 // if original Ethernet frame contains no LLC/SNAP,
2170 // then an extra LLC/SNAP encap is required
2172 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2173 if (pTxBlk->pExtraLlcSnapEncap)
2177 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2180 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2181 // get 2 octets (TypeofLen)
2182 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2184 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2188 // If TKIP is used and fragmentation is required. Driver has to
2189 // append TKIP MIC at tail of the scatter buffer
2190 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2191 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2194 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2195 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2196 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2197 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2198 pTxBlk->SrcBufLen += 8;
2199 pTxBlk->TotalFrameLen += 8;
2200 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2204 // calcuate the overhead bytes that encryption algorithm may add. This
2205 // affects the calculate of "duration" field
2207 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2208 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2209 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2210 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2211 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2212 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2213 else if (pTxBlk->CipherAlg == CIPHER_AES)
2214 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2216 EncryptionOverhead = 0;
2218 // decide how much time an ACK/CTS frame will consume in the air
2219 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2221 // Init the total payload length of this frame.
2222 SrcRemainingBytes = pTxBlk->SrcBufLen;
2224 pTxBlk->TotalFragNum = 0xff;
2228 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2230 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2232 if (SrcRemainingBytes <= FreeMpduSize)
2233 { // this is the last or only fragment
2235 pTxBlk->SrcBufLen = SrcRemainingBytes;
2237 pHeader_802_11->FC.MoreFrag = 0;
2238 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2240 // Indicate the lower layer that this's the last fragment.
2241 pTxBlk->TotalFragNum = fragNum;
2244 { // more fragment is required
2246 pTxBlk->SrcBufLen = FreeMpduSize;
2248 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2249 pHeader_802_11->FC.MoreFrag = 1;
2250 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2254 pTxBlk->FrameGap = IFS_HTTXOP;
2256 pTxBlk->FrameGap = IFS_SIFS;
2258 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2260 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2262 pAd->RalinkCounters.KickTxCount++;
2263 pAd->RalinkCounters.OneSecTxDoneCount++;
2265 // Update the frame number, remaining size of the NDIS packet payload.
2267 // space for 802.11 header.
2268 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2269 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2272 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2273 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2275 pHeader_802_11->Frag++; // increase Frag #
2277 }while(SrcRemainingBytes > 0);
2282 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2286 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2287 while(_pTxBlk->TxPacketList.Head) \
2289 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2290 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2295 ========================================================================
2297 Routine Description:
2298 Copy frame from waiting queue into relative ring buffer and set
2299 appropriate ASIC register to kick hardware encryption before really
2303 pAd Pointer to our adapter
2304 PNDIS_PACKET Pointer to outgoing Ndis frame
2305 NumberOfFrag Number of fragment required
2310 IRQL = DISPATCH_LEVEL
2314 ========================================================================
2316 NDIS_STATUS STAHardTransmit(
2317 IN PRTMP_ADAPTER pAd,
2321 NDIS_PACKET *pPacket;
2322 PQUEUE_ENTRY pQEntry;
2324 // ---------------------------------------------
2325 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2326 // ---------------------------------------------
2328 ASSERT(pTxBlk->TxPacketList.Number);
2329 if (pTxBlk->TxPacketList.Head == NULL)
2331 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2332 return NDIS_STATUS_FAILURE;
2335 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2337 // ------------------------------------------------------------------
2338 // STEP 1. WAKE UP PHY
2339 // outgoing frame always wakeup PHY to prevent frame lost and
2340 // turn off PSM bit to improve performance
2341 // ------------------------------------------------------------------
2342 // not to change PSM bit, just send this frame out?
2343 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2345 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2346 AsicForceWakeup(pAd, TRUE);
2349 // It should not change PSM bit, when APSD turn on.
2350 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2351 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2352 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2354 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2355 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2356 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2359 switch (pTxBlk->TxFrameType)
2361 case TX_AMPDU_FRAME:
2362 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2364 case TX_AMSDU_FRAME:
2365 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2367 case TX_LEGACY_FRAME:
2368 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2370 case TX_MCAST_FRAME:
2371 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2373 case TX_RALINK_FRAME:
2374 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2377 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2381 // It should not happened!
2382 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2383 while(pTxBlk->TxPacketList.Number)
2385 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2386 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2388 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2394 return (NDIS_STATUS_SUCCESS);
2398 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2400 unsigned char *word = value;
2401 unsigned int ret = 0;
2404 for(i=0; i < len; i++)
2407 ret ^=(unsigned int) (word[i]) << mod;
2408 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2413 VOID Sta_Announce_or_Forward_802_3_Packet(
2414 IN PRTMP_ADAPTER pAd,
2415 IN PNDIS_PACKET pPacket,
2416 IN UCHAR FromWhichBSSID)
2421 announce_802_3_packet(pAd, pPacket);
2426 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);