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)
77 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
79 // Set key material and cipherAlg to Asic
80 AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
82 // Assign group key info
83 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
85 // Assign pairwise key info
86 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
88 pAd->IndicateMediaState = NdisMediaStateConnected;
89 pAd->ExtraInfo = GENERAL_LINK_UP;
90 // For Preventing ShardKey Table is cleared by remove key procedure.
91 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
92 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
93 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
94 pAd->StaCfg.DesireSharedKey[idx].Key,
95 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
100 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
106 // Special DATA frame that has to pass to MLME
107 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
108 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
110 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
111 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
112 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
113 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
117 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
122 VOID STARxDataFrameAnnounce(
123 IN PRTMP_ADAPTER pAd,
124 IN MAC_TABLE_ENTRY *pEntry,
126 IN UCHAR FromWhichBSSID)
130 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
133 // drop all non-EAP DATA frame before
134 // this client's Port-Access-Control is secured
135 if (pRxBlk->pHeader->FC.Wep)
137 // unsupported cipher suite
138 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
141 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
147 // encryption in-use but receive a non-EAPOL clear text frame, drop it
148 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
149 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
152 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
157 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
158 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
160 // Normal legacy, AMPDU or AMSDU
161 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
167 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
172 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
173 #ifdef DOT11_N_SUPPORT
174 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
176 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
179 #endif // DOT11_N_SUPPORT //
181 // Determin the destination of the EAP frame
182 // to WPA state machine or upper layer
183 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
189 // For TKIP frame, calculate the MIC value
190 BOOLEAN STACheckTkipMICValue(
191 IN PRTMP_ADAPTER pAd,
192 IN MAC_TABLE_ENTRY *pEntry,
195 PHEADER_802_11 pHeader = pRxBlk->pHeader;
196 UCHAR *pData = pRxBlk->pData;
197 USHORT DataSize = pRxBlk->DataSize;
198 UCHAR UserPriority = pRxBlk->UserPriority;
202 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
204 pDA = pHeader->Addr1;
205 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
207 pSA = pHeader->Addr3;
211 pSA = pHeader->Addr2;
214 if (RTMPTkipCompareMICValue(pAd,
222 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
224 if (pAd->StaCfg.WpaSupplicantUP)
226 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
230 RTMPReportMicError(pAd, pWpaKey);
234 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
243 // All Rx routines use RX_BLK structure to hande rx events
244 // It is very important to build pRxBlk attributes
245 // 1. pHeader pointer to 802.11 Header
246 // 2. pData pointer to payload including LLC (just skip Header)
247 // 3. set payload size including LLC to DataSize
248 // 4. set some flags with RX_BLK_SET_FLAG()
250 VOID STAHandleRxDataFrame(
251 IN PRTMP_ADAPTER pAd,
254 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
255 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
256 PHEADER_802_11 pHeader = pRxBlk->pHeader;
257 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
258 BOOLEAN bFragment = FALSE;
259 MAC_TABLE_ENTRY *pEntry = NULL;
260 UCHAR FromWhichBSSID = BSS0;
261 UCHAR UserPriority = 0;
264 // before LINK UP, all DATA frames are rejected
265 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
268 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
272 // Drop not my BSS frames
273 if (pRxD->MyBss == 0)
277 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
282 pAd->RalinkCounters.RxCountSinceLastNULL++;
283 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
286 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
289 pData = (PUCHAR)pHeader + LENGTH_802_11;
290 if ((*pData >> 4) & 0x01)
292 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
293 pAd->CommonCfg.bInServicePeriod = FALSE;
295 // Force driver to fall into sleep mode when rcv EOSP frame
296 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
298 USHORT TbttNumToNextWakeUp;
299 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
302 NdisGetSystemUpTime(&Now);
303 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
305 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
306 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
307 TbttNumToNextWakeUp = NextDtim;
309 MlmeSetPsmBit(pAd, PWR_SAVE);
310 // if WMM-APSD is failed, try to disable following line
311 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
315 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
317 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
321 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
322 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
325 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
329 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
333 // Infrastructure mode, check address 2 for BSSID
334 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
336 // Receive frame not my BSSID
338 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
342 else // Ad-Hoc mode or Not associated
344 // Ad-Hoc mode, check address 3 for BSSID
345 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
347 // Receive frame not my BSSID
349 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
357 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
359 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
363 // 1. release packet if infra mode
364 // 2. new a pEntry if ad-hoc mode
365 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
372 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
373 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
376 // check Atheros Client
377 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
379 pEntry->bIAmBadAtheros = TRUE;
380 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
381 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
382 if (!STA_AES_ON(pAd))
384 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
389 pRxBlk->pData = (UCHAR *)pHeader;
392 // update RxBlk->pData, DataSize
393 // 802.11 Header, QOS, HTC, Hw Padding
396 // 1. skip 802.11 HEADER
398 pRxBlk->pData += LENGTH_802_11;
399 pRxBlk->DataSize -= LENGTH_802_11;
403 if (pHeader->FC.SubType & 0x08)
405 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
406 UserPriority = *(pRxBlk->pData) & 0x0f;
407 // bit 7 in QoS Control field signals the HT A-MSDU format
408 if ((*pRxBlk->pData) & 0x80)
410 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
413 // skip QOS contorl field
415 pRxBlk->DataSize -=2;
417 pRxBlk->UserPriority = UserPriority;
419 // 3. Order bit: A-Ralink or HTC+
420 if (pHeader->FC.Order)
422 #ifdef AGGREGATION_SUPPORT
423 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
425 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
430 #ifdef DOT11_N_SUPPORT
431 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
432 // skip HTC contorl field
434 pRxBlk->DataSize -= 4;
435 #endif // DOT11_N_SUPPORT //
439 // 4. skip HW padding
442 // just move pData pointer
443 // because DataSize excluding HW padding
444 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
448 #ifdef DOT11_N_SUPPORT
451 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
453 #endif // DOT11_N_SUPPORT //
457 // Case I Process Broadcast & Multicast data frame
459 if (pRxD->Bcast || pRxD->Mcast)
461 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
463 // Drop Mcast/Bcast frame with fragment bit on
464 if (pHeader->FC.MoreFrag)
467 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
471 // Filter out Bcast frame which AP relayed for us
472 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
475 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
479 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
484 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
488 pEntry = MacTableLookup(pAd, pHeader->Addr2);
490 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
494 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
496 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
497 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
499 pAd->RalinkCounters.OneSecRxOkDataCnt++;
502 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
504 // re-assemble the fragmented packets
505 // return complete frame (pRxPacket) or NULL
507 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
512 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
514 // process complete frame
515 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
518 pRxBlk->DataSize -= 8;
520 // For TKIP frame, calculate the MIC value
521 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
527 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
533 // because RTMPDeFragmentDataFrame() will release rx packet,
534 // if packet is fragmented
541 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
544 VOID STAHandleRxMgmtFrame(
545 IN PRTMP_ADAPTER pAd,
548 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
549 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
550 PHEADER_802_11 pHeader = pRxBlk->pHeader;
551 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
556 // We should collect RSSI not only U2M data but also my beacon
557 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
559 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
561 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
562 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
565 // First check the size, it MUST not exceed the mlme queue size
566 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
568 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
572 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
573 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
576 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
579 VOID STAHandleRxControlFrame(
580 IN PRTMP_ADAPTER pAd,
583 #ifdef DOT11_N_SUPPORT
584 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
585 #endif // DOT11_N_SUPPORT //
586 PHEADER_802_11 pHeader = pRxBlk->pHeader;
587 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
589 switch (pHeader->FC.SubType)
591 case SUBTYPE_BLOCK_ACK_REQ:
592 #ifdef DOT11_N_SUPPORT
594 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
597 #endif // DOT11_N_SUPPORT //
598 case SUBTYPE_BLOCK_ACK:
604 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
609 ========================================================================
612 Process RxDone interrupt, running in DPC level
615 pAd Pointer to our adapter
620 IRQL = DISPATCH_LEVEL
623 This routine has to maintain Rx ring read pointer.
624 Need to consider QOS DATA format when converting to 802.3
625 ========================================================================
627 BOOLEAN STARxDoneInterruptHandle(
628 IN PRTMP_ADAPTER pAd,
632 UINT32 RxProcessed, RxPending;
633 BOOLEAN bReschedule = FALSE;
634 RT28XX_RXD_STRUC *pRxD;
637 PNDIS_PACKET pRxPacket;
638 PHEADER_802_11 pHeader;
641 RxProcessed = RxPending = 0;
643 // process whole rx ring
647 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
648 fRTMP_ADAPTER_RESET_IN_PROGRESS |
649 fRTMP_ADAPTER_HALT_IN_PROGRESS |
650 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
651 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
656 if (RxProcessed++ > MAX_RX_PROCESS_CNT)
658 // need to reschedule rx handle
663 RxProcessed ++; // test
665 // 1. allocate a new data packet into rx ring to replace received packet
666 // then processing the received packet
667 // 2. the callee must take charge of release of packet
668 // 3. As far as driver is concerned ,
669 // the rx packet must
670 // a. be indicated to upper layer or
671 // b. be released if it is discarded
672 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
673 if (pRxPacket == NULL)
675 // no more packet to process
679 // get rx ring descriptor
680 pRxD = &(RxCell.RxD);
681 // get rx data buffer
682 pData = GET_OS_PKT_DATAPTR(pRxPacket);
683 pRxWI = (PRXWI_STRUC) pData;
684 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
687 RxCell.pRxWI = pRxWI;
688 RxCell.pHeader = pHeader;
689 RxCell.pRxPacket = pRxPacket;
690 RxCell.pData = (UCHAR *) pHeader;
691 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
694 // Increase Total receive byte counter after real data received no mater any error or not
695 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
696 pAd->RalinkCounters.RxCount ++;
698 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
700 if (pRxWI->MPDUtotalByteCount < 14)
701 Status = NDIS_STATUS_FAILURE;
705 send_monitor_packets(pAd, &RxCell);
708 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
710 // Check for all RxD errors
711 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
713 // Handle the received frame
714 if (Status == NDIS_STATUS_SUCCESS)
716 switch (pHeader->FC.Type)
718 // CASE I, receive a DATA frame
721 // process DATA frame
722 STAHandleRxDataFrame(pAd, &RxCell);
725 // CASE II, receive a MGMT frame
728 STAHandleRxMgmtFrame(pAd, &RxCell);
731 // CASE III. receive a CNTL frame
734 STAHandleRxControlFrame(pAd, &RxCell);
737 // discard other type
739 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
745 pAd->Counters8023.RxErrors++;
746 // discard this frame
747 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
751 // fRTMP_PS_GO_TO_SLEEP_NOW is set if receiving beacon.
752 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW) && (INFRA_ON(pAd)))
754 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
755 AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp);
762 ========================================================================
766 pAd Pointer to our adapter
768 IRQL = DISPATCH_LEVEL
770 ========================================================================
772 VOID RTMPHandleTwakeupInterrupt(
773 IN PRTMP_ADAPTER pAd)
775 AsicForceWakeup(pAd, DOT11POWERSAVE);
779 ========================================================================
781 Early checking and OS-depened parsing for Tx packet send to our STA driver.
784 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
785 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
786 UINT NumberOfPackets Number of packet in packet array.
792 This function do early checking and classification for send-out packet.
793 You only can put OS-depened & STA related code in here.
794 ========================================================================
797 IN NDIS_HANDLE MiniportAdapterContext,
798 IN PPNDIS_PACKET ppPacketArray,
799 IN UINT NumberOfPackets)
802 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
803 PNDIS_PACKET pPacket;
804 BOOLEAN allowToSend = FALSE;
807 for (Index = 0; Index < NumberOfPackets; Index++)
809 pPacket = ppPacketArray[Index];
813 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
814 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
815 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
817 // Drop send request since hardware is in reset state
820 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
822 // Drop send request since there are no physical connection yet
827 // Record that orignal packet source is from NDIS layer,so that
828 // later on driver knows how to release this NDIS PACKET
829 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
830 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
831 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
832 pAd->RalinkCounters.PendingNdisPacketCount++;
838 if (allowToSend == TRUE)
839 STASendPacket(pAd, pPacket);
841 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
844 // Dequeue outgoing frames from TxSwQueue[] and process it
845 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
851 ========================================================================
853 This routine is used to do packet parsing and classification for Tx packet
854 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
858 pAd Pointer to our adapter
859 pPacket Pointer to send packet
862 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
863 NDIS_STATUS_FAILURE If failed to do en-queue.
866 You only can put OS-indepened & STA related code in here.
867 ========================================================================
869 NDIS_STATUS STASendPacket(
870 IN PRTMP_ADAPTER pAd,
871 IN PNDIS_PACKET pPacket)
873 PACKET_INFO PacketInfo;
878 UCHAR QueIdx, UserPriority;
879 MAC_TABLE_ENTRY *pEntry = NULL;
880 unsigned int IrqFlags;
884 // Prepare packet information structure for buffer descriptor
885 // chained within a single NDIS packet.
886 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
888 if (pSrcBufVA == NULL)
890 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
891 // Resourece is low, system did not allocate virtual address
892 // return NDIS_STATUS_FAILURE directly to upper layer
893 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
894 return NDIS_STATUS_FAILURE;
900 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
901 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
902 return (NDIS_STATUS_FAILURE);
905 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
906 // Note multicast packets in adhoc also use BSSID_WCID index.
911 pEntry = &pAd->MacTab.Content[BSSID_WCID];
912 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
913 Rate = pAd->CommonCfg.TxRate;
916 else if (ADHOC_ON(pAd))
918 if (*pSrcBufVA & 0x01)
920 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
921 pEntry = &pAd->MacTab.Content[MCAST_WCID];
925 pEntry = MacTableLookup(pAd, pSrcBufVA);
927 Rate = pAd->CommonCfg.TxRate;
933 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
934 // Resourece is low, system did not allocate virtual address
935 // return NDIS_STATUS_FAILURE directly to upper layer
936 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
937 return NDIS_STATUS_FAILURE;
943 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
947 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
948 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
949 RTMPCheckEtherType(pAd, pPacket);
954 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
956 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
957 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
958 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
959 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
960 || (pAd->StaCfg.IEEE8021X == TRUE)
962 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
963 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
966 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
967 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
969 return (NDIS_STATUS_FAILURE);
973 // STEP 1. Decide number of fragments required to deliver this MSDU.
974 // The estimation here is not very accurate because difficult to
975 // take encryption overhead into consideration here. The result
976 // "NumberOfFrag" is then just used to pre-check if enough free
977 // TXD are available to hold this MSDU.
980 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
982 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
983 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
984 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
985 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
986 #ifdef DOT11_N_SUPPORT
987 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
988 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
989 #endif // DOT11_N_SUPPORT //
992 // The calculated "NumberOfFrag" is a rough estimation because of various
993 // encryption/encapsulation overhead not taken into consideration. This number is just
994 // used to make sure enough free TXD are available before fragmentation takes place.
995 // In case the actual required number of fragments of an NDIS packet
996 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
997 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
998 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
999 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1001 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1002 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1003 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1004 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1010 // Save fragment number to Ndis packet reserved field
1011 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1014 // STEP 2. Check the requirement of RTS:
1015 // If multiple fragment required, RTS is required only for the first fragment
1016 // if the fragment size large than RTS threshold
1017 // For RT28xx, Let ASIC send RTS/CTS
1018 RTMP_SET_PACKET_RTS(pPacket, 0);
1019 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1022 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1026 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1029 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1032 // get Ethernet protocol field
1033 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1034 if (Protocol <= 1500)
1036 // get Ethernet protocol field from LLC/SNAP
1037 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1040 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1044 // always AC_BE for non-IP packet
1045 if (Protocol != 0x0800)
1049 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1052 // return AC_BE if packet is not IPv4
1053 if ((Byte0 & 0xf0) != 0x40)
1057 UserPriority = (Byte1 & 0xe0) >> 5;
1058 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1060 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1061 // TODO: downgrade UP & QueIdx before passing ACM
1062 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1070 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1074 // Make sure SendTxWait queue resource won't be used by other threads
1075 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1076 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1078 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1079 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1081 return NDIS_STATUS_FAILURE;
1085 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1087 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1089 #ifdef DOT11_N_SUPPORT
1090 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1091 (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1093 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1094 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1095 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1096 // For IOT compatibility, if
1097 // 1. It is Ralink chip or
1098 // 2. It is OPEN or AES mode,
1099 // then BA session can be bulit.
1100 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1101 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1104 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1107 #endif // DOT11_N_SUPPORT //
1109 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1110 return NDIS_STATUS_SUCCESS;
1115 ========================================================================
1117 Routine Description:
1118 This subroutine will scan through releative ring descriptor to find
1119 out avaliable free ring descriptor and compare with request size.
1122 pAd Pointer to our adapter
1123 QueIdx Selected TX Ring
1126 NDIS_STATUS_FAILURE Not enough free descriptor
1127 NDIS_STATUS_SUCCESS Enough free descriptor
1129 IRQL = PASSIVE_LEVEL
1130 IRQL = DISPATCH_LEVEL
1134 ========================================================================
1136 NDIS_STATUS RTMPFreeTXDRequest(
1137 IN PRTMP_ADAPTER pAd,
1139 IN UCHAR NumberRequired,
1140 IN PUCHAR FreeNumberIs)
1142 ULONG FreeNumber = 0;
1143 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1152 if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1153 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1155 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1157 if (FreeNumber >= NumberRequired)
1158 Status = NDIS_STATUS_SUCCESS;
1162 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1163 FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1165 FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1167 if (FreeNumber >= NumberRequired)
1168 Status = NDIS_STATUS_SUCCESS;
1172 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1175 *FreeNumberIs = (UCHAR)FreeNumber;
1182 VOID RTMPSendDisassociationFrame(
1183 IN PRTMP_ADAPTER pAd)
1187 VOID RTMPSendNullFrame(
1188 IN PRTMP_ADAPTER pAd,
1190 IN BOOLEAN bQosNull)
1192 UCHAR NullFrame[48];
1194 PHEADER_802_11 pHeader_802_11;
1196 // WPA 802.1x secured port control
1197 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1198 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1199 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1200 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1201 || (pAd->StaCfg.IEEE8021X == TRUE)
1203 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1208 NdisZeroMemory(NullFrame, 48);
1209 Length = sizeof(HEADER_802_11);
1211 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1213 pHeader_802_11->FC.Type = BTYPE_DATA;
1214 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1215 pHeader_802_11->FC.ToDs = 1;
1216 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1217 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1218 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1220 if (pAd->CommonCfg.bAPSDForcePowerSave)
1222 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1226 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1228 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1231 pHeader_802_11->Sequence = pAd->Sequence;
1233 // Prepare QosNull function frame
1236 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1238 // copy QOS control bytes
1239 NullFrame[Length] = 0;
1240 NullFrame[Length+1] = 0;
1241 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1244 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1248 // IRQL = DISPATCH_LEVEL
1249 VOID RTMPSendRTSFrame(
1250 IN PRTMP_ADAPTER pAd,
1252 IN unsigned int NextMpduSize,
1255 IN USHORT AckDuration,
1263 // --------------------------------------------------------
1264 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1265 // Find the WPA key, either Group or Pairwise Key
1266 // LEAP + TKIP also use WPA key.
1267 // --------------------------------------------------------
1268 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1269 // In Cisco CCX 2.0 Leap Authentication
1270 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1271 // Instead of the SharedKey, SharedKey Length may be Zero.
1272 VOID STAFindCipherAlgorithm(
1273 IN PRTMP_ADAPTER pAd,
1276 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1277 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1278 UCHAR KeyIdx = 0xff;
1280 PCIPHER_KEY pKey = NULL;
1282 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1286 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1287 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1289 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1291 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1293 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1295 // 4-way handshaking frame must be clear
1296 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1297 (pAd->SharedKey[BSS0][0].KeyLen))
1299 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1303 else if (Cipher == Ndis802_11Encryption1Enabled)
1305 KeyIdx = pAd->StaCfg.DefaultKeyId;
1307 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1308 (Cipher == Ndis802_11Encryption3Enabled))
1310 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1311 KeyIdx = pAd->StaCfg.DefaultKeyId;
1312 else if (pAd->SharedKey[BSS0][0].KeyLen)
1315 KeyIdx = pAd->StaCfg.DefaultKeyId;
1319 CipherAlg = CIPHER_NONE;
1320 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1321 CipherAlg = CIPHER_NONE;
1322 else if ( pAd->StaCfg.WpaSupplicantUP &&
1323 (Cipher == Ndis802_11Encryption1Enabled) &&
1324 (pAd->StaCfg.IEEE8021X == TRUE) &&
1325 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1326 CipherAlg = CIPHER_NONE;
1329 //Header_802_11.FC.Wep = 1;
1330 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1331 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1335 pTxBlk->CipherAlg = CipherAlg;
1336 pTxBlk->pKey = pKey;
1340 VOID STABuildCommon802_11Header(
1341 IN PRTMP_ADAPTER pAd,
1344 HEADER_802_11 *pHeader_802_11;
1347 // MAKE A COMMON 802.11 HEADER
1350 // normal wlan header size : 24 octets
1351 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1353 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1355 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1357 pHeader_802_11->FC.FrDs = 0;
1358 pHeader_802_11->FC.Type = BTYPE_DATA;
1359 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1361 if (pTxBlk->pMacEntry)
1363 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1365 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1366 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1371 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1372 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1378 pHeader_802_11->Sequence = pAd->Sequence;
1379 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1382 pHeader_802_11->Frag = 0;
1384 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1390 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1391 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1392 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1393 pHeader_802_11->FC.ToDs = 1;
1396 else if (ADHOC_ON(pAd))
1398 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1399 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1400 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1401 pHeader_802_11->FC.ToDs = 0;
1405 if (pTxBlk->CipherAlg != CIPHER_NONE)
1406 pHeader_802_11->FC.Wep = 1;
1408 // -----------------------------------------------------------------
1409 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1410 // -----------------------------------------------------------------
1411 if (pAd->CommonCfg.bAPSDForcePowerSave)
1412 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1414 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1417 #ifdef DOT11_N_SUPPORT
1418 VOID STABuildCache802_11Header(
1419 IN RTMP_ADAPTER *pAd,
1423 MAC_TABLE_ENTRY *pMacEntry;
1424 PHEADER_802_11 pHeader80211;
1426 pHeader80211 = (PHEADER_802_11)pHeader;
1427 pMacEntry = pTxBlk->pMacEntry;
1430 // Update the cached 802.11 HEADER
1433 // normal wlan header size : 24 octets
1434 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1437 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1440 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1441 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1444 // The addr3 of normal packet send from DS is Dest Mac address.
1446 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1448 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1451 // -----------------------------------------------------------------
1452 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1453 // -----------------------------------------------------------------
1454 if (pAd->CommonCfg.bAPSDForcePowerSave)
1455 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1457 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1459 #endif // DOT11_N_SUPPORT //
1461 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1462 IN RTMP_ADAPTER *pAd,
1465 PUCHAR pHeaderBufPtr;
1466 HEADER_802_11 *pHeader_802_11;
1467 PNDIS_PACKET pNextPacket;
1469 PQUEUE_ENTRY pQEntry;
1471 STAFindCipherAlgorithm(pAd, pTxBlk);
1472 STABuildCommon802_11Header(pAd, pTxBlk);
1475 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1476 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1478 // steal "order" bit to mark "aggregation"
1479 pHeader_802_11->FC.Order = 1;
1481 // skip common header
1482 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1484 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1487 // build QOS Control bytes
1489 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1491 *(pHeaderBufPtr+1) = 0;
1493 pTxBlk->MpduHeaderLen += 2;
1496 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1497 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1498 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1499 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1501 // For RA Aggregation,
1502 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1503 pQEntry = pTxBlk->TxPacketList.Head;
1504 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1505 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1506 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1507 nextBufLen -= LENGTH_802_1Q;
1509 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1510 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1513 pTxBlk->MpduHeaderLen += 2;
1515 return pHeaderBufPtr;
1519 #ifdef DOT11_N_SUPPORT
1520 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1521 IN RTMP_ADAPTER *pAd,
1524 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1525 HEADER_802_11 *pHeader_802_11;
1528 STAFindCipherAlgorithm(pAd, pTxBlk);
1529 STABuildCommon802_11Header(pAd, pTxBlk);
1531 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1532 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1534 // skip common header
1535 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1538 // build QOS Control bytes
1540 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1545 *pHeaderBufPtr |= 0x80;
1547 *(pHeaderBufPtr+1) = 0;
1549 pTxBlk->MpduHeaderLen += 2;
1551 //pSaveBufPtr = pHeaderBufPtr;
1554 // padding at front of LLC header
1555 // LLC header should locate at 4-octets aligment
1557 // @@@ MpduHeaderLen excluding padding @@@
1559 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1560 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1561 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1563 return pHeaderBufPtr;
1568 VOID STA_AMPDU_Frame_Tx(
1569 IN PRTMP_ADAPTER pAd,
1572 HEADER_802_11 *pHeader_802_11;
1573 PUCHAR pHeaderBufPtr;
1575 MAC_TABLE_ENTRY *pMacEntry;
1577 PQUEUE_ENTRY pQEntry;
1581 while(pTxBlk->TxPacketList.Head)
1583 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1584 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1585 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1587 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1591 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1593 pMacEntry = pTxBlk->pMacEntry;
1594 if (pMacEntry->isCached)
1596 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1597 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1598 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1599 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1603 STAFindCipherAlgorithm(pAd, pTxBlk);
1604 STABuildCommon802_11Header(pAd, pTxBlk);
1606 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1610 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1612 // skip common header
1613 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1616 // build QOS Control bytes
1618 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1619 *(pHeaderBufPtr+1) = 0;
1621 pTxBlk->MpduHeaderLen += 2;
1625 // HTC control filed following QoS field
1627 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1629 if (pMacEntry->isCached == FALSE)
1632 pHeader_802_11->FC.Order = 1;
1634 NdisZeroMemory(pHeaderBufPtr, 4);
1635 *(pHeaderBufPtr+3) |= 0x80;
1638 pTxBlk->MpduHeaderLen += 4;
1641 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1642 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1644 // skip 802.3 header
1645 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1646 pTxBlk->SrcBufLen -= LENGTH_802_3;
1651 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1652 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1656 // padding at front of LLC header
1657 // LLC header should locate at 4-octets aligment
1659 // @@@ MpduHeaderLen excluding padding @@@
1661 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1662 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1663 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1668 // Insert LLC-SNAP encapsulation - 8 octets
1670 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1671 if (pTxBlk->pExtraLlcSnapEncap)
1673 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1675 // get 2 octets (TypeofLen)
1676 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1678 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1683 if (pMacEntry->isCached)
1685 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1689 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1691 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1692 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1693 pMacEntry->isCached = TRUE;
1696 // calculate Transmitted AMPDU count and ByteCount
1698 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1699 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1702 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1704 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1709 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1710 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1712 pAd->RalinkCounters.KickTxCount++;
1713 pAd->RalinkCounters.OneSecTxDoneCount++;
1719 VOID STA_AMSDU_Frame_Tx(
1720 IN PRTMP_ADAPTER pAd,
1723 PUCHAR pHeaderBufPtr;
1725 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1726 USHORT totalMPDUSize=0;
1727 UCHAR *subFrameHeader;
1729 USHORT FirstTx = 0, LastTxIdx = 0;
1732 PQUEUE_ENTRY pQEntry;
1737 ASSERT((pTxBlk->TxPacketList.Number > 1));
1739 while(pTxBlk->TxPacketList.Head)
1741 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1742 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1743 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1745 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1749 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1751 // skip 802.3 header
1752 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1753 pTxBlk->SrcBufLen -= LENGTH_802_3;
1758 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1759 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1764 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1766 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1767 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1771 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1772 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1773 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1774 pHeaderBufPtr += padding;
1775 pTxBlk->MpduHeaderLen = padding;
1780 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1782 subFrameHeader = pHeaderBufPtr;
1783 subFramePayloadLen = pTxBlk->SrcBufLen;
1785 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1788 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1789 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1793 // Insert LLC-SNAP encapsulation - 8 octets
1795 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1797 subFramePayloadLen = pTxBlk->SrcBufLen;
1799 if (pTxBlk->pExtraLlcSnapEncap)
1801 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1803 // get 2 octets (TypeofLen)
1804 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1806 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1807 subFramePayloadLen += LENGTH_802_1_H;
1810 // update subFrame Length field
1811 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1812 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1814 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1817 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1819 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1823 pAd->RalinkCounters.KickTxCount++;
1824 pAd->RalinkCounters.OneSecTxDoneCount++;
1826 // calculate Transmitted AMSDU Count and ByteCount
1828 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1829 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1834 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1835 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1840 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1841 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1843 #endif // DOT11_N_SUPPORT //
1845 VOID STA_Legacy_Frame_Tx(
1846 IN PRTMP_ADAPTER pAd,
1849 HEADER_802_11 *pHeader_802_11;
1850 PUCHAR pHeaderBufPtr;
1853 PQUEUE_ENTRY pQEntry;
1858 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1859 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1860 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1862 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1866 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1868 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1871 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1872 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1874 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1876 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1878 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1879 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1881 STAFindCipherAlgorithm(pAd, pTxBlk);
1882 STABuildCommon802_11Header(pAd, pTxBlk);
1885 // skip 802.3 header
1886 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1887 pTxBlk->SrcBufLen -= LENGTH_802_3;
1892 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1893 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1896 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1897 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1899 // skip common header
1900 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1902 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1905 // build QOS Control bytes
1907 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1908 *(pHeaderBufPtr+1) = 0;
1910 pTxBlk->MpduHeaderLen += 2;
1913 // The remaining content of MPDU header should locate at 4-octets aligment
1914 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1915 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1916 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1921 // Insert LLC-SNAP encapsulation - 8 octets
1924 // if original Ethernet frame contains no LLC/SNAP,
1925 // then an extra LLC/SNAP encap is required
1927 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
1928 if (pTxBlk->pExtraLlcSnapEncap)
1932 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1935 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
1936 // get 2 octets (TypeofLen)
1937 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
1939 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1946 // use Wcid as Key Index
1949 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1951 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1953 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1955 pAd->RalinkCounters.KickTxCount++;
1956 pAd->RalinkCounters.OneSecTxDoneCount++;
1961 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1962 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1966 VOID STA_ARalink_Frame_Tx(
1967 IN PRTMP_ADAPTER pAd,
1970 PUCHAR pHeaderBufPtr;
1972 USHORT totalMPDUSize=0;
1973 USHORT FirstTx, LastTxIdx;
1976 PQUEUE_ENTRY pQEntry;
1981 ASSERT((pTxBlk->TxPacketList.Number== 2));
1984 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
1985 while(pTxBlk->TxPacketList.Head)
1987 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1988 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1990 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1992 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1996 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1998 // skip 802.3 header
1999 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2000 pTxBlk->SrcBufLen -= LENGTH_802_3;
2005 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2006 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2010 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2012 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2014 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2015 // will be updated after final frame was handled.
2016 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2020 // Insert LLC-SNAP encapsulation - 8 octets
2022 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2024 if (pTxBlk->pExtraLlcSnapEncap)
2026 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2028 // get 2 octets (TypeofLen)
2029 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2031 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2035 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2037 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2038 pTxBlk->MpduHeaderLen = 0;
2040 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2041 // DA(6)+SA(6)+FrameType(2)
2042 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2043 pHeaderBufPtr += 12;
2044 // get 2 octets (TypeofLen)
2045 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2047 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2050 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2052 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2054 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2056 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2060 pAd->RalinkCounters.OneSecTxAggregationCount++;
2061 pAd->RalinkCounters.KickTxCount++;
2062 pAd->RalinkCounters.OneSecTxDoneCount++;
2066 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2067 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2072 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2073 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2078 VOID STA_Fragment_Frame_Tx(
2079 IN RTMP_ADAPTER *pAd,
2082 HEADER_802_11 *pHeader_802_11;
2083 PUCHAR pHeaderBufPtr;
2086 PACKET_INFO PacketInfo;
2087 USHORT EncryptionOverhead = 0;
2088 UINT32 FreeMpduSize, SrcRemainingBytes;
2092 PQUEUE_ENTRY pQEntry;
2097 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2098 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2099 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2101 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2105 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2106 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2108 STAFindCipherAlgorithm(pAd, pTxBlk);
2109 STABuildCommon802_11Header(pAd, pTxBlk);
2111 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2113 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2114 if (pTxBlk->pPacket == NULL)
2116 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2119 // skip 802.3 header
2120 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2121 pTxBlk->SrcBufLen -= LENGTH_802_3;
2127 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2128 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2131 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2132 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2135 // skip common header
2136 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2138 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2141 // build QOS Control bytes
2143 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2145 *(pHeaderBufPtr+1) = 0;
2147 pTxBlk->MpduHeaderLen += 2;
2151 // padding at front of LLC header
2152 // LLC header should locate at 4-octets aligment
2154 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2155 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2156 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2161 // Insert LLC-SNAP encapsulation - 8 octets
2164 // if original Ethernet frame contains no LLC/SNAP,
2165 // then an extra LLC/SNAP encap is required
2167 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2168 if (pTxBlk->pExtraLlcSnapEncap)
2172 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2175 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2176 // get 2 octets (TypeofLen)
2177 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2179 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2183 // If TKIP is used and fragmentation is required. Driver has to
2184 // append TKIP MIC at tail of the scatter buffer
2185 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2186 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2189 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2190 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2191 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2192 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2193 pTxBlk->SrcBufLen += 8;
2194 pTxBlk->TotalFrameLen += 8;
2195 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2199 // calcuate the overhead bytes that encryption algorithm may add. This
2200 // affects the calculate of "duration" field
2202 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2203 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2204 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2205 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2206 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2207 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2208 else if (pTxBlk->CipherAlg == CIPHER_AES)
2209 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2211 EncryptionOverhead = 0;
2213 // decide how much time an ACK/CTS frame will consume in the air
2214 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2216 // Init the total payload length of this frame.
2217 SrcRemainingBytes = pTxBlk->SrcBufLen;
2219 pTxBlk->TotalFragNum = 0xff;
2223 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2225 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2227 if (SrcRemainingBytes <= FreeMpduSize)
2228 { // this is the last or only fragment
2230 pTxBlk->SrcBufLen = SrcRemainingBytes;
2232 pHeader_802_11->FC.MoreFrag = 0;
2233 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2235 // Indicate the lower layer that this's the last fragment.
2236 pTxBlk->TotalFragNum = fragNum;
2239 { // more fragment is required
2241 pTxBlk->SrcBufLen = FreeMpduSize;
2243 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2244 pHeader_802_11->FC.MoreFrag = 1;
2245 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2249 pTxBlk->FrameGap = IFS_HTTXOP;
2251 pTxBlk->FrameGap = IFS_SIFS;
2253 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2255 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2257 pAd->RalinkCounters.KickTxCount++;
2258 pAd->RalinkCounters.OneSecTxDoneCount++;
2260 // Update the frame number, remaining size of the NDIS packet payload.
2262 // space for 802.11 header.
2263 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2264 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2267 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2268 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2270 pHeader_802_11->Frag++; // increase Frag #
2272 }while(SrcRemainingBytes > 0);
2277 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2281 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2282 while(_pTxBlk->TxPacketList.Head) \
2284 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2285 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2290 ========================================================================
2292 Routine Description:
2293 Copy frame from waiting queue into relative ring buffer and set
2294 appropriate ASIC register to kick hardware encryption before really
2298 pAd Pointer to our adapter
2299 PNDIS_PACKET Pointer to outgoing Ndis frame
2300 NumberOfFrag Number of fragment required
2305 IRQL = DISPATCH_LEVEL
2309 ========================================================================
2311 NDIS_STATUS STAHardTransmit(
2312 IN PRTMP_ADAPTER pAd,
2316 NDIS_PACKET *pPacket;
2317 PQUEUE_ENTRY pQEntry;
2319 // ---------------------------------------------
2320 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2321 // ---------------------------------------------
2323 ASSERT(pTxBlk->TxPacketList.Number);
2324 if (pTxBlk->TxPacketList.Head == NULL)
2326 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2327 return NDIS_STATUS_FAILURE;
2330 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2332 // ------------------------------------------------------------------
2333 // STEP 1. WAKE UP PHY
2334 // outgoing frame always wakeup PHY to prevent frame lost and
2335 // turn off PSM bit to improve performance
2336 // ------------------------------------------------------------------
2337 // not to change PSM bit, just send this frame out?
2338 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2340 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2341 AsicForceWakeup(pAd, FROM_TX);
2344 // It should not change PSM bit, when APSD turn on.
2345 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2346 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2347 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2349 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2350 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2351 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2354 switch (pTxBlk->TxFrameType)
2356 #ifdef DOT11_N_SUPPORT
2357 case TX_AMPDU_FRAME:
2358 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2360 case TX_AMSDU_FRAME:
2361 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2363 #endif // DOT11_N_SUPPORT //
2364 case TX_LEGACY_FRAME:
2365 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2367 case TX_MCAST_FRAME:
2368 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2370 case TX_RALINK_FRAME:
2371 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2374 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2378 // It should not happened!
2379 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2380 while(pTxBlk->TxPacketList.Number)
2382 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2383 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2385 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2391 return (NDIS_STATUS_SUCCESS);
2395 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2397 unsigned char *word = value;
2398 unsigned int ret = 0;
2401 for(i=0; i < len; i++)
2404 ret ^=(unsigned int) (word[i]) << mod;
2405 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2410 VOID Sta_Announce_or_Forward_802_3_Packet(
2411 IN PRTMP_ADAPTER pAd,
2412 IN PNDIS_PACKET pPacket,
2413 IN UCHAR FromWhichBSSID)
2418 announce_802_3_packet(pAd, pPacket);
2423 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);