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.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
974 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
977 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
978 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
980 return (NDIS_STATUS_FAILURE);
984 // STEP 1. Decide number of fragments required to deliver this MSDU.
985 // The estimation here is not very accurate because difficult to
986 // take encryption overhead into consideration here. The result
987 // "NumberOfFrag" is then just used to pre-check if enough free
988 // TXD are available to hold this MSDU.
991 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
993 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
994 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
995 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
996 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
997 #ifdef DOT11_N_SUPPORT
998 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
999 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1000 #endif // DOT11_N_SUPPORT //
1003 // The calculated "NumberOfFrag" is a rough estimation because of various
1004 // encryption/encapsulation overhead not taken into consideration. This number is just
1005 // used to make sure enough free TXD are available before fragmentation takes place.
1006 // In case the actual required number of fragments of an NDIS packet
1007 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1008 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1009 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1010 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1012 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1013 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1014 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1015 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1021 // Save fragment number to Ndis packet reserved field
1022 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1025 // STEP 2. Check the requirement of RTS:
1026 // If multiple fragment required, RTS is required only for the first fragment
1027 // if the fragment size large than RTS threshold
1028 // For RT28xx, Let ASIC send RTS/CTS
1029 RTMP_SET_PACKET_RTS(pPacket, 0);
1030 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1033 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1037 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1038 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1041 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1044 // get Ethernet protocol field
1045 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1046 if (Protocol <= 1500)
1048 // get Ethernet protocol field from LLC/SNAP
1049 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1052 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1056 // always AC_BE for non-IP packet
1057 if (Protocol != 0x0800)
1061 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1064 // return AC_BE if packet is not IPv4
1065 if ((Byte0 & 0xf0) != 0x40)
1069 UserPriority = (Byte1 & 0xe0) >> 5;
1070 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1072 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1073 // TODO: downgrade UP & QueIdx before passing ACM
1074 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1082 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1086 // Make sure SendTxWait queue resource won't be used by other threads
1087 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1088 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1090 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1091 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1093 return NDIS_STATUS_FAILURE;
1097 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1099 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1101 #ifdef DOT11_N_SUPPORT
1102 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1105 //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID];
1106 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1107 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1108 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1109 // For IOT compatibility, if
1110 // 1. It is Ralink chip or
1111 // 2. It is OPEN or AES mode,
1112 // then BA session can be bulit.
1113 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1114 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1117 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1120 #endif // DOT11_N_SUPPORT //
1122 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1123 return NDIS_STATUS_SUCCESS;
1128 ========================================================================
1130 Routine Description:
1131 This subroutine will scan through releative ring descriptor to find
1132 out avaliable free ring descriptor and compare with request size.
1135 pAd Pointer to our adapter
1136 QueIdx Selected TX Ring
1139 NDIS_STATUS_FAILURE Not enough free descriptor
1140 NDIS_STATUS_SUCCESS Enough free descriptor
1142 IRQL = PASSIVE_LEVEL
1143 IRQL = DISPATCH_LEVEL
1147 ========================================================================
1152 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1153 If no frame need to send, go to sleep, else, still wake up.
1155 NDIS_STATUS RTMPFreeTXDRequest(
1156 IN PRTMP_ADAPTER pAd,
1158 IN UCHAR NumberRequired,
1159 IN PUCHAR FreeNumberIs)
1161 //ULONG FreeNumber = 0;
1162 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1163 unsigned long IrqFlags;
1164 HT_TX_CONTEXT *pHTTXContext;
1174 pHTTXContext = &pAd->TxContext[QueIdx];
1175 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1176 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1177 (pHTTXContext->IRPPending == TRUE))
1179 Status = NDIS_STATUS_FAILURE;
1183 Status = NDIS_STATUS_SUCCESS;
1185 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1190 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1191 Status = NDIS_STATUS_FAILURE;
1193 Status = NDIS_STATUS_SUCCESS;
1197 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1207 VOID RTMPSendDisassociationFrame(
1208 IN PRTMP_ADAPTER pAd)
1212 VOID RTMPSendNullFrame(
1213 IN PRTMP_ADAPTER pAd,
1215 IN BOOLEAN bQosNull)
1217 UCHAR NullFrame[48];
1219 PHEADER_802_11 pHeader_802_11;
1221 // WPA 802.1x secured port control
1222 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1223 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1224 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1225 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1226 #ifdef WPA_SUPPLICANT_SUPPORT
1227 || (pAd->StaCfg.IEEE8021X == TRUE)
1230 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1235 NdisZeroMemory(NullFrame, 48);
1236 Length = sizeof(HEADER_802_11);
1238 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1240 pHeader_802_11->FC.Type = BTYPE_DATA;
1241 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1242 pHeader_802_11->FC.ToDs = 1;
1243 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1244 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1245 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1247 if (pAd->CommonCfg.bAPSDForcePowerSave)
1249 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1253 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1255 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1258 pHeader_802_11->Sequence = pAd->Sequence;
1260 // Prepare QosNull function frame
1263 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1265 // copy QOS control bytes
1266 NullFrame[Length] = 0;
1267 NullFrame[Length+1] = 0;
1268 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1271 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1275 // IRQL = DISPATCH_LEVEL
1276 VOID RTMPSendRTSFrame(
1277 IN PRTMP_ADAPTER pAd,
1279 IN unsigned int NextMpduSize,
1282 IN USHORT AckDuration,
1290 // --------------------------------------------------------
1291 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1292 // Find the WPA key, either Group or Pairwise Key
1293 // LEAP + TKIP also use WPA key.
1294 // --------------------------------------------------------
1295 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1296 // In Cisco CCX 2.0 Leap Authentication
1297 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1298 // Instead of the SharedKey, SharedKey Length may be Zero.
1299 VOID STAFindCipherAlgorithm(
1300 IN PRTMP_ADAPTER pAd,
1303 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1304 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1305 UCHAR KeyIdx = 0xff;
1307 PCIPHER_KEY pKey = NULL;
1309 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1313 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1314 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1316 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1318 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1320 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1322 // 4-way handshaking frame must be clear
1323 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1324 (pAd->SharedKey[BSS0][0].KeyLen))
1326 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1330 else if (Cipher == Ndis802_11Encryption1Enabled)
1332 KeyIdx = pAd->StaCfg.DefaultKeyId;
1334 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1335 (Cipher == Ndis802_11Encryption3Enabled))
1337 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1338 KeyIdx = pAd->StaCfg.DefaultKeyId;
1339 else if (pAd->SharedKey[BSS0][0].KeyLen)
1342 KeyIdx = pAd->StaCfg.DefaultKeyId;
1346 CipherAlg = CIPHER_NONE;
1347 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1348 CipherAlg = CIPHER_NONE;
1349 #ifdef WPA_SUPPLICANT_SUPPORT
1350 else if ( pAd->StaCfg.WpaSupplicantUP &&
1351 (Cipher == Ndis802_11Encryption1Enabled) &&
1352 (pAd->StaCfg.IEEE8021X == TRUE) &&
1353 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1354 CipherAlg = CIPHER_NONE;
1355 #endif // WPA_SUPPLICANT_SUPPORT //
1358 //Header_802_11.FC.Wep = 1;
1359 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1360 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1364 pTxBlk->CipherAlg = CipherAlg;
1365 pTxBlk->pKey = pKey;
1369 VOID STABuildCommon802_11Header(
1370 IN PRTMP_ADAPTER pAd,
1373 HEADER_802_11 *pHeader_802_11;
1376 // MAKE A COMMON 802.11 HEADER
1379 // normal wlan header size : 24 octets
1380 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1382 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1384 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1386 pHeader_802_11->FC.FrDs = 0;
1387 pHeader_802_11->FC.Type = BTYPE_DATA;
1388 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1390 if (pTxBlk->pMacEntry)
1392 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1394 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1395 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1399 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1400 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1405 pHeader_802_11->Sequence = pAd->Sequence;
1406 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1409 pHeader_802_11->Frag = 0;
1411 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1417 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1418 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1419 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1420 pHeader_802_11->FC.ToDs = 1;
1423 else if (ADHOC_ON(pAd))
1425 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1426 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1427 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1428 pHeader_802_11->FC.ToDs = 0;
1432 if (pTxBlk->CipherAlg != CIPHER_NONE)
1433 pHeader_802_11->FC.Wep = 1;
1435 // -----------------------------------------------------------------
1436 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1437 // -----------------------------------------------------------------
1438 if (pAd->CommonCfg.bAPSDForcePowerSave)
1439 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1441 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1444 #ifdef DOT11_N_SUPPORT
1445 VOID STABuildCache802_11Header(
1446 IN RTMP_ADAPTER *pAd,
1450 MAC_TABLE_ENTRY *pMacEntry;
1451 PHEADER_802_11 pHeader80211;
1453 pHeader80211 = (PHEADER_802_11)pHeader;
1454 pMacEntry = pTxBlk->pMacEntry;
1457 // Update the cached 802.11 HEADER
1460 // normal wlan header size : 24 octets
1461 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1464 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1467 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1468 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1471 // The addr3 of normal packet send from DS is Dest Mac address.
1473 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1475 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1478 // -----------------------------------------------------------------
1479 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1480 // -----------------------------------------------------------------
1481 if (pAd->CommonCfg.bAPSDForcePowerSave)
1482 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1484 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1486 #endif // DOT11_N_SUPPORT //
1488 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1489 IN RTMP_ADAPTER *pAd,
1492 PUCHAR pHeaderBufPtr;
1493 HEADER_802_11 *pHeader_802_11;
1494 PNDIS_PACKET pNextPacket;
1496 PQUEUE_ENTRY pQEntry;
1498 STAFindCipherAlgorithm(pAd, pTxBlk);
1499 STABuildCommon802_11Header(pAd, pTxBlk);
1502 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1503 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1505 // steal "order" bit to mark "aggregation"
1506 pHeader_802_11->FC.Order = 1;
1508 // skip common header
1509 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1511 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1514 // build QOS Control bytes
1516 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1518 *(pHeaderBufPtr+1) = 0;
1520 pTxBlk->MpduHeaderLen += 2;
1523 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1524 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1525 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1526 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1528 // For RA Aggregation,
1529 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1530 pQEntry = pTxBlk->TxPacketList.Head;
1531 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1532 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1533 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1534 nextBufLen -= LENGTH_802_1Q;
1536 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1537 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1540 pTxBlk->MpduHeaderLen += 2;
1542 return pHeaderBufPtr;
1546 #ifdef DOT11_N_SUPPORT
1547 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1548 IN RTMP_ADAPTER *pAd,
1551 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1552 HEADER_802_11 *pHeader_802_11;
1555 STAFindCipherAlgorithm(pAd, pTxBlk);
1556 STABuildCommon802_11Header(pAd, pTxBlk);
1558 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1559 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1561 // skip common header
1562 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1565 // build QOS Control bytes
1567 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1572 *pHeaderBufPtr |= 0x80;
1574 *(pHeaderBufPtr+1) = 0;
1576 pTxBlk->MpduHeaderLen += 2;
1578 //pSaveBufPtr = pHeaderBufPtr;
1581 // padding at front of LLC header
1582 // LLC header should locate at 4-octets aligment
1584 // @@@ MpduHeaderLen excluding padding @@@
1586 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1587 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1588 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1590 return pHeaderBufPtr;
1595 VOID STA_AMPDU_Frame_Tx(
1596 IN PRTMP_ADAPTER pAd,
1599 HEADER_802_11 *pHeader_802_11;
1600 PUCHAR pHeaderBufPtr;
1602 MAC_TABLE_ENTRY *pMacEntry;
1604 PQUEUE_ENTRY pQEntry;
1608 while(pTxBlk->TxPacketList.Head)
1610 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1611 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1612 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1614 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1618 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1620 pMacEntry = pTxBlk->pMacEntry;
1621 if (pMacEntry->isCached)
1623 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1624 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1625 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1626 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1630 STAFindCipherAlgorithm(pAd, pTxBlk);
1631 STABuildCommon802_11Header(pAd, pTxBlk);
1633 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1637 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1639 // skip common header
1640 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1643 // build QOS Control bytes
1645 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1646 *(pHeaderBufPtr+1) = 0;
1648 pTxBlk->MpduHeaderLen += 2;
1652 // HTC control filed following QoS field
1654 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1656 if (pMacEntry->isCached == FALSE)
1659 pHeader_802_11->FC.Order = 1;
1661 NdisZeroMemory(pHeaderBufPtr, 4);
1662 *(pHeaderBufPtr+3) |= 0x80;
1665 pTxBlk->MpduHeaderLen += 4;
1668 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1669 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1671 // skip 802.3 header
1672 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1673 pTxBlk->SrcBufLen -= LENGTH_802_3;
1678 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1679 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1683 // padding at front of LLC header
1684 // LLC header should locate at 4-octets aligment
1686 // @@@ MpduHeaderLen excluding padding @@@
1688 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1689 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1690 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1695 // Insert LLC-SNAP encapsulation - 8 octets
1697 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1698 if (pTxBlk->pExtraLlcSnapEncap)
1700 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1702 // get 2 octets (TypeofLen)
1703 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1705 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1710 if (pMacEntry->isCached)
1712 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1716 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1718 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1719 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1720 pMacEntry->isCached = TRUE;
1723 // calculate Transmitted AMPDU count and ByteCount
1725 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1726 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1729 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1731 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1736 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1738 pAd->RalinkCounters.KickTxCount++;
1739 pAd->RalinkCounters.OneSecTxDoneCount++;
1745 VOID STA_AMSDU_Frame_Tx(
1746 IN PRTMP_ADAPTER pAd,
1749 PUCHAR pHeaderBufPtr;
1751 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1752 USHORT totalMPDUSize=0;
1753 UCHAR *subFrameHeader;
1755 USHORT FirstTx = 0, LastTxIdx = 0;
1758 PQUEUE_ENTRY pQEntry;
1763 ASSERT((pTxBlk->TxPacketList.Number > 1));
1765 while(pTxBlk->TxPacketList.Head)
1767 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1768 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1769 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1771 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1775 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1777 // skip 802.3 header
1778 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1779 pTxBlk->SrcBufLen -= LENGTH_802_3;
1784 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1785 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1790 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1792 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1793 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1797 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1798 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1799 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1800 pHeaderBufPtr += padding;
1801 pTxBlk->MpduHeaderLen = padding;
1806 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1808 subFrameHeader = pHeaderBufPtr;
1809 subFramePayloadLen = pTxBlk->SrcBufLen;
1811 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1814 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1815 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1819 // Insert LLC-SNAP encapsulation - 8 octets
1821 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1823 subFramePayloadLen = pTxBlk->SrcBufLen;
1825 if (pTxBlk->pExtraLlcSnapEncap)
1827 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1829 // get 2 octets (TypeofLen)
1830 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1832 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1833 subFramePayloadLen += LENGTH_802_1_H;
1836 // update subFrame Length field
1837 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1838 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1840 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1843 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1845 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1849 pAd->RalinkCounters.KickTxCount++;
1850 pAd->RalinkCounters.OneSecTxDoneCount++;
1852 // calculate Transmitted AMSDU Count and ByteCount
1854 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1855 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1860 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1861 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1866 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1868 #endif // DOT11_N_SUPPORT //
1870 VOID STA_Legacy_Frame_Tx(
1871 IN PRTMP_ADAPTER pAd,
1874 HEADER_802_11 *pHeader_802_11;
1875 PUCHAR pHeaderBufPtr;
1878 PQUEUE_ENTRY pQEntry;
1883 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1884 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1885 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1887 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1891 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1893 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1896 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1897 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1899 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1901 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1903 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1904 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1906 STAFindCipherAlgorithm(pAd, pTxBlk);
1907 STABuildCommon802_11Header(pAd, pTxBlk);
1910 // skip 802.3 header
1911 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1912 pTxBlk->SrcBufLen -= LENGTH_802_3;
1917 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1918 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1921 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1922 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1924 // skip common header
1925 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1927 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1930 // build QOS Control bytes
1932 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1933 *(pHeaderBufPtr+1) = 0;
1935 pTxBlk->MpduHeaderLen += 2;
1938 // The remaining content of MPDU header should locate at 4-octets aligment
1939 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1940 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1941 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1946 // Insert LLC-SNAP encapsulation - 8 octets
1949 // if original Ethernet frame contains no LLC/SNAP,
1950 // then an extra LLC/SNAP encap is required
1952 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
1953 if (pTxBlk->pExtraLlcSnapEncap)
1957 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1960 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
1961 // get 2 octets (TypeofLen)
1962 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
1964 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1971 // use Wcid as Key Index
1974 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1976 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1978 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1980 pAd->RalinkCounters.KickTxCount++;
1981 pAd->RalinkCounters.OneSecTxDoneCount++;
1986 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1990 VOID STA_ARalink_Frame_Tx(
1991 IN PRTMP_ADAPTER pAd,
1994 PUCHAR pHeaderBufPtr;
1996 USHORT totalMPDUSize=0;
1997 USHORT FirstTx, LastTxIdx;
2000 PQUEUE_ENTRY pQEntry;
2005 ASSERT((pTxBlk->TxPacketList.Number== 2));
2008 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2009 while(pTxBlk->TxPacketList.Head)
2011 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2012 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2014 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2016 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2020 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2022 // skip 802.3 header
2023 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2024 pTxBlk->SrcBufLen -= LENGTH_802_3;
2029 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2030 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2034 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2036 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2038 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2039 // will be updated after final frame was handled.
2040 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2044 // Insert LLC-SNAP encapsulation - 8 octets
2046 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2048 if (pTxBlk->pExtraLlcSnapEncap)
2050 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2052 // get 2 octets (TypeofLen)
2053 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2055 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2059 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2061 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2062 pTxBlk->MpduHeaderLen = 0;
2064 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2065 // DA(6)+SA(6)+FrameType(2)
2066 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2067 pHeaderBufPtr += 12;
2068 // get 2 octets (TypeofLen)
2069 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2071 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2074 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2076 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2078 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2080 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2084 pAd->RalinkCounters.OneSecTxAggregationCount++;
2085 pAd->RalinkCounters.KickTxCount++;
2086 pAd->RalinkCounters.OneSecTxDoneCount++;
2090 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2091 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2096 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2101 VOID STA_Fragment_Frame_Tx(
2102 IN RTMP_ADAPTER *pAd,
2105 HEADER_802_11 *pHeader_802_11;
2106 PUCHAR pHeaderBufPtr;
2109 PACKET_INFO PacketInfo;
2110 USHORT EncryptionOverhead = 0;
2111 UINT32 FreeMpduSize, SrcRemainingBytes;
2115 PQUEUE_ENTRY pQEntry;
2120 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2121 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2122 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2124 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2128 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2129 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2131 STAFindCipherAlgorithm(pAd, pTxBlk);
2132 STABuildCommon802_11Header(pAd, pTxBlk);
2134 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2136 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2137 if (pTxBlk->pPacket == NULL)
2139 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2142 // skip 802.3 header
2143 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2144 pTxBlk->SrcBufLen -= LENGTH_802_3;
2150 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2151 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2154 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2155 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2158 // skip common header
2159 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2161 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2164 // build QOS Control bytes
2166 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2168 *(pHeaderBufPtr+1) = 0;
2170 pTxBlk->MpduHeaderLen += 2;
2174 // padding at front of LLC header
2175 // LLC header should locate at 4-octets aligment
2177 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2178 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2179 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2184 // Insert LLC-SNAP encapsulation - 8 octets
2187 // if original Ethernet frame contains no LLC/SNAP,
2188 // then an extra LLC/SNAP encap is required
2190 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2191 if (pTxBlk->pExtraLlcSnapEncap)
2195 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2198 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2199 // get 2 octets (TypeofLen)
2200 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2202 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2206 // If TKIP is used and fragmentation is required. Driver has to
2207 // append TKIP MIC at tail of the scatter buffer
2208 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2209 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2212 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2213 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2214 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2215 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2216 pTxBlk->SrcBufLen += 8;
2217 pTxBlk->TotalFrameLen += 8;
2218 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2222 // calcuate the overhead bytes that encryption algorithm may add. This
2223 // affects the calculate of "duration" field
2225 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2226 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2227 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2228 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2229 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2230 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2231 else if (pTxBlk->CipherAlg == CIPHER_AES)
2232 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2234 EncryptionOverhead = 0;
2236 // decide how much time an ACK/CTS frame will consume in the air
2237 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2239 // Init the total payload length of this frame.
2240 SrcRemainingBytes = pTxBlk->SrcBufLen;
2242 pTxBlk->TotalFragNum = 0xff;
2246 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2248 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2250 if (SrcRemainingBytes <= FreeMpduSize)
2251 { // this is the last or only fragment
2253 pTxBlk->SrcBufLen = SrcRemainingBytes;
2255 pHeader_802_11->FC.MoreFrag = 0;
2256 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2258 // Indicate the lower layer that this's the last fragment.
2259 pTxBlk->TotalFragNum = fragNum;
2262 { // more fragment is required
2264 pTxBlk->SrcBufLen = FreeMpduSize;
2266 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2267 pHeader_802_11->FC.MoreFrag = 1;
2268 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2272 pTxBlk->FrameGap = IFS_HTTXOP;
2274 pTxBlk->FrameGap = IFS_SIFS;
2276 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2278 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2280 pAd->RalinkCounters.KickTxCount++;
2281 pAd->RalinkCounters.OneSecTxDoneCount++;
2283 // Update the frame number, remaining size of the NDIS packet payload.
2285 // space for 802.11 header.
2286 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2287 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2290 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2291 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2293 pHeader_802_11->Frag++; // increase Frag #
2295 }while(SrcRemainingBytes > 0);
2300 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2304 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2305 while(_pTxBlk->TxPacketList.Head) \
2307 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2308 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2313 ========================================================================
2315 Routine Description:
2316 Copy frame from waiting queue into relative ring buffer and set
2317 appropriate ASIC register to kick hardware encryption before really
2321 pAd Pointer to our adapter
2322 PNDIS_PACKET Pointer to outgoing Ndis frame
2323 NumberOfFrag Number of fragment required
2328 IRQL = DISPATCH_LEVEL
2332 ========================================================================
2334 NDIS_STATUS STAHardTransmit(
2335 IN PRTMP_ADAPTER pAd,
2339 NDIS_PACKET *pPacket;
2340 PQUEUE_ENTRY pQEntry;
2342 // ---------------------------------------------
2343 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2344 // ---------------------------------------------
2346 ASSERT(pTxBlk->TxPacketList.Number);
2347 if (pTxBlk->TxPacketList.Head == NULL)
2349 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2350 return NDIS_STATUS_FAILURE;
2353 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2355 // ------------------------------------------------------------------
2356 // STEP 1. WAKE UP PHY
2357 // outgoing frame always wakeup PHY to prevent frame lost and
2358 // turn off PSM bit to improve performance
2359 // ------------------------------------------------------------------
2360 // not to change PSM bit, just send this frame out?
2361 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2363 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2364 AsicForceWakeup(pAd, TRUE);
2367 // It should not change PSM bit, when APSD turn on.
2368 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2369 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2370 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2372 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2373 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2374 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2377 switch (pTxBlk->TxFrameType)
2379 #ifdef DOT11_N_SUPPORT
2380 case TX_AMPDU_FRAME:
2381 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2383 case TX_AMSDU_FRAME:
2384 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2386 #endif // DOT11_N_SUPPORT //
2387 case TX_LEGACY_FRAME:
2388 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2390 case TX_MCAST_FRAME:
2391 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2393 case TX_RALINK_FRAME:
2394 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2397 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2401 // It should not happened!
2402 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2403 while(pTxBlk->TxPacketList.Number)
2405 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2406 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2408 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2414 return (NDIS_STATUS_SUCCESS);
2418 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2420 unsigned char *word = value;
2421 unsigned int ret = 0;
2424 for(i=0; i < len; i++)
2427 ret ^=(unsigned int) (word[i]) << mod;
2428 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2433 VOID Sta_Announce_or_Forward_802_3_Packet(
2434 IN PRTMP_ADAPTER pAd,
2435 IN PNDIS_PACKET pPacket,
2436 IN UCHAR FromWhichBSSID)
2441 announce_802_3_packet(pAd, pPacket);
2446 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);