2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
35 -------- ---------- ----------------------------------------------
36 John Aug/17/04 major modification for RT2561/2661
37 Jan Lee Mar/17/06 major modification for RT2860 New Ring Design
39 #include "../rt_config.h"
43 VOID STARxEAPOLFrameIndicate(
45 IN MAC_TABLE_ENTRY *pEntry,
47 IN UCHAR FromWhichBSSID)
49 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
50 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
53 #ifdef WPA_SUPPLICANT_SUPPORT
54 if (pAd->StaCfg.WpaSupplicantUP)
56 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
57 // TBD : process fragmented EAPol frames
59 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
60 if ( pAd->StaCfg.IEEE8021X == TRUE &&
61 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
67 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
68 STA_PORT_SECURED(pAd);
70 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
72 idx = pAd->StaCfg.DesireSharedKeyId;
73 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
74 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
76 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
78 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
80 // Set key material and cipherAlg to Asic
81 AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
83 // Assign group key info
84 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
86 // Assign pairwise key info
87 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
89 pAd->IndicateMediaState = NdisMediaStateConnected;
90 pAd->ExtraInfo = GENERAL_LINK_UP;
91 // For Preventing ShardKey Table is cleared by remove key procedure.
92 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
93 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
94 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
95 pAd->StaCfg.DesireSharedKey[idx].Key,
96 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
101 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
106 #endif // WPA_SUPPLICANT_SUPPORT //
108 // Special DATA frame that has to pass to MLME
109 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
110 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
112 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
113 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
114 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
115 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
119 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
124 VOID STARxDataFrameAnnounce(
125 IN PRTMP_ADAPTER pAd,
126 IN MAC_TABLE_ENTRY *pEntry,
128 IN UCHAR FromWhichBSSID)
132 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
135 // drop all non-EAP DATA frame before
136 // this client's Port-Access-Control is secured
137 if (pRxBlk->pHeader->FC.Wep)
139 // unsupported cipher suite
140 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
143 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
149 // encryption in-use but receive a non-EAPOL clear text frame, drop it
150 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
151 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
154 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
159 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
160 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
162 // Normal legacy, AMPDU or AMSDU
163 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
169 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
174 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
175 #ifdef DOT11_N_SUPPORT
176 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
178 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
181 #endif // DOT11_N_SUPPORT //
183 // Determin the destination of the EAP frame
184 // to WPA state machine or upper layer
185 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
191 // For TKIP frame, calculate the MIC value
192 BOOLEAN STACheckTkipMICValue(
193 IN PRTMP_ADAPTER pAd,
194 IN MAC_TABLE_ENTRY *pEntry,
197 PHEADER_802_11 pHeader = pRxBlk->pHeader;
198 UCHAR *pData = pRxBlk->pData;
199 USHORT DataSize = pRxBlk->DataSize;
200 UCHAR UserPriority = pRxBlk->UserPriority;
204 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
206 pDA = pHeader->Addr1;
207 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
209 pSA = pHeader->Addr3;
213 pSA = pHeader->Addr2;
216 if (RTMPTkipCompareMICValue(pAd,
224 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
226 #ifdef WPA_SUPPLICANT_SUPPORT
227 if (pAd->StaCfg.WpaSupplicantUP)
229 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
232 #endif // WPA_SUPPLICANT_SUPPORT //
234 RTMPReportMicError(pAd, pWpaKey);
238 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
247 // All Rx routines use RX_BLK structure to hande rx events
248 // It is very important to build pRxBlk attributes
249 // 1. pHeader pointer to 802.11 Header
250 // 2. pData pointer to payload including LLC (just skip Header)
251 // 3. set payload size including LLC to DataSize
252 // 4. set some flags with RX_BLK_SET_FLAG()
254 VOID STAHandleRxDataFrame(
255 IN PRTMP_ADAPTER pAd,
258 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
259 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
260 PHEADER_802_11 pHeader = pRxBlk->pHeader;
261 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
262 BOOLEAN bFragment = FALSE;
263 MAC_TABLE_ENTRY *pEntry = NULL;
264 UCHAR FromWhichBSSID = BSS0;
265 UCHAR UserPriority = 0;
268 // before LINK UP, all DATA frames are rejected
269 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
272 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
276 // Drop not my BSS frames
277 if (pRxD->MyBss == 0)
281 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
286 pAd->RalinkCounters.RxCountSinceLastNULL++;
287 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
290 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
293 pData = (PUCHAR)pHeader + LENGTH_802_11;
294 if ((*pData >> 4) & 0x01)
296 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
297 pAd->CommonCfg.bInServicePeriod = FALSE;
299 // Force driver to fall into sleep mode when rcv EOSP frame
300 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
302 USHORT TbttNumToNextWakeUp;
303 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
306 NdisGetSystemUpTime(&Now);
307 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
309 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
310 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
311 TbttNumToNextWakeUp = NextDtim;
313 MlmeSetPsmBit(pAd, PWR_SAVE);
314 // if WMM-APSD is failed, try to disable following line
315 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
319 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
321 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
325 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
326 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
329 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
333 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
337 // Infrastructure mode, check address 2 for BSSID
338 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
340 // Receive frame not my BSSID
342 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
346 else // Ad-Hoc mode or Not associated
348 // Ad-Hoc mode, check address 3 for BSSID
349 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
351 // Receive frame not my BSSID
353 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
361 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
363 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
367 // 1. release packet if infra mode
368 // 2. new a pEntry if ad-hoc mode
369 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
376 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
377 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
380 // check Atheros Client
381 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
383 pEntry->bIAmBadAtheros = TRUE;
384 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
385 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
386 if (!STA_AES_ON(pAd))
388 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
393 pRxBlk->pData = (UCHAR *)pHeader;
396 // update RxBlk->pData, DataSize
397 // 802.11 Header, QOS, HTC, Hw Padding
400 // 1. skip 802.11 HEADER
402 pRxBlk->pData += LENGTH_802_11;
403 pRxBlk->DataSize -= LENGTH_802_11;
407 if (pHeader->FC.SubType & 0x08)
409 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
410 UserPriority = *(pRxBlk->pData) & 0x0f;
411 // bit 7 in QoS Control field signals the HT A-MSDU format
412 if ((*pRxBlk->pData) & 0x80)
414 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
417 // skip QOS contorl field
419 pRxBlk->DataSize -=2;
421 pRxBlk->UserPriority = UserPriority;
423 // 3. Order bit: A-Ralink or HTC+
424 if (pHeader->FC.Order)
426 #ifdef AGGREGATION_SUPPORT
427 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
429 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
434 #ifdef DOT11_N_SUPPORT
435 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
436 // skip HTC contorl field
438 pRxBlk->DataSize -= 4;
439 #endif // DOT11_N_SUPPORT //
443 // 4. skip HW padding
446 // just move pData pointer
447 // because DataSize excluding HW padding
448 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
452 #ifdef DOT11_N_SUPPORT
455 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
457 #endif // DOT11_N_SUPPORT //
461 // Case I Process Broadcast & Multicast data frame
463 if (pRxD->Bcast || pRxD->Mcast)
465 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
467 // Drop Mcast/Bcast frame with fragment bit on
468 if (pHeader->FC.MoreFrag)
471 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
475 // Filter out Bcast frame which AP relayed for us
476 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
479 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
483 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
488 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
492 pEntry = MacTableLookup(pAd, pHeader->Addr2);
494 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
498 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
500 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
501 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
503 pAd->RalinkCounters.OneSecRxOkDataCnt++;
506 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
508 // re-assemble the fragmented packets
509 // return complete frame (pRxPacket) or NULL
511 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
516 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
518 // process complete frame
519 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
522 pRxBlk->DataSize -= 8;
524 // For TKIP frame, calculate the MIC value
525 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
531 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
537 // because RTMPDeFragmentDataFrame() will release rx packet,
538 // if packet is fragmented
545 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
548 VOID STAHandleRxMgmtFrame(
549 IN PRTMP_ADAPTER pAd,
552 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
553 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
554 PHEADER_802_11 pHeader = pRxBlk->pHeader;
555 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
560 // We should collect RSSI not only U2M data but also my beacon
561 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
563 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
565 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
566 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
569 // First check the size, it MUST not exceed the mlme queue size
570 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
572 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
576 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
577 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
580 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
583 VOID STAHandleRxControlFrame(
584 IN PRTMP_ADAPTER pAd,
587 #ifdef DOT11_N_SUPPORT
588 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
589 #endif // DOT11_N_SUPPORT //
590 PHEADER_802_11 pHeader = pRxBlk->pHeader;
591 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
593 switch (pHeader->FC.SubType)
595 case SUBTYPE_BLOCK_ACK_REQ:
596 #ifdef DOT11_N_SUPPORT
598 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
601 #endif // DOT11_N_SUPPORT //
602 case SUBTYPE_BLOCK_ACK:
608 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
613 ========================================================================
616 Process RxDone interrupt, running in DPC level
619 pAd Pointer to our adapter
624 IRQL = DISPATCH_LEVEL
627 This routine has to maintain Rx ring read pointer.
628 Need to consider QOS DATA format when converting to 802.3
629 ========================================================================
631 BOOLEAN STARxDoneInterruptHandle(
632 IN PRTMP_ADAPTER pAd,
636 UINT32 RxProcessed, RxPending;
637 BOOLEAN bReschedule = FALSE;
638 RT28XX_RXD_STRUC *pRxD;
641 PNDIS_PACKET pRxPacket;
642 PHEADER_802_11 pHeader;
645 RxProcessed = RxPending = 0;
647 // process whole rx ring
651 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
652 fRTMP_ADAPTER_RESET_IN_PROGRESS |
653 fRTMP_ADAPTER_HALT_IN_PROGRESS |
654 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
655 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
660 if (RxProcessed++ > MAX_RX_PROCESS_CNT)
662 // need to reschedule rx handle
667 RxProcessed ++; // test
669 // 1. allocate a new data packet into rx ring to replace received packet
670 // then processing the received packet
671 // 2. the callee must take charge of release of packet
672 // 3. As far as driver is concerned ,
673 // the rx packet must
674 // a. be indicated to upper layer or
675 // b. be released if it is discarded
676 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
677 if (pRxPacket == NULL)
679 // no more packet to process
683 // get rx ring descriptor
684 pRxD = &(RxCell.RxD);
685 // get rx data buffer
686 pData = GET_OS_PKT_DATAPTR(pRxPacket);
687 pRxWI = (PRXWI_STRUC) pData;
688 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
691 RxCell.pRxWI = pRxWI;
692 RxCell.pHeader = pHeader;
693 RxCell.pRxPacket = pRxPacket;
694 RxCell.pData = (UCHAR *) pHeader;
695 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
698 // Increase Total receive byte counter after real data received no mater any error or not
699 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
700 pAd->RalinkCounters.RxCount ++;
702 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
704 if (pRxWI->MPDUtotalByteCount < 14)
705 Status = NDIS_STATUS_FAILURE;
709 send_monitor_packets(pAd, &RxCell);
712 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
714 // Check for all RxD errors
715 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
717 // Handle the received frame
718 if (Status == NDIS_STATUS_SUCCESS)
720 switch (pHeader->FC.Type)
722 // CASE I, receive a DATA frame
725 // process DATA frame
726 STAHandleRxDataFrame(pAd, &RxCell);
729 // CASE II, receive a MGMT frame
732 STAHandleRxMgmtFrame(pAd, &RxCell);
735 // CASE III. receive a CNTL frame
738 STAHandleRxControlFrame(pAd, &RxCell);
741 // discard other type
743 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
749 pAd->Counters8023.RxErrors++;
750 // discard this frame
751 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
755 // fRTMP_PS_GO_TO_SLEEP_NOW is set if receiving beacon.
756 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW) && (INFRA_ON(pAd)))
758 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
759 AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp);
766 ========================================================================
770 pAd Pointer to our adapter
772 IRQL = DISPATCH_LEVEL
774 ========================================================================
776 VOID RTMPHandleTwakeupInterrupt(
777 IN PRTMP_ADAPTER pAd)
779 AsicForceWakeup(pAd, DOT11POWERSAVE);
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];
817 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
818 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
819 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
821 // Drop send request since hardware is in reset state
824 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
826 // Drop send request since there are no physical connection yet
831 // Record that orignal packet source is from NDIS layer,so that
832 // later on driver knows how to release this NDIS PACKET
833 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
834 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
835 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
836 pAd->RalinkCounters.PendingNdisPacketCount++;
842 if (allowToSend == TRUE)
843 STASendPacket(pAd, pPacket);
845 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
848 // Dequeue outgoing frames from TxSwQueue[] and process it
849 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
855 ========================================================================
857 This routine is used to do packet parsing and classification for Tx packet
858 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
862 pAd Pointer to our adapter
863 pPacket Pointer to send packet
866 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
867 NDIS_STATUS_FAILURE If failed to do en-queue.
870 You only can put OS-indepened & STA related code in here.
871 ========================================================================
873 NDIS_STATUS STASendPacket(
874 IN PRTMP_ADAPTER pAd,
875 IN PNDIS_PACKET pPacket)
877 PACKET_INFO PacketInfo;
882 UCHAR QueIdx, UserPriority;
883 MAC_TABLE_ENTRY *pEntry = NULL;
884 unsigned int IrqFlags;
888 // Prepare packet information structure for buffer descriptor
889 // chained within a single NDIS packet.
890 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
892 if (pSrcBufVA == NULL)
894 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
895 // Resourece is low, system did not allocate virtual address
896 // return NDIS_STATUS_FAILURE directly to upper layer
897 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
898 return NDIS_STATUS_FAILURE;
904 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
905 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
906 return (NDIS_STATUS_FAILURE);
909 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
910 // Note multicast packets in adhoc also use BSSID_WCID index.
915 pEntry = &pAd->MacTab.Content[BSSID_WCID];
916 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
917 Rate = pAd->CommonCfg.TxRate;
920 else if (ADHOC_ON(pAd))
922 if (*pSrcBufVA & 0x01)
924 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
925 pEntry = &pAd->MacTab.Content[MCAST_WCID];
929 pEntry = MacTableLookup(pAd, pSrcBufVA);
931 Rate = pAd->CommonCfg.TxRate;
937 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
938 // Resourece is low, system did not allocate virtual address
939 // return NDIS_STATUS_FAILURE directly to upper layer
940 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
941 return NDIS_STATUS_FAILURE;
947 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
951 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
952 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
953 RTMPCheckEtherType(pAd, pPacket);
958 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
960 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
961 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
962 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
963 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
964 #ifdef WPA_SUPPLICANT_SUPPORT
965 || (pAd->StaCfg.IEEE8021X == TRUE)
966 #endif // WPA_SUPPLICANT_SUPPORT //
968 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
969 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
972 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
973 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
975 return (NDIS_STATUS_FAILURE);
979 // STEP 1. Decide number of fragments required to deliver this MSDU.
980 // The estimation here is not very accurate because difficult to
981 // take encryption overhead into consideration here. The result
982 // "NumberOfFrag" is then just used to pre-check if enough free
983 // TXD are available to hold this MSDU.
986 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
988 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
989 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
990 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
991 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
992 #ifdef DOT11_N_SUPPORT
993 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
994 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
995 #endif // DOT11_N_SUPPORT //
998 // The calculated "NumberOfFrag" is a rough estimation because of various
999 // encryption/encapsulation overhead not taken into consideration. This number is just
1000 // used to make sure enough free TXD are available before fragmentation takes place.
1001 // In case the actual required number of fragments of an NDIS packet
1002 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1003 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1004 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1005 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1007 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1008 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1009 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1010 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1016 // Save fragment number to Ndis packet reserved field
1017 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1020 // STEP 2. Check the requirement of RTS:
1021 // If multiple fragment required, RTS is required only for the first fragment
1022 // if the fragment size large than RTS threshold
1023 // For RT28xx, Let ASIC send RTS/CTS
1024 RTMP_SET_PACKET_RTS(pPacket, 0);
1025 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1028 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1032 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1035 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1038 // get Ethernet protocol field
1039 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1040 if (Protocol <= 1500)
1042 // get Ethernet protocol field from LLC/SNAP
1043 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1046 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1050 // always AC_BE for non-IP packet
1051 if (Protocol != 0x0800)
1055 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1058 // return AC_BE if packet is not IPv4
1059 if ((Byte0 & 0xf0) != 0x40)
1063 UserPriority = (Byte1 & 0xe0) >> 5;
1064 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1066 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1067 // TODO: downgrade UP & QueIdx before passing ACM
1068 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1076 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1080 // Make sure SendTxWait queue resource won't be used by other threads
1081 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1082 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1084 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1085 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1087 return NDIS_STATUS_FAILURE;
1091 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1093 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1095 #ifdef DOT11_N_SUPPORT
1096 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1097 (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1099 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1100 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1101 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1102 // For IOT compatibility, if
1103 // 1. It is Ralink chip or
1104 // 2. It is OPEN or AES mode,
1105 // then BA session can be bulit.
1106 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1107 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1110 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1113 #endif // DOT11_N_SUPPORT //
1115 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1116 return NDIS_STATUS_SUCCESS;
1121 ========================================================================
1123 Routine Description:
1124 This subroutine will scan through releative ring descriptor to find
1125 out avaliable free ring descriptor and compare with request size.
1128 pAd Pointer to our adapter
1129 QueIdx Selected TX Ring
1132 NDIS_STATUS_FAILURE Not enough free descriptor
1133 NDIS_STATUS_SUCCESS Enough free descriptor
1135 IRQL = PASSIVE_LEVEL
1136 IRQL = DISPATCH_LEVEL
1140 ========================================================================
1142 NDIS_STATUS RTMPFreeTXDRequest(
1143 IN PRTMP_ADAPTER pAd,
1145 IN UCHAR NumberRequired,
1146 IN PUCHAR FreeNumberIs)
1148 ULONG FreeNumber = 0;
1149 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1158 if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1159 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1161 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1163 if (FreeNumber >= NumberRequired)
1164 Status = NDIS_STATUS_SUCCESS;
1168 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1169 FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1171 FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1173 if (FreeNumber >= NumberRequired)
1174 Status = NDIS_STATUS_SUCCESS;
1178 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1181 *FreeNumberIs = (UCHAR)FreeNumber;
1188 VOID RTMPSendDisassociationFrame(
1189 IN PRTMP_ADAPTER pAd)
1193 VOID RTMPSendNullFrame(
1194 IN PRTMP_ADAPTER pAd,
1196 IN BOOLEAN bQosNull)
1198 UCHAR NullFrame[48];
1200 PHEADER_802_11 pHeader_802_11;
1202 // WPA 802.1x secured port control
1203 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1204 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1205 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1206 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1207 #ifdef WPA_SUPPLICANT_SUPPORT
1208 || (pAd->StaCfg.IEEE8021X == TRUE)
1211 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1216 NdisZeroMemory(NullFrame, 48);
1217 Length = sizeof(HEADER_802_11);
1219 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1221 pHeader_802_11->FC.Type = BTYPE_DATA;
1222 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1223 pHeader_802_11->FC.ToDs = 1;
1224 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1225 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1226 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1228 if (pAd->CommonCfg.bAPSDForcePowerSave)
1230 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1234 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1236 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1239 pHeader_802_11->Sequence = pAd->Sequence;
1241 // Prepare QosNull function frame
1244 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1246 // copy QOS control bytes
1247 NullFrame[Length] = 0;
1248 NullFrame[Length+1] = 0;
1249 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1252 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1256 // IRQL = DISPATCH_LEVEL
1257 VOID RTMPSendRTSFrame(
1258 IN PRTMP_ADAPTER pAd,
1260 IN unsigned int NextMpduSize,
1263 IN USHORT AckDuration,
1271 // --------------------------------------------------------
1272 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1273 // Find the WPA key, either Group or Pairwise Key
1274 // LEAP + TKIP also use WPA key.
1275 // --------------------------------------------------------
1276 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1277 // In Cisco CCX 2.0 Leap Authentication
1278 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1279 // Instead of the SharedKey, SharedKey Length may be Zero.
1280 VOID STAFindCipherAlgorithm(
1281 IN PRTMP_ADAPTER pAd,
1284 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1285 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1286 UCHAR KeyIdx = 0xff;
1288 PCIPHER_KEY pKey = NULL;
1290 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1294 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1295 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1297 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1299 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1301 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1303 // 4-way handshaking frame must be clear
1304 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1305 (pAd->SharedKey[BSS0][0].KeyLen))
1307 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1311 else if (Cipher == Ndis802_11Encryption1Enabled)
1313 KeyIdx = pAd->StaCfg.DefaultKeyId;
1315 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1316 (Cipher == Ndis802_11Encryption3Enabled))
1318 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1319 KeyIdx = pAd->StaCfg.DefaultKeyId;
1320 else if (pAd->SharedKey[BSS0][0].KeyLen)
1323 KeyIdx = pAd->StaCfg.DefaultKeyId;
1327 CipherAlg = CIPHER_NONE;
1328 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1329 CipherAlg = CIPHER_NONE;
1330 #ifdef WPA_SUPPLICANT_SUPPORT
1331 else if ( pAd->StaCfg.WpaSupplicantUP &&
1332 (Cipher == Ndis802_11Encryption1Enabled) &&
1333 (pAd->StaCfg.IEEE8021X == TRUE) &&
1334 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1335 CipherAlg = CIPHER_NONE;
1336 #endif // WPA_SUPPLICANT_SUPPORT //
1339 //Header_802_11.FC.Wep = 1;
1340 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1341 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1345 pTxBlk->CipherAlg = CipherAlg;
1346 pTxBlk->pKey = pKey;
1350 VOID STABuildCommon802_11Header(
1351 IN PRTMP_ADAPTER pAd,
1354 HEADER_802_11 *pHeader_802_11;
1357 // MAKE A COMMON 802.11 HEADER
1360 // normal wlan header size : 24 octets
1361 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1363 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1365 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1367 pHeader_802_11->FC.FrDs = 0;
1368 pHeader_802_11->FC.Type = BTYPE_DATA;
1369 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1371 if (pTxBlk->pMacEntry)
1373 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1375 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1376 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1381 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1382 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1388 pHeader_802_11->Sequence = pAd->Sequence;
1389 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1392 pHeader_802_11->Frag = 0;
1394 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1400 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1401 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1402 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1403 pHeader_802_11->FC.ToDs = 1;
1406 else if (ADHOC_ON(pAd))
1408 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1409 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1410 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1411 pHeader_802_11->FC.ToDs = 0;
1415 if (pTxBlk->CipherAlg != CIPHER_NONE)
1416 pHeader_802_11->FC.Wep = 1;
1418 // -----------------------------------------------------------------
1419 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1420 // -----------------------------------------------------------------
1421 if (pAd->CommonCfg.bAPSDForcePowerSave)
1422 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1424 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1427 #ifdef DOT11_N_SUPPORT
1428 VOID STABuildCache802_11Header(
1429 IN RTMP_ADAPTER *pAd,
1433 MAC_TABLE_ENTRY *pMacEntry;
1434 PHEADER_802_11 pHeader80211;
1436 pHeader80211 = (PHEADER_802_11)pHeader;
1437 pMacEntry = pTxBlk->pMacEntry;
1440 // Update the cached 802.11 HEADER
1443 // normal wlan header size : 24 octets
1444 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1447 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1450 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1451 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1454 // The addr3 of normal packet send from DS is Dest Mac address.
1456 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1458 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1461 // -----------------------------------------------------------------
1462 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1463 // -----------------------------------------------------------------
1464 if (pAd->CommonCfg.bAPSDForcePowerSave)
1465 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1467 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1469 #endif // DOT11_N_SUPPORT //
1471 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1472 IN RTMP_ADAPTER *pAd,
1475 PUCHAR pHeaderBufPtr;
1476 HEADER_802_11 *pHeader_802_11;
1477 PNDIS_PACKET pNextPacket;
1479 PQUEUE_ENTRY pQEntry;
1481 STAFindCipherAlgorithm(pAd, pTxBlk);
1482 STABuildCommon802_11Header(pAd, pTxBlk);
1485 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1486 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1488 // steal "order" bit to mark "aggregation"
1489 pHeader_802_11->FC.Order = 1;
1491 // skip common header
1492 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1494 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1497 // build QOS Control bytes
1499 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1501 *(pHeaderBufPtr+1) = 0;
1503 pTxBlk->MpduHeaderLen += 2;
1506 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1507 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1508 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1509 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1511 // For RA Aggregation,
1512 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1513 pQEntry = pTxBlk->TxPacketList.Head;
1514 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1515 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1516 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1517 nextBufLen -= LENGTH_802_1Q;
1519 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1520 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1523 pTxBlk->MpduHeaderLen += 2;
1525 return pHeaderBufPtr;
1529 #ifdef DOT11_N_SUPPORT
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 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1720 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1722 pAd->RalinkCounters.KickTxCount++;
1723 pAd->RalinkCounters.OneSecTxDoneCount++;
1729 VOID STA_AMSDU_Frame_Tx(
1730 IN PRTMP_ADAPTER pAd,
1733 PUCHAR pHeaderBufPtr;
1735 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1736 USHORT totalMPDUSize=0;
1737 UCHAR *subFrameHeader;
1739 USHORT FirstTx = 0, LastTxIdx = 0;
1742 PQUEUE_ENTRY pQEntry;
1747 ASSERT((pTxBlk->TxPacketList.Number > 1));
1749 while(pTxBlk->TxPacketList.Head)
1751 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1752 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1753 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1755 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1759 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1761 // skip 802.3 header
1762 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1763 pTxBlk->SrcBufLen -= LENGTH_802_3;
1768 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1769 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1774 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1776 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1777 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1781 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1782 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1783 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1784 pHeaderBufPtr += padding;
1785 pTxBlk->MpduHeaderLen = padding;
1790 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1792 subFrameHeader = pHeaderBufPtr;
1793 subFramePayloadLen = pTxBlk->SrcBufLen;
1795 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1798 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1799 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1803 // Insert LLC-SNAP encapsulation - 8 octets
1805 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1807 subFramePayloadLen = pTxBlk->SrcBufLen;
1809 if (pTxBlk->pExtraLlcSnapEncap)
1811 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1813 // get 2 octets (TypeofLen)
1814 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1816 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1817 subFramePayloadLen += LENGTH_802_1_H;
1820 // update subFrame Length field
1821 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1822 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1824 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1827 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1829 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1833 pAd->RalinkCounters.KickTxCount++;
1834 pAd->RalinkCounters.OneSecTxDoneCount++;
1836 // calculate Transmitted AMSDU Count and ByteCount
1838 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1839 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1844 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1845 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1850 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1851 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1853 #endif // DOT11_N_SUPPORT //
1855 VOID STA_Legacy_Frame_Tx(
1856 IN PRTMP_ADAPTER pAd,
1859 HEADER_802_11 *pHeader_802_11;
1860 PUCHAR pHeaderBufPtr;
1863 PQUEUE_ENTRY pQEntry;
1868 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1869 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1870 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1872 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1876 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1878 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1881 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1882 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1884 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1886 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1888 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1889 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1891 STAFindCipherAlgorithm(pAd, pTxBlk);
1892 STABuildCommon802_11Header(pAd, pTxBlk);
1895 // skip 802.3 header
1896 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1897 pTxBlk->SrcBufLen -= LENGTH_802_3;
1902 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1903 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1906 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1907 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1909 // skip common header
1910 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1912 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1915 // build QOS Control bytes
1917 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1918 *(pHeaderBufPtr+1) = 0;
1920 pTxBlk->MpduHeaderLen += 2;
1923 // The remaining content of MPDU header should locate at 4-octets aligment
1924 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1925 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1926 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1931 // Insert LLC-SNAP encapsulation - 8 octets
1934 // if original Ethernet frame contains no LLC/SNAP,
1935 // then an extra LLC/SNAP encap is required
1937 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
1938 if (pTxBlk->pExtraLlcSnapEncap)
1942 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1945 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
1946 // get 2 octets (TypeofLen)
1947 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
1949 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1956 // use Wcid as Key Index
1959 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1961 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1963 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1965 pAd->RalinkCounters.KickTxCount++;
1966 pAd->RalinkCounters.OneSecTxDoneCount++;
1971 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1972 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1976 VOID STA_ARalink_Frame_Tx(
1977 IN PRTMP_ADAPTER pAd,
1980 PUCHAR pHeaderBufPtr;
1982 USHORT totalMPDUSize=0;
1983 USHORT FirstTx, LastTxIdx;
1986 PQUEUE_ENTRY pQEntry;
1991 ASSERT((pTxBlk->TxPacketList.Number== 2));
1994 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
1995 while(pTxBlk->TxPacketList.Head)
1997 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1998 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2000 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2002 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2006 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2008 // skip 802.3 header
2009 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2010 pTxBlk->SrcBufLen -= LENGTH_802_3;
2015 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2016 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2020 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2022 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2024 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2025 // will be updated after final frame was handled.
2026 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2030 // Insert LLC-SNAP encapsulation - 8 octets
2032 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2034 if (pTxBlk->pExtraLlcSnapEncap)
2036 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2038 // get 2 octets (TypeofLen)
2039 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2041 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2045 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2047 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2048 pTxBlk->MpduHeaderLen = 0;
2050 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2051 // DA(6)+SA(6)+FrameType(2)
2052 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2053 pHeaderBufPtr += 12;
2054 // get 2 octets (TypeofLen)
2055 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2057 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2060 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2062 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2064 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2066 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2070 pAd->RalinkCounters.OneSecTxAggregationCount++;
2071 pAd->RalinkCounters.KickTxCount++;
2072 pAd->RalinkCounters.OneSecTxDoneCount++;
2076 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2077 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2082 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2083 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2088 VOID STA_Fragment_Frame_Tx(
2089 IN RTMP_ADAPTER *pAd,
2092 HEADER_802_11 *pHeader_802_11;
2093 PUCHAR pHeaderBufPtr;
2096 PACKET_INFO PacketInfo;
2097 USHORT EncryptionOverhead = 0;
2098 UINT32 FreeMpduSize, SrcRemainingBytes;
2102 PQUEUE_ENTRY pQEntry;
2107 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2108 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2109 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2111 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2115 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2116 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2118 STAFindCipherAlgorithm(pAd, pTxBlk);
2119 STABuildCommon802_11Header(pAd, pTxBlk);
2121 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2123 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2124 if (pTxBlk->pPacket == NULL)
2126 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2129 // skip 802.3 header
2130 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2131 pTxBlk->SrcBufLen -= LENGTH_802_3;
2137 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2138 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2141 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2142 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2145 // skip common header
2146 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2148 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2151 // build QOS Control bytes
2153 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2155 *(pHeaderBufPtr+1) = 0;
2157 pTxBlk->MpduHeaderLen += 2;
2161 // padding at front of LLC header
2162 // LLC header should locate at 4-octets aligment
2164 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2165 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2166 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2171 // Insert LLC-SNAP encapsulation - 8 octets
2174 // if original Ethernet frame contains no LLC/SNAP,
2175 // then an extra LLC/SNAP encap is required
2177 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2178 if (pTxBlk->pExtraLlcSnapEncap)
2182 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2185 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2186 // get 2 octets (TypeofLen)
2187 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2189 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2193 // If TKIP is used and fragmentation is required. Driver has to
2194 // append TKIP MIC at tail of the scatter buffer
2195 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2196 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2199 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2200 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2201 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2202 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2203 pTxBlk->SrcBufLen += 8;
2204 pTxBlk->TotalFrameLen += 8;
2205 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2209 // calcuate the overhead bytes that encryption algorithm may add. This
2210 // affects the calculate of "duration" field
2212 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2213 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2214 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2215 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2216 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2217 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2218 else if (pTxBlk->CipherAlg == CIPHER_AES)
2219 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2221 EncryptionOverhead = 0;
2223 // decide how much time an ACK/CTS frame will consume in the air
2224 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2226 // Init the total payload length of this frame.
2227 SrcRemainingBytes = pTxBlk->SrcBufLen;
2229 pTxBlk->TotalFragNum = 0xff;
2233 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2235 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2237 if (SrcRemainingBytes <= FreeMpduSize)
2238 { // this is the last or only fragment
2240 pTxBlk->SrcBufLen = SrcRemainingBytes;
2242 pHeader_802_11->FC.MoreFrag = 0;
2243 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2245 // Indicate the lower layer that this's the last fragment.
2246 pTxBlk->TotalFragNum = fragNum;
2249 { // more fragment is required
2251 pTxBlk->SrcBufLen = FreeMpduSize;
2253 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2254 pHeader_802_11->FC.MoreFrag = 1;
2255 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2259 pTxBlk->FrameGap = IFS_HTTXOP;
2261 pTxBlk->FrameGap = IFS_SIFS;
2263 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2265 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2267 pAd->RalinkCounters.KickTxCount++;
2268 pAd->RalinkCounters.OneSecTxDoneCount++;
2270 // Update the frame number, remaining size of the NDIS packet payload.
2272 // space for 802.11 header.
2273 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2274 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2277 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2278 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2280 pHeader_802_11->Frag++; // increase Frag #
2282 }while(SrcRemainingBytes > 0);
2287 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2291 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2292 while(_pTxBlk->TxPacketList.Head) \
2294 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2295 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2300 ========================================================================
2302 Routine Description:
2303 Copy frame from waiting queue into relative ring buffer and set
2304 appropriate ASIC register to kick hardware encryption before really
2308 pAd Pointer to our adapter
2309 PNDIS_PACKET Pointer to outgoing Ndis frame
2310 NumberOfFrag Number of fragment required
2315 IRQL = DISPATCH_LEVEL
2319 ========================================================================
2321 NDIS_STATUS STAHardTransmit(
2322 IN PRTMP_ADAPTER pAd,
2326 NDIS_PACKET *pPacket;
2327 PQUEUE_ENTRY pQEntry;
2329 // ---------------------------------------------
2330 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2331 // ---------------------------------------------
2333 ASSERT(pTxBlk->TxPacketList.Number);
2334 if (pTxBlk->TxPacketList.Head == NULL)
2336 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2337 return NDIS_STATUS_FAILURE;
2340 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2342 // ------------------------------------------------------------------
2343 // STEP 1. WAKE UP PHY
2344 // outgoing frame always wakeup PHY to prevent frame lost and
2345 // turn off PSM bit to improve performance
2346 // ------------------------------------------------------------------
2347 // not to change PSM bit, just send this frame out?
2348 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2350 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2351 AsicForceWakeup(pAd, FROM_TX);
2354 // It should not change PSM bit, when APSD turn on.
2355 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2356 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2357 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2359 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2360 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2361 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2364 switch (pTxBlk->TxFrameType)
2366 #ifdef DOT11_N_SUPPORT
2367 case TX_AMPDU_FRAME:
2368 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2370 case TX_AMSDU_FRAME:
2371 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2373 #endif // DOT11_N_SUPPORT //
2374 case TX_LEGACY_FRAME:
2375 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2377 case TX_MCAST_FRAME:
2378 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2380 case TX_RALINK_FRAME:
2381 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2384 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2388 // It should not happened!
2389 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2390 while(pTxBlk->TxPacketList.Number)
2392 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2393 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2395 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2401 return (NDIS_STATUS_SUCCESS);
2405 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2407 unsigned char *word = value;
2408 unsigned int ret = 0;
2411 for(i=0; i < len; i++)
2414 ret ^=(unsigned int) (word[i]) << mod;
2415 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2420 VOID Sta_Announce_or_Forward_802_3_Packet(
2421 IN PRTMP_ADAPTER pAd,
2422 IN PNDIS_PACKET pPacket,
2423 IN UCHAR FromWhichBSSID)
2428 announce_802_3_packet(pAd, pPacket);
2433 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);