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"
42 VOID STARxEAPOLFrameIndicate(
44 IN MAC_TABLE_ENTRY *pEntry,
46 IN UCHAR FromWhichBSSID)
48 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
49 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
52 #ifdef WPA_SUPPLICANT_SUPPORT
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 //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
68 STA_PORT_SECURED(pAd);
70 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
72 idx = pAd->StaCfg.DesireSharedKeyId;
73 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
74 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
76 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
81 char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
82 NDIS_802_11_WEP keyinfo;
87 NdisZeroMemory(&WepKey, sizeof(WepKey));
88 len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
90 NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
91 pAd->StaCfg.DesireSharedKey[idx].Key,
92 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
94 WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
95 WepKey.keyinfo.KeyLength = len;
96 pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
98 pAd->IndicateMediaState = NdisMediaStateConnected;
99 pAd->ExtraInfo = GENERAL_LINK_UP;
100 // need to enqueue cmd to thread
101 RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
103 // For Preventing ShardKey Table is cleared by remove key procedure.
104 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
105 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
106 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
107 pAd->StaCfg.DesireSharedKey[idx].Key,
108 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
113 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
118 #endif // WPA_SUPPLICANT_SUPPORT //
120 // Special DATA frame that has to pass to MLME
121 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
122 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
124 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
125 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
126 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
127 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
131 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
136 VOID STARxDataFrameAnnounce(
137 IN PRTMP_ADAPTER pAd,
138 IN MAC_TABLE_ENTRY *pEntry,
140 IN UCHAR FromWhichBSSID)
144 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
147 // drop all non-EAP DATA frame before
148 // this client's Port-Access-Control is secured
149 if (pRxBlk->pHeader->FC.Wep)
151 // unsupported cipher suite
152 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
155 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
161 // encryption in-use but receive a non-EAPOL clear text frame, drop it
162 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
163 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
166 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
171 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
172 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
174 // Normal legacy, AMPDU or AMSDU
175 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
181 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
186 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
187 #ifdef DOT11_N_SUPPORT
188 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
190 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
193 #endif // DOT11_N_SUPPORT //
195 // Determin the destination of the EAP frame
196 // to WPA state machine or upper layer
197 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
203 // For TKIP frame, calculate the MIC value
204 BOOLEAN STACheckTkipMICValue(
205 IN PRTMP_ADAPTER pAd,
206 IN MAC_TABLE_ENTRY *pEntry,
209 PHEADER_802_11 pHeader = pRxBlk->pHeader;
210 UCHAR *pData = pRxBlk->pData;
211 USHORT DataSize = pRxBlk->DataSize;
212 UCHAR UserPriority = pRxBlk->UserPriority;
216 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
218 pDA = pHeader->Addr1;
219 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
221 pSA = pHeader->Addr3;
225 pSA = pHeader->Addr2;
228 if (RTMPTkipCompareMICValue(pAd,
236 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
238 #ifdef WPA_SUPPLICANT_SUPPORT
239 if (pAd->StaCfg.WpaSupplicantUP)
241 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
244 #endif // WPA_SUPPLICANT_SUPPORT //
246 RTMPReportMicError(pAd, pWpaKey);
250 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
259 // All Rx routines use RX_BLK structure to hande rx events
260 // It is very important to build pRxBlk attributes
261 // 1. pHeader pointer to 802.11 Header
262 // 2. pData pointer to payload including LLC (just skip Header)
263 // 3. set payload size including LLC to DataSize
264 // 4. set some flags with RX_BLK_SET_FLAG()
266 VOID STAHandleRxDataFrame(
267 IN PRTMP_ADAPTER pAd,
270 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
271 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
272 PHEADER_802_11 pHeader = pRxBlk->pHeader;
273 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
274 BOOLEAN bFragment = FALSE;
275 MAC_TABLE_ENTRY *pEntry = NULL;
276 UCHAR FromWhichBSSID = BSS0;
277 UCHAR UserPriority = 0;
280 // before LINK UP, all DATA frames are rejected
281 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
284 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
288 // Drop not my BSS frames
289 if (pRxD->MyBss == 0)
293 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
298 pAd->RalinkCounters.RxCountSinceLastNULL++;
299 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
302 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
305 pData = (PUCHAR)pHeader + LENGTH_802_11;
306 if ((*pData >> 4) & 0x01)
308 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
309 pAd->CommonCfg.bInServicePeriod = FALSE;
311 // Force driver to fall into sleep mode when rcv EOSP frame
312 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
314 USHORT TbttNumToNextWakeUp;
315 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
318 NdisGetSystemUpTime(&Now);
319 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
321 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
322 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
323 TbttNumToNextWakeUp = NextDtim;
325 MlmeSetPsmBit(pAd, PWR_SAVE);
326 // if WMM-APSD is failed, try to disable following line
327 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
331 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
333 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
337 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
338 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
341 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
345 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
349 // Infrastructure mode, check address 2 for BSSID
350 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
352 // Receive frame not my BSSID
354 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
358 else // Ad-Hoc mode or Not associated
360 // Ad-Hoc mode, check address 3 for BSSID
361 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
363 // Receive frame not my BSSID
365 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
373 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
375 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
379 // 1. release packet if infra mode
380 // 2. new a pEntry if ad-hoc mode
381 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
388 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
389 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
392 // check Atheros Client
393 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
395 pEntry->bIAmBadAtheros = TRUE;
396 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
397 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
398 if (!STA_AES_ON(pAd))
400 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
405 pRxBlk->pData = (UCHAR *)pHeader;
408 // update RxBlk->pData, DataSize
409 // 802.11 Header, QOS, HTC, Hw Padding
412 // 1. skip 802.11 HEADER
414 pRxBlk->pData += LENGTH_802_11;
415 pRxBlk->DataSize -= LENGTH_802_11;
419 if (pHeader->FC.SubType & 0x08)
421 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
422 UserPriority = *(pRxBlk->pData) & 0x0f;
423 // bit 7 in QoS Control field signals the HT A-MSDU format
424 if ((*pRxBlk->pData) & 0x80)
426 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
429 // skip QOS contorl field
431 pRxBlk->DataSize -=2;
433 pRxBlk->UserPriority = UserPriority;
435 // 3. Order bit: A-Ralink or HTC+
436 if (pHeader->FC.Order)
438 #ifdef AGGREGATION_SUPPORT
439 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
441 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
446 #ifdef DOT11_N_SUPPORT
447 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
448 // skip HTC contorl field
450 pRxBlk->DataSize -= 4;
451 #endif // DOT11_N_SUPPORT //
455 // 4. skip HW padding
458 // just move pData pointer
459 // because DataSize excluding HW padding
460 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
464 #ifdef DOT11_N_SUPPORT
467 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
469 #endif // DOT11_N_SUPPORT //
473 // Case I Process Broadcast & Multicast data frame
475 if (pRxD->Bcast || pRxD->Mcast)
477 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
479 // Drop Mcast/Bcast frame with fragment bit on
480 if (pHeader->FC.MoreFrag)
483 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
487 // Filter out Bcast frame which AP relayed for us
488 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
491 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
495 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
500 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
504 pEntry = MacTableLookup(pAd, pHeader->Addr2);
506 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
510 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
512 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
513 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
515 pAd->RalinkCounters.OneSecRxOkDataCnt++;
518 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
520 // re-assemble the fragmented packets
521 // return complete frame (pRxPacket) or NULL
523 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
528 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
530 // process complete frame
531 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
534 pRxBlk->DataSize -= 8;
536 // For TKIP frame, calculate the MIC value
537 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
543 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
549 // because RTMPDeFragmentDataFrame() will release rx packet,
550 // if packet is fragmented
557 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
560 VOID STAHandleRxMgmtFrame(
561 IN PRTMP_ADAPTER pAd,
564 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
565 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
566 PHEADER_802_11 pHeader = pRxBlk->pHeader;
567 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
572 // We should collect RSSI not only U2M data but also my beacon
573 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
575 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
577 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
578 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
581 // First check the size, it MUST not exceed the mlme queue size
582 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
584 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
588 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
589 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
592 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
595 VOID STAHandleRxControlFrame(
596 IN PRTMP_ADAPTER pAd,
599 #ifdef DOT11_N_SUPPORT
600 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
601 #endif // DOT11_N_SUPPORT //
602 PHEADER_802_11 pHeader = pRxBlk->pHeader;
603 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
605 switch (pHeader->FC.SubType)
607 case SUBTYPE_BLOCK_ACK_REQ:
608 #ifdef DOT11_N_SUPPORT
610 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
613 #endif // DOT11_N_SUPPORT //
614 case SUBTYPE_BLOCK_ACK:
620 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
625 ========================================================================
628 Process RxDone interrupt, running in DPC level
631 pAd Pointer to our adapter
636 IRQL = DISPATCH_LEVEL
639 This routine has to maintain Rx ring read pointer.
640 Need to consider QOS DATA format when converting to 802.3
641 ========================================================================
643 BOOLEAN STARxDoneInterruptHandle(
644 IN PRTMP_ADAPTER pAd,
648 UINT32 RxProcessed, RxPending;
649 BOOLEAN bReschedule = FALSE;
650 RT28XX_RXD_STRUC *pRxD;
653 PNDIS_PACKET pRxPacket;
654 PHEADER_802_11 pHeader;
657 RxProcessed = RxPending = 0;
659 // process whole rx ring
663 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
664 fRTMP_ADAPTER_RESET_IN_PROGRESS |
665 fRTMP_ADAPTER_HALT_IN_PROGRESS |
666 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
667 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
673 RxProcessed ++; // test
675 // 1. allocate a new data packet into rx ring to replace received packet
676 // then processing the received packet
677 // 2. the callee must take charge of release of packet
678 // 3. As far as driver is concerned ,
679 // the rx packet must
680 // a. be indicated to upper layer or
681 // b. be released if it is discarded
682 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
683 if (pRxPacket == NULL)
685 // no more packet to process
689 // get rx ring descriptor
690 pRxD = &(RxCell.RxD);
691 // get rx data buffer
692 pData = GET_OS_PKT_DATAPTR(pRxPacket);
693 pRxWI = (PRXWI_STRUC) pData;
694 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
697 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE);
698 RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI);
702 RxCell.pRxWI = pRxWI;
703 RxCell.pHeader = pHeader;
704 RxCell.pRxPacket = pRxPacket;
705 RxCell.pData = (UCHAR *) pHeader;
706 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
709 // Increase Total receive byte counter after real data received no mater any error or not
710 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
711 pAd->RalinkCounters.RxCount ++;
713 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
715 if (pRxWI->MPDUtotalByteCount < 14)
716 Status = NDIS_STATUS_FAILURE;
720 send_monitor_packets(pAd, &RxCell);
723 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
725 // Check for all RxD errors
726 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
728 // Handle the received frame
729 if (Status == NDIS_STATUS_SUCCESS)
731 switch (pHeader->FC.Type)
733 // CASE I, receive a DATA frame
736 // process DATA frame
737 STAHandleRxDataFrame(pAd, &RxCell);
740 // CASE II, receive a MGMT frame
743 STAHandleRxMgmtFrame(pAd, &RxCell);
746 // CASE III. receive a CNTL frame
749 STAHandleRxControlFrame(pAd, &RxCell);
752 // discard other type
754 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
760 pAd->Counters8023.RxErrors++;
761 // discard this frame
762 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
770 ========================================================================
774 pAd Pointer to our adapter
776 IRQL = DISPATCH_LEVEL
778 ========================================================================
780 VOID RTMPHandleTwakeupInterrupt(
781 IN PRTMP_ADAPTER pAd)
783 AsicForceWakeup(pAd, FALSE);
787 ========================================================================
789 Early checking and OS-depened parsing for Tx packet send to our STA driver.
792 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
793 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
794 UINT NumberOfPackets Number of packet in packet array.
800 This function do early checking and classification for send-out packet.
801 You only can put OS-depened & STA related code in here.
802 ========================================================================
805 IN NDIS_HANDLE MiniportAdapterContext,
806 IN PPNDIS_PACKET ppPacketArray,
807 IN UINT NumberOfPackets)
810 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
811 PNDIS_PACKET pPacket;
812 BOOLEAN allowToSend = FALSE;
815 for (Index = 0; Index < NumberOfPackets; Index++)
817 pPacket = ppPacketArray[Index];
821 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
822 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
823 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
825 // Drop send request since hardware is in reset state
828 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
830 // Drop send request since there are no physical connection yet
835 // Record that orignal packet source is from NDIS layer,so that
836 // later on driver knows how to release this NDIS PACKET
837 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
838 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
839 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
840 pAd->RalinkCounters.PendingNdisPacketCount++;
846 if (allowToSend == TRUE)
847 STASendPacket(pAd, pPacket);
849 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
852 // Dequeue outgoing frames from TxSwQueue[] and process it
853 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
859 ========================================================================
861 This routine is used to do packet parsing and classification for Tx packet
862 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
866 pAd Pointer to our adapter
867 pPacket Pointer to send packet
870 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
871 NDIS_STATUS_FAILURE If failed to do en-queue.
874 You only can put OS-indepened & STA related code in here.
875 ========================================================================
877 NDIS_STATUS STASendPacket(
878 IN PRTMP_ADAPTER pAd,
879 IN PNDIS_PACKET pPacket)
881 PACKET_INFO PacketInfo;
886 // UCHAR RTSRequired;
887 UCHAR QueIdx, UserPriority;
888 MAC_TABLE_ENTRY *pEntry = NULL;
889 unsigned int IrqFlags;
893 // Prepare packet information structure for buffer descriptor
894 // chained within a single NDIS packet.
895 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
897 if (pSrcBufVA == NULL)
899 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
900 // Resourece is low, system did not allocate virtual address
901 // return NDIS_STATUS_FAILURE directly to upper layer
902 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
903 return NDIS_STATUS_FAILURE;
909 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
910 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
911 return (NDIS_STATUS_FAILURE);
914 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
915 // Note multicast packets in adhoc also use BSSID_WCID index.
920 pEntry = &pAd->MacTab.Content[BSSID_WCID];
921 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
922 Rate = pAd->CommonCfg.TxRate;
925 else if (ADHOC_ON(pAd))
927 if (*pSrcBufVA & 0x01)
929 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
930 pEntry = &pAd->MacTab.Content[MCAST_WCID];
934 pEntry = MacTableLookup(pAd, pSrcBufVA);
936 Rate = pAd->CommonCfg.TxRate;
942 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
943 // Resourece is low, system did not allocate virtual address
944 // return NDIS_STATUS_FAILURE directly to upper layer
945 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
946 return NDIS_STATUS_FAILURE;
952 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
956 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
957 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
958 RTMPCheckEtherType(pAd, pPacket);
963 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
965 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
966 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
967 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
968 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
969 #ifdef WPA_SUPPLICANT_SUPPORT
970 || (pAd->StaCfg.IEEE8021X == TRUE)
971 #endif // WPA_SUPPLICANT_SUPPORT //
973 || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
974 #endif // LEAP_SUPPORT //
976 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
977 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
980 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
981 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
983 return (NDIS_STATUS_FAILURE);
987 // STEP 1. Decide number of fragments required to deliver this MSDU.
988 // The estimation here is not very accurate because difficult to
989 // take encryption overhead into consideration here. The result
990 // "NumberOfFrag" is then just used to pre-check if enough free
991 // TXD are available to hold this MSDU.
994 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
996 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
997 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
998 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
999 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1000 #ifdef DOT11_N_SUPPORT
1001 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1002 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1003 #endif // DOT11_N_SUPPORT //
1006 // The calculated "NumberOfFrag" is a rough estimation because of various
1007 // encryption/encapsulation overhead not taken into consideration. This number is just
1008 // used to make sure enough free TXD are available before fragmentation takes place.
1009 // In case the actual required number of fragments of an NDIS packet
1010 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1011 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1012 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1013 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1015 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1016 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1017 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1018 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1024 // Save fragment number to Ndis packet reserved field
1025 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1028 // STEP 2. Check the requirement of RTS:
1029 // If multiple fragment required, RTS is required only for the first fragment
1030 // if the fragment size large than RTS threshold
1031 // For RT28xx, Let ASIC send RTS/CTS
1032 RTMP_SET_PACKET_RTS(pPacket, 0);
1033 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1036 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1040 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1041 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1044 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1047 // get Ethernet protocol field
1048 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1049 if (Protocol <= 1500)
1051 // get Ethernet protocol field from LLC/SNAP
1052 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1055 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1059 // always AC_BE for non-IP packet
1060 if (Protocol != 0x0800)
1064 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1067 // return AC_BE if packet is not IPv4
1068 if ((Byte0 & 0xf0) != 0x40)
1072 UserPriority = (Byte1 & 0xe0) >> 5;
1073 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1075 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1076 // TODO: downgrade UP & QueIdx before passing ACM
1077 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1085 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1089 // Make sure SendTxWait queue resource won't be used by other threads
1090 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1091 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1093 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1094 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1096 return NDIS_STATUS_FAILURE;
1100 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1102 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1104 #ifdef DOT11_N_SUPPORT
1105 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1108 //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID];
1109 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1110 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1111 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1112 // For IOT compatibility, if
1113 // 1. It is Ralink chip or
1114 // 2. It is OPEN or AES mode,
1115 // then BA session can be bulit.
1116 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1117 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1120 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1123 #endif // DOT11_N_SUPPORT //
1125 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1126 return NDIS_STATUS_SUCCESS;
1131 ========================================================================
1133 Routine Description:
1134 This subroutine will scan through releative ring descriptor to find
1135 out avaliable free ring descriptor and compare with request size.
1138 pAd Pointer to our adapter
1139 QueIdx Selected TX Ring
1142 NDIS_STATUS_FAILURE Not enough free descriptor
1143 NDIS_STATUS_SUCCESS Enough free descriptor
1145 IRQL = PASSIVE_LEVEL
1146 IRQL = DISPATCH_LEVEL
1150 ========================================================================
1155 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1156 If no frame need to send, go to sleep, else, still wake up.
1158 NDIS_STATUS RTMPFreeTXDRequest(
1159 IN PRTMP_ADAPTER pAd,
1161 IN UCHAR NumberRequired,
1162 IN PUCHAR FreeNumberIs)
1164 //ULONG FreeNumber = 0;
1165 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1166 unsigned long IrqFlags;
1167 HT_TX_CONTEXT *pHTTXContext;
1177 pHTTXContext = &pAd->TxContext[QueIdx];
1178 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1179 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1180 (pHTTXContext->IRPPending == TRUE))
1182 Status = NDIS_STATUS_FAILURE;
1186 Status = NDIS_STATUS_SUCCESS;
1188 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1193 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1194 Status = NDIS_STATUS_FAILURE;
1196 Status = NDIS_STATUS_SUCCESS;
1200 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1210 VOID RTMPSendDisassociationFrame(
1211 IN PRTMP_ADAPTER pAd)
1215 VOID RTMPSendNullFrame(
1216 IN PRTMP_ADAPTER pAd,
1218 IN BOOLEAN bQosNull)
1220 UCHAR NullFrame[48];
1222 PHEADER_802_11 pHeader_802_11;
1224 // WPA 802.1x secured port control
1225 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1226 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1227 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1228 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1229 #ifdef WPA_SUPPLICANT_SUPPORT
1230 || (pAd->StaCfg.IEEE8021X == TRUE)
1233 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1238 NdisZeroMemory(NullFrame, 48);
1239 Length = sizeof(HEADER_802_11);
1241 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1243 pHeader_802_11->FC.Type = BTYPE_DATA;
1244 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1245 pHeader_802_11->FC.ToDs = 1;
1246 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1247 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1248 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1250 if (pAd->CommonCfg.bAPSDForcePowerSave)
1252 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1256 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1258 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1261 pHeader_802_11->Sequence = pAd->Sequence;
1263 // Prepare QosNull function frame
1266 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1268 // copy QOS control bytes
1269 NullFrame[Length] = 0;
1270 NullFrame[Length+1] = 0;
1271 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1274 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1278 // IRQL = DISPATCH_LEVEL
1279 VOID RTMPSendRTSFrame(
1280 IN PRTMP_ADAPTER pAd,
1282 IN unsigned int NextMpduSize,
1285 IN USHORT AckDuration,
1293 // --------------------------------------------------------
1294 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1295 // Find the WPA key, either Group or Pairwise Key
1296 // LEAP + TKIP also use WPA key.
1297 // --------------------------------------------------------
1298 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1299 // In Cisco CCX 2.0 Leap Authentication
1300 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1301 // Instead of the SharedKey, SharedKey Length may be Zero.
1302 VOID STAFindCipherAlgorithm(
1303 IN PRTMP_ADAPTER pAd,
1306 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1307 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1308 UCHAR KeyIdx = 0xff;
1310 PCIPHER_KEY pKey = NULL;
1312 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1316 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1317 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1319 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1321 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1323 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1325 // 4-way handshaking frame must be clear
1326 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1327 (pAd->SharedKey[BSS0][0].KeyLen))
1329 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1333 else if (Cipher == Ndis802_11Encryption1Enabled)
1336 if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1338 if (LEAP_CCKM_ON(pAd))
1340 if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1346 KeyIdx = pAd->StaCfg.DefaultKeyId;
1348 else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1349 KeyIdx = pAd->StaCfg.DefaultKeyId;
1350 else if (LEAP_CCKM_ON(pAd))
1352 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1357 else // standard WEP64 or WEP128
1358 #endif // LEAP_SUPPORT //
1359 KeyIdx = pAd->StaCfg.DefaultKeyId;
1361 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1362 (Cipher == Ndis802_11Encryption3Enabled))
1364 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1365 KeyIdx = pAd->StaCfg.DefaultKeyId;
1366 else if (pAd->SharedKey[BSS0][0].KeyLen)
1369 KeyIdx = pAd->StaCfg.DefaultKeyId;
1373 CipherAlg = CIPHER_NONE;
1374 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1375 CipherAlg = CIPHER_NONE;
1376 #ifdef WPA_SUPPLICANT_SUPPORT
1377 else if ( pAd->StaCfg.WpaSupplicantUP &&
1378 (Cipher == Ndis802_11Encryption1Enabled) &&
1379 (pAd->StaCfg.IEEE8021X == TRUE) &&
1380 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1381 CipherAlg = CIPHER_NONE;
1382 #endif // WPA_SUPPLICANT_SUPPORT //
1385 //Header_802_11.FC.Wep = 1;
1386 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1387 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1391 pTxBlk->CipherAlg = CipherAlg;
1392 pTxBlk->pKey = pKey;
1396 VOID STABuildCommon802_11Header(
1397 IN PRTMP_ADAPTER pAd,
1400 HEADER_802_11 *pHeader_802_11;
1403 // MAKE A COMMON 802.11 HEADER
1406 // normal wlan header size : 24 octets
1407 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1409 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1411 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1413 pHeader_802_11->FC.FrDs = 0;
1414 pHeader_802_11->FC.Type = BTYPE_DATA;
1415 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1417 if (pTxBlk->pMacEntry)
1419 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1421 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1422 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1426 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1427 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1432 pHeader_802_11->Sequence = pAd->Sequence;
1433 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1436 pHeader_802_11->Frag = 0;
1438 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1444 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1445 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1446 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1447 pHeader_802_11->FC.ToDs = 1;
1450 else if (ADHOC_ON(pAd))
1452 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1453 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1454 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1455 pHeader_802_11->FC.ToDs = 0;
1459 if (pTxBlk->CipherAlg != CIPHER_NONE)
1460 pHeader_802_11->FC.Wep = 1;
1462 // -----------------------------------------------------------------
1463 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1464 // -----------------------------------------------------------------
1465 if (pAd->CommonCfg.bAPSDForcePowerSave)
1466 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1468 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1471 #ifdef DOT11_N_SUPPORT
1472 VOID STABuildCache802_11Header(
1473 IN RTMP_ADAPTER *pAd,
1477 MAC_TABLE_ENTRY *pMacEntry;
1478 PHEADER_802_11 pHeader80211;
1480 pHeader80211 = (PHEADER_802_11)pHeader;
1481 pMacEntry = pTxBlk->pMacEntry;
1484 // Update the cached 802.11 HEADER
1487 // normal wlan header size : 24 octets
1488 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1491 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1494 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1495 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1498 // The addr3 of normal packet send from DS is Dest Mac address.
1500 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1502 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1505 // -----------------------------------------------------------------
1506 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1507 // -----------------------------------------------------------------
1508 if (pAd->CommonCfg.bAPSDForcePowerSave)
1509 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1511 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1513 #endif // DOT11_N_SUPPORT //
1515 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1516 IN RTMP_ADAPTER *pAd,
1519 PUCHAR pHeaderBufPtr;
1520 HEADER_802_11 *pHeader_802_11;
1521 PNDIS_PACKET pNextPacket;
1523 PQUEUE_ENTRY pQEntry;
1525 STAFindCipherAlgorithm(pAd, pTxBlk);
1526 STABuildCommon802_11Header(pAd, pTxBlk);
1529 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1530 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1532 // steal "order" bit to mark "aggregation"
1533 pHeader_802_11->FC.Order = 1;
1535 // skip common header
1536 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1538 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1541 // build QOS Control bytes
1543 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1545 *(pHeaderBufPtr+1) = 0;
1547 pTxBlk->MpduHeaderLen += 2;
1550 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1551 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1552 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1553 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1555 // For RA Aggregation,
1556 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1557 pQEntry = pTxBlk->TxPacketList.Head;
1558 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1559 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1560 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1561 nextBufLen -= LENGTH_802_1Q;
1563 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1564 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1567 pTxBlk->MpduHeaderLen += 2;
1569 return pHeaderBufPtr;
1573 #ifdef DOT11_N_SUPPORT
1574 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1575 IN RTMP_ADAPTER *pAd,
1578 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1579 HEADER_802_11 *pHeader_802_11;
1582 STAFindCipherAlgorithm(pAd, pTxBlk);
1583 STABuildCommon802_11Header(pAd, pTxBlk);
1585 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1586 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1588 // skip common header
1589 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1592 // build QOS Control bytes
1594 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1599 *pHeaderBufPtr |= 0x80;
1601 *(pHeaderBufPtr+1) = 0;
1603 pTxBlk->MpduHeaderLen += 2;
1605 //pSaveBufPtr = pHeaderBufPtr;
1608 // padding at front of LLC header
1609 // LLC header should locate at 4-octets aligment
1611 // @@@ MpduHeaderLen excluding padding @@@
1613 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1614 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1615 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1617 return pHeaderBufPtr;
1622 VOID STA_AMPDU_Frame_Tx(
1623 IN PRTMP_ADAPTER pAd,
1626 HEADER_802_11 *pHeader_802_11;
1627 PUCHAR pHeaderBufPtr;
1629 MAC_TABLE_ENTRY *pMacEntry;
1631 PQUEUE_ENTRY pQEntry;
1635 while(pTxBlk->TxPacketList.Head)
1637 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1638 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1639 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1641 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1645 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1647 pMacEntry = pTxBlk->pMacEntry;
1648 if (pMacEntry->isCached)
1650 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1651 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1652 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1653 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1657 STAFindCipherAlgorithm(pAd, pTxBlk);
1658 STABuildCommon802_11Header(pAd, pTxBlk);
1660 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1664 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1666 // skip common header
1667 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1670 // build QOS Control bytes
1672 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1673 *(pHeaderBufPtr+1) = 0;
1675 pTxBlk->MpduHeaderLen += 2;
1679 // HTC control filed following QoS field
1681 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1683 if (pMacEntry->isCached == FALSE)
1686 pHeader_802_11->FC.Order = 1;
1688 NdisZeroMemory(pHeaderBufPtr, 4);
1689 *(pHeaderBufPtr+3) |= 0x80;
1692 pTxBlk->MpduHeaderLen += 4;
1695 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1696 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1698 // skip 802.3 header
1699 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1700 pTxBlk->SrcBufLen -= LENGTH_802_3;
1705 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1706 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1710 // padding at front of LLC header
1711 // LLC header should locate at 4-octets aligment
1713 // @@@ MpduHeaderLen excluding padding @@@
1715 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1716 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1717 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1722 // Insert LLC-SNAP encapsulation - 8 octets
1724 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1725 if (pTxBlk->pExtraLlcSnapEncap)
1727 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1729 // get 2 octets (TypeofLen)
1730 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1732 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1737 if (pMacEntry->isCached)
1739 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1743 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1745 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1746 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1747 pMacEntry->isCached = TRUE;
1750 // calculate Transmitted AMPDU count and ByteCount
1752 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1753 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1756 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1758 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1763 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1765 pAd->RalinkCounters.KickTxCount++;
1766 pAd->RalinkCounters.OneSecTxDoneCount++;
1772 VOID STA_AMSDU_Frame_Tx(
1773 IN PRTMP_ADAPTER pAd,
1776 PUCHAR pHeaderBufPtr;
1778 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1779 USHORT totalMPDUSize=0;
1780 UCHAR *subFrameHeader;
1782 USHORT FirstTx = 0, LastTxIdx = 0;
1785 PQUEUE_ENTRY pQEntry;
1790 ASSERT((pTxBlk->TxPacketList.Number > 1));
1792 while(pTxBlk->TxPacketList.Head)
1794 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1795 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1796 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1798 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1802 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1804 // skip 802.3 header
1805 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1806 pTxBlk->SrcBufLen -= LENGTH_802_3;
1811 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1812 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1817 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1819 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1820 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1824 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1825 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1826 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1827 pHeaderBufPtr += padding;
1828 pTxBlk->MpduHeaderLen = padding;
1833 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1835 subFrameHeader = pHeaderBufPtr;
1836 subFramePayloadLen = pTxBlk->SrcBufLen;
1838 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1841 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1842 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1846 // Insert LLC-SNAP encapsulation - 8 octets
1848 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1850 subFramePayloadLen = pTxBlk->SrcBufLen;
1852 if (pTxBlk->pExtraLlcSnapEncap)
1854 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1856 // get 2 octets (TypeofLen)
1857 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1859 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1860 subFramePayloadLen += LENGTH_802_1_H;
1863 // update subFrame Length field
1864 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1865 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1867 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1870 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1872 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1876 pAd->RalinkCounters.KickTxCount++;
1877 pAd->RalinkCounters.OneSecTxDoneCount++;
1879 // calculate Transmitted AMSDU Count and ByteCount
1881 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1882 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1887 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1888 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1893 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1895 #endif // DOT11_N_SUPPORT //
1897 VOID STA_Legacy_Frame_Tx(
1898 IN PRTMP_ADAPTER pAd,
1901 HEADER_802_11 *pHeader_802_11;
1902 PUCHAR pHeaderBufPtr;
1905 PQUEUE_ENTRY pQEntry;
1910 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1911 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1912 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1914 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1918 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1920 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1923 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1924 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1926 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1928 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1930 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1931 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1933 STAFindCipherAlgorithm(pAd, pTxBlk);
1934 STABuildCommon802_11Header(pAd, pTxBlk);
1937 // skip 802.3 header
1938 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1939 pTxBlk->SrcBufLen -= LENGTH_802_3;
1944 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1945 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1948 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1949 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1951 // skip common header
1952 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1954 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1957 // build QOS Control bytes
1959 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1960 *(pHeaderBufPtr+1) = 0;
1962 pTxBlk->MpduHeaderLen += 2;
1965 // The remaining content of MPDU header should locate at 4-octets aligment
1966 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1967 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1968 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1973 // Insert LLC-SNAP encapsulation - 8 octets
1976 // if original Ethernet frame contains no LLC/SNAP,
1977 // then an extra LLC/SNAP encap is required
1979 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
1980 if (pTxBlk->pExtraLlcSnapEncap)
1984 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1987 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
1988 // get 2 octets (TypeofLen)
1989 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
1991 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1998 // use Wcid as Key Index
2001 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2003 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2005 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2007 pAd->RalinkCounters.KickTxCount++;
2008 pAd->RalinkCounters.OneSecTxDoneCount++;
2013 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2017 VOID STA_ARalink_Frame_Tx(
2018 IN PRTMP_ADAPTER pAd,
2021 PUCHAR pHeaderBufPtr;
2023 USHORT totalMPDUSize=0;
2024 USHORT FirstTx, LastTxIdx;
2027 PQUEUE_ENTRY pQEntry;
2032 ASSERT((pTxBlk->TxPacketList.Number== 2));
2035 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2036 while(pTxBlk->TxPacketList.Head)
2038 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2039 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2041 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2043 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2047 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2049 // skip 802.3 header
2050 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2051 pTxBlk->SrcBufLen -= LENGTH_802_3;
2056 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2057 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2061 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2063 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2065 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2066 // will be updated after final frame was handled.
2067 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2071 // Insert LLC-SNAP encapsulation - 8 octets
2073 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2075 if (pTxBlk->pExtraLlcSnapEncap)
2077 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2079 // get 2 octets (TypeofLen)
2080 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2082 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2086 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2088 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2089 pTxBlk->MpduHeaderLen = 0;
2091 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2092 // DA(6)+SA(6)+FrameType(2)
2093 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2094 pHeaderBufPtr += 12;
2095 // get 2 octets (TypeofLen)
2096 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2098 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2101 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2103 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2105 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2107 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2111 pAd->RalinkCounters.OneSecTxAggregationCount++;
2112 pAd->RalinkCounters.KickTxCount++;
2113 pAd->RalinkCounters.OneSecTxDoneCount++;
2117 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2118 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2123 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2128 VOID STA_Fragment_Frame_Tx(
2129 IN RTMP_ADAPTER *pAd,
2132 HEADER_802_11 *pHeader_802_11;
2133 PUCHAR pHeaderBufPtr;
2136 PACKET_INFO PacketInfo;
2137 USHORT EncryptionOverhead = 0;
2138 UINT32 FreeMpduSize, SrcRemainingBytes;
2142 PQUEUE_ENTRY pQEntry;
2147 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2148 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2149 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2151 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2155 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2156 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2158 STAFindCipherAlgorithm(pAd, pTxBlk);
2159 STABuildCommon802_11Header(pAd, pTxBlk);
2161 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2163 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2164 if (pTxBlk->pPacket == NULL)
2166 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2169 // skip 802.3 header
2170 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2171 pTxBlk->SrcBufLen -= LENGTH_802_3;
2177 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2178 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2181 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2182 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2185 // skip common header
2186 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2188 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2191 // build QOS Control bytes
2193 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2195 *(pHeaderBufPtr+1) = 0;
2197 pTxBlk->MpduHeaderLen += 2;
2201 // padding at front of LLC header
2202 // LLC header should locate at 4-octets aligment
2204 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2205 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2206 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2211 // Insert LLC-SNAP encapsulation - 8 octets
2214 // if original Ethernet frame contains no LLC/SNAP,
2215 // then an extra LLC/SNAP encap is required
2217 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2218 if (pTxBlk->pExtraLlcSnapEncap)
2222 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2225 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2226 // get 2 octets (TypeofLen)
2227 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2229 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2233 // If TKIP is used and fragmentation is required. Driver has to
2234 // append TKIP MIC at tail of the scatter buffer
2235 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2236 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2239 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2240 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2241 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2242 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2243 pTxBlk->SrcBufLen += 8;
2244 pTxBlk->TotalFrameLen += 8;
2245 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2249 // calcuate the overhead bytes that encryption algorithm may add. This
2250 // affects the calculate of "duration" field
2252 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2253 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2254 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2255 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2256 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2257 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2258 else if (pTxBlk->CipherAlg == CIPHER_AES)
2259 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2261 EncryptionOverhead = 0;
2263 // decide how much time an ACK/CTS frame will consume in the air
2264 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2266 // Init the total payload length of this frame.
2267 SrcRemainingBytes = pTxBlk->SrcBufLen;
2269 pTxBlk->TotalFragNum = 0xff;
2273 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2275 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2277 if (SrcRemainingBytes <= FreeMpduSize)
2278 { // this is the last or only fragment
2280 pTxBlk->SrcBufLen = SrcRemainingBytes;
2282 pHeader_802_11->FC.MoreFrag = 0;
2283 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2285 // Indicate the lower layer that this's the last fragment.
2286 pTxBlk->TotalFragNum = fragNum;
2289 { // more fragment is required
2291 pTxBlk->SrcBufLen = FreeMpduSize;
2293 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2294 pHeader_802_11->FC.MoreFrag = 1;
2295 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2299 pTxBlk->FrameGap = IFS_HTTXOP;
2301 pTxBlk->FrameGap = IFS_SIFS;
2303 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2305 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2307 pAd->RalinkCounters.KickTxCount++;
2308 pAd->RalinkCounters.OneSecTxDoneCount++;
2310 // Update the frame number, remaining size of the NDIS packet payload.
2312 // space for 802.11 header.
2313 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2314 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2317 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2318 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2320 pHeader_802_11->Frag++; // increase Frag #
2322 }while(SrcRemainingBytes > 0);
2327 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2331 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2332 while(_pTxBlk->TxPacketList.Head) \
2334 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2335 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2340 ========================================================================
2342 Routine Description:
2343 Copy frame from waiting queue into relative ring buffer and set
2344 appropriate ASIC register to kick hardware encryption before really
2348 pAd Pointer to our adapter
2349 PNDIS_PACKET Pointer to outgoing Ndis frame
2350 NumberOfFrag Number of fragment required
2355 IRQL = DISPATCH_LEVEL
2359 ========================================================================
2361 NDIS_STATUS STAHardTransmit(
2362 IN PRTMP_ADAPTER pAd,
2366 NDIS_PACKET *pPacket;
2367 PQUEUE_ENTRY pQEntry;
2369 // ---------------------------------------------
2370 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2371 // ---------------------------------------------
2373 ASSERT(pTxBlk->TxPacketList.Number);
2374 if (pTxBlk->TxPacketList.Head == NULL)
2376 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2377 return NDIS_STATUS_FAILURE;
2380 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2382 // ------------------------------------------------------------------
2383 // STEP 1. WAKE UP PHY
2384 // outgoing frame always wakeup PHY to prevent frame lost and
2385 // turn off PSM bit to improve performance
2386 // ------------------------------------------------------------------
2387 // not to change PSM bit, just send this frame out?
2388 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2390 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2391 AsicForceWakeup(pAd, TRUE);
2394 // It should not change PSM bit, when APSD turn on.
2395 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2396 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2397 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2399 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2400 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2401 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2404 switch (pTxBlk->TxFrameType)
2406 #ifdef DOT11_N_SUPPORT
2407 case TX_AMPDU_FRAME:
2408 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2410 case TX_AMSDU_FRAME:
2411 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2413 #endif // DOT11_N_SUPPORT //
2414 case TX_LEGACY_FRAME:
2415 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2417 case TX_MCAST_FRAME:
2418 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2420 case TX_RALINK_FRAME:
2421 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2424 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2428 // It should not happened!
2429 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2430 while(pTxBlk->TxPacketList.Number)
2432 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2433 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2435 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2441 return (NDIS_STATUS_SUCCESS);
2445 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2447 unsigned char *word = value;
2448 unsigned int ret = 0;
2451 for(i=0; i < len; i++)
2454 ret ^=(unsigned int) (word[i]) << mod;
2455 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2460 VOID Sta_Announce_or_Forward_802_3_Packet(
2461 IN PRTMP_ADAPTER pAd,
2462 IN PNDIS_PACKET pPacket,
2463 IN UCHAR FromWhichBSSID)
2468 announce_802_3_packet(pAd, pPacket);
2473 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);