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 if (pAd->StaCfg.WpaSupplicantUP)
54 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
55 // TBD : process fragmented EAPol frames
57 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
58 if ( pAd->StaCfg.IEEE8021X == TRUE &&
59 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
65 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
66 STA_PORT_SECURED(pAd);
68 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
70 idx = pAd->StaCfg.DesireSharedKeyId;
71 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
72 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
74 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
79 char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
80 NDIS_802_11_WEP keyinfo;
85 NdisZeroMemory(&WepKey, sizeof(WepKey));
86 len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
88 NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
89 pAd->StaCfg.DesireSharedKey[idx].Key,
90 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
92 WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
93 WepKey.keyinfo.KeyLength = len;
94 pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
96 pAd->IndicateMediaState = NdisMediaStateConnected;
97 pAd->ExtraInfo = GENERAL_LINK_UP;
98 // need to enqueue cmd to thread
99 RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
101 // For Preventing ShardKey Table is cleared by remove key procedure.
102 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
103 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
104 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
105 pAd->StaCfg.DesireSharedKey[idx].Key,
106 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
111 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
117 // Special DATA frame that has to pass to MLME
118 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
119 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
121 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
122 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
123 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
124 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
128 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
133 VOID STARxDataFrameAnnounce(
134 IN PRTMP_ADAPTER pAd,
135 IN MAC_TABLE_ENTRY *pEntry,
137 IN UCHAR FromWhichBSSID)
141 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
144 // drop all non-EAP DATA frame before
145 // this client's Port-Access-Control is secured
146 if (pRxBlk->pHeader->FC.Wep)
148 // unsupported cipher suite
149 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
152 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
158 // encryption in-use but receive a non-EAPOL clear text frame, drop it
159 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
160 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
163 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
168 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
169 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
171 // Normal legacy, AMPDU or AMSDU
172 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
178 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
183 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
185 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
187 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
191 // Determin the destination of the EAP frame
192 // to WPA state machine or upper layer
193 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
199 // For TKIP frame, calculate the MIC value
200 BOOLEAN STACheckTkipMICValue(
201 IN PRTMP_ADAPTER pAd,
202 IN MAC_TABLE_ENTRY *pEntry,
205 PHEADER_802_11 pHeader = pRxBlk->pHeader;
206 UCHAR *pData = pRxBlk->pData;
207 USHORT DataSize = pRxBlk->DataSize;
208 UCHAR UserPriority = pRxBlk->UserPriority;
212 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
214 pDA = pHeader->Addr1;
215 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
217 pSA = pHeader->Addr3;
221 pSA = pHeader->Addr2;
224 if (RTMPTkipCompareMICValue(pAd,
232 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
234 if (pAd->StaCfg.WpaSupplicantUP)
236 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
240 RTMPReportMicError(pAd, pWpaKey);
244 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
253 // All Rx routines use RX_BLK structure to hande rx events
254 // It is very important to build pRxBlk attributes
255 // 1. pHeader pointer to 802.11 Header
256 // 2. pData pointer to payload including LLC (just skip Header)
257 // 3. set payload size including LLC to DataSize
258 // 4. set some flags with RX_BLK_SET_FLAG()
260 VOID STAHandleRxDataFrame(
261 IN PRTMP_ADAPTER pAd,
264 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
265 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
266 PHEADER_802_11 pHeader = pRxBlk->pHeader;
267 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
268 BOOLEAN bFragment = FALSE;
269 MAC_TABLE_ENTRY *pEntry = NULL;
270 UCHAR FromWhichBSSID = BSS0;
271 UCHAR UserPriority = 0;
274 // before LINK UP, all DATA frames are rejected
275 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
278 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
282 // Drop not my BSS frames
283 if (pRxD->MyBss == 0)
287 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
292 pAd->RalinkCounters.RxCountSinceLastNULL++;
293 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
296 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
299 pData = (PUCHAR)pHeader + LENGTH_802_11;
300 if ((*pData >> 4) & 0x01)
302 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
303 pAd->CommonCfg.bInServicePeriod = FALSE;
305 // Force driver to fall into sleep mode when rcv EOSP frame
306 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
308 USHORT TbttNumToNextWakeUp;
309 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
312 NdisGetSystemUpTime(&Now);
313 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
315 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
316 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
317 TbttNumToNextWakeUp = NextDtim;
319 MlmeSetPsmBit(pAd, PWR_SAVE);
320 // if WMM-APSD is failed, try to disable following line
321 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
325 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
327 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
331 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
332 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
335 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
339 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
343 // Infrastructure mode, check address 2 for BSSID
344 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
346 // Receive frame not my BSSID
348 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
352 else // Ad-Hoc mode or Not associated
354 // Ad-Hoc mode, check address 3 for BSSID
355 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
357 // Receive frame not my BSSID
359 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
367 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
369 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
373 // 1. release packet if infra mode
374 // 2. new a pEntry if ad-hoc mode
375 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
382 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
383 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
386 // check Atheros Client
387 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
389 pEntry->bIAmBadAtheros = TRUE;
390 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
391 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
392 if (!STA_AES_ON(pAd))
394 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
399 pRxBlk->pData = (UCHAR *)pHeader;
402 // update RxBlk->pData, DataSize
403 // 802.11 Header, QOS, HTC, Hw Padding
406 // 1. skip 802.11 HEADER
408 pRxBlk->pData += LENGTH_802_11;
409 pRxBlk->DataSize -= LENGTH_802_11;
413 if (pHeader->FC.SubType & 0x08)
415 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
416 UserPriority = *(pRxBlk->pData) & 0x0f;
417 // bit 7 in QoS Control field signals the HT A-MSDU format
418 if ((*pRxBlk->pData) & 0x80)
420 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
423 // skip QOS contorl field
425 pRxBlk->DataSize -=2;
427 pRxBlk->UserPriority = UserPriority;
429 // 3. Order bit: A-Ralink or HTC+
430 if (pHeader->FC.Order)
432 #ifdef AGGREGATION_SUPPORT
433 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
435 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
440 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
441 // skip HTC contorl field
443 pRxBlk->DataSize -= 4;
447 // 4. skip HW padding
450 // just move pData pointer
451 // because DataSize excluding HW padding
452 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
458 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
462 // Case I Process Broadcast & Multicast data frame
464 if (pRxD->Bcast || pRxD->Mcast)
466 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
468 // Drop Mcast/Bcast frame with fragment bit on
469 if (pHeader->FC.MoreFrag)
472 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
476 // Filter out Bcast frame which AP relayed for us
477 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
480 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
484 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
489 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
493 pEntry = MacTableLookup(pAd, pHeader->Addr2);
495 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
499 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
501 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
502 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
504 pAd->RalinkCounters.OneSecRxOkDataCnt++;
507 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
509 // re-assemble the fragmented packets
510 // return complete frame (pRxPacket) or NULL
512 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
517 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
519 // process complete frame
520 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
523 pRxBlk->DataSize -= 8;
525 // For TKIP frame, calculate the MIC value
526 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
532 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
538 // because RTMPDeFragmentDataFrame() will release rx packet,
539 // if packet is fragmented
546 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
549 VOID STAHandleRxMgmtFrame(
550 IN PRTMP_ADAPTER pAd,
553 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
554 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
555 PHEADER_802_11 pHeader = pRxBlk->pHeader;
556 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
561 // We should collect RSSI not only U2M data but also my beacon
563 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))
564 && (pAd->RxAnt.EvaluatePeriod == 0))
567 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
570 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
572 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
573 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
577 // collect rssi information for antenna diversity
578 if (pAd->NicConfig2.field.AntDiversity)
580 if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))))
582 COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxWI->RSSI0, RSSI_0), 0); //Note: RSSI2 not used on RT73
583 pAd->StaCfg.NumOfAvgRssiSample ++;
588 // First check the size, it MUST not exceed the mlme queue size
589 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
591 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
595 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
596 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
599 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
602 VOID STAHandleRxControlFrame(
603 IN PRTMP_ADAPTER pAd,
606 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
607 PHEADER_802_11 pHeader = pRxBlk->pHeader;
608 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
610 switch (pHeader->FC.SubType)
612 case SUBTYPE_BLOCK_ACK_REQ:
614 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
617 case SUBTYPE_BLOCK_ACK:
623 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
628 ========================================================================
631 Process RxDone interrupt, running in DPC level
634 pAd Pointer to our adapter
639 IRQL = DISPATCH_LEVEL
642 This routine has to maintain Rx ring read pointer.
643 Need to consider QOS DATA format when converting to 802.3
644 ========================================================================
646 BOOLEAN STARxDoneInterruptHandle(
647 IN PRTMP_ADAPTER pAd,
651 UINT32 RxProcessed, RxPending;
652 BOOLEAN bReschedule = FALSE;
653 RT28XX_RXD_STRUC *pRxD;
656 PNDIS_PACKET pRxPacket;
657 PHEADER_802_11 pHeader;
660 RxProcessed = RxPending = 0;
662 // process whole rx ring
666 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
667 fRTMP_ADAPTER_RESET_IN_PROGRESS |
668 fRTMP_ADAPTER_HALT_IN_PROGRESS |
669 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
670 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
676 RxProcessed ++; // test
678 // 1. allocate a new data packet into rx ring to replace received packet
679 // then processing the received packet
680 // 2. the callee must take charge of release of packet
681 // 3. As far as driver is concerned ,
682 // the rx packet must
683 // a. be indicated to upper layer or
684 // b. be released if it is discarded
685 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
686 if (pRxPacket == NULL)
688 // no more packet to process
692 // get rx ring descriptor
693 pRxD = &(RxCell.RxD);
694 // get rx data buffer
695 pData = GET_OS_PKT_DATAPTR(pRxPacket);
696 pRxWI = (PRXWI_STRUC) pData;
697 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
700 RxCell.pRxWI = pRxWI;
701 RxCell.pHeader = pHeader;
702 RxCell.pRxPacket = pRxPacket;
703 RxCell.pData = (UCHAR *) pHeader;
704 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
707 // Increase Total receive byte counter after real data received no mater any error or not
708 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
709 pAd->RalinkCounters.RxCount ++;
711 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
713 if (pRxWI->MPDUtotalByteCount < 14)
714 Status = NDIS_STATUS_FAILURE;
718 send_monitor_packets(pAd, &RxCell);
721 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
723 // Check for all RxD errors
724 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
726 // Handle the received frame
727 if (Status == NDIS_STATUS_SUCCESS)
729 switch (pHeader->FC.Type)
731 // CASE I, receive a DATA frame
734 // process DATA frame
735 STAHandleRxDataFrame(pAd, &RxCell);
738 // CASE II, receive a MGMT frame
741 STAHandleRxMgmtFrame(pAd, &RxCell);
744 // CASE III. receive a CNTL frame
747 STAHandleRxControlFrame(pAd, &RxCell);
750 // discard other type
752 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
758 pAd->Counters8023.RxErrors++;
759 // discard this frame
760 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
768 ========================================================================
772 pAd Pointer to our adapter
774 IRQL = DISPATCH_LEVEL
776 ========================================================================
778 VOID RTMPHandleTwakeupInterrupt(
779 IN PRTMP_ADAPTER pAd)
781 AsicForceWakeup(pAd, FALSE);
785 ========================================================================
787 Early checking and OS-depened parsing for Tx packet send to our STA driver.
790 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
791 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
792 UINT NumberOfPackets Number of packet in packet array.
798 This function do early checking and classification for send-out packet.
799 You only can put OS-depened & STA related code in here.
800 ========================================================================
803 IN NDIS_HANDLE MiniportAdapterContext,
804 IN PPNDIS_PACKET ppPacketArray,
805 IN UINT NumberOfPackets)
808 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
809 PNDIS_PACKET pPacket;
810 BOOLEAN allowToSend = FALSE;
813 for (Index = 0; Index < NumberOfPackets; Index++)
815 pPacket = ppPacketArray[Index];
819 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
820 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
821 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
823 // Drop send request since hardware is in reset state
826 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
828 // Drop send request since there are no physical connection yet
833 // Record that orignal packet source is from NDIS layer,so that
834 // later on driver knows how to release this NDIS PACKET
835 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
836 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
837 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
838 pAd->RalinkCounters.PendingNdisPacketCount++;
844 if (allowToSend == TRUE)
845 STASendPacket(pAd, pPacket);
847 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
850 // Dequeue outgoing frames from TxSwQueue[] and process it
851 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
857 ========================================================================
859 This routine is used to do packet parsing and classification for Tx packet
860 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
864 pAd Pointer to our adapter
865 pPacket Pointer to send packet
868 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
869 NDIS_STATUS_FAILURE If failed to do en-queue.
872 You only can put OS-indepened & STA related code in here.
873 ========================================================================
875 NDIS_STATUS STASendPacket(
876 IN PRTMP_ADAPTER pAd,
877 IN PNDIS_PACKET pPacket)
879 PACKET_INFO PacketInfo;
884 UCHAR QueIdx, UserPriority;
885 MAC_TABLE_ENTRY *pEntry = NULL;
886 unsigned int IrqFlags;
890 // Prepare packet information structure for buffer descriptor
891 // chained within a single NDIS packet.
892 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
894 if (pSrcBufVA == NULL)
896 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
897 // Resourece is low, system did not allocate virtual address
898 // return NDIS_STATUS_FAILURE directly to upper layer
899 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
900 return NDIS_STATUS_FAILURE;
906 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
907 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
908 return (NDIS_STATUS_FAILURE);
911 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
912 // Note multicast packets in adhoc also use BSSID_WCID index.
917 pEntry = &pAd->MacTab.Content[BSSID_WCID];
918 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
919 Rate = pAd->CommonCfg.TxRate;
922 else if (ADHOC_ON(pAd))
924 if (*pSrcBufVA & 0x01)
926 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
927 pEntry = &pAd->MacTab.Content[MCAST_WCID];
931 pEntry = MacTableLookup(pAd, pSrcBufVA);
933 Rate = pAd->CommonCfg.TxRate;
939 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
940 // Resourece is low, system did not allocate virtual address
941 // return NDIS_STATUS_FAILURE directly to upper layer
942 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
943 return NDIS_STATUS_FAILURE;
949 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
953 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
954 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
955 RTMPCheckEtherType(pAd, pPacket);
960 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
962 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
963 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
964 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
965 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
966 || (pAd->StaCfg.IEEE8021X == TRUE)
968 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
969 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
972 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
973 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
975 return (NDIS_STATUS_FAILURE);
979 // STEP 1. Decide number of fragments required to deliver this MSDU.
980 // The estimation here is not very accurate because difficult to
981 // take encryption overhead into consideration here. The result
982 // "NumberOfFrag" is then just used to pre-check if enough free
983 // TXD are available to hold this MSDU.
986 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
988 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
989 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
990 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
991 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
992 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
993 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
996 // The calculated "NumberOfFrag" is a rough estimation because of various
997 // encryption/encapsulation overhead not taken into consideration. This number is just
998 // used to make sure enough free TXD are available before fragmentation takes place.
999 // In case the actual required number of fragments of an NDIS packet
1000 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1001 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1002 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1003 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1005 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1006 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1007 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1008 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1014 // Save fragment number to Ndis packet reserved field
1015 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1018 // STEP 2. Check the requirement of RTS:
1019 // If multiple fragment required, RTS is required only for the first fragment
1020 // if the fragment size large than RTS threshold
1021 // For RT28xx, Let ASIC send RTS/CTS
1022 RTMP_SET_PACKET_RTS(pPacket, 0);
1023 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1026 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1030 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1031 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1034 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1037 // get Ethernet protocol field
1038 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1039 if (Protocol <= 1500)
1041 // get Ethernet protocol field from LLC/SNAP
1042 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1045 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1049 // always AC_BE for non-IP packet
1050 if (Protocol != 0x0800)
1054 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1057 // return AC_BE if packet is not IPv4
1058 if ((Byte0 & 0xf0) != 0x40)
1062 UserPriority = (Byte1 & 0xe0) >> 5;
1063 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1065 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1066 // TODO: downgrade UP & QueIdx before passing ACM
1067 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1075 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1079 // Make sure SendTxWait queue resource won't be used by other threads
1080 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1081 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1083 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1084 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1086 return NDIS_STATUS_FAILURE;
1090 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1092 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1094 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1097 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1098 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1099 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1100 // For IOT compatibility, if
1101 // 1. It is Ralink chip or
1102 // 2. It is OPEN or AES mode,
1103 // then BA session can be bulit.
1104 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1105 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1108 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1112 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1113 return NDIS_STATUS_SUCCESS;
1118 ========================================================================
1120 Routine Description:
1121 This subroutine will scan through releative ring descriptor to find
1122 out avaliable free ring descriptor and compare with request size.
1125 pAd Pointer to our adapter
1126 QueIdx Selected TX Ring
1129 NDIS_STATUS_FAILURE Not enough free descriptor
1130 NDIS_STATUS_SUCCESS Enough free descriptor
1132 IRQL = PASSIVE_LEVEL
1133 IRQL = DISPATCH_LEVEL
1137 ========================================================================
1142 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1143 If no frame need to send, go to sleep, else, still wake up.
1145 NDIS_STATUS RTMPFreeTXDRequest(
1146 IN PRTMP_ADAPTER pAd,
1148 IN UCHAR NumberRequired,
1149 IN PUCHAR FreeNumberIs)
1151 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1152 unsigned long IrqFlags;
1153 HT_TX_CONTEXT *pHTTXContext;
1163 pHTTXContext = &pAd->TxContext[QueIdx];
1164 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1165 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1166 (pHTTXContext->IRPPending == TRUE))
1168 Status = NDIS_STATUS_FAILURE;
1172 Status = NDIS_STATUS_SUCCESS;
1174 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1179 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1180 Status = NDIS_STATUS_FAILURE;
1182 Status = NDIS_STATUS_SUCCESS;
1186 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1196 VOID RTMPSendDisassociationFrame(
1197 IN PRTMP_ADAPTER pAd)
1201 VOID RTMPSendNullFrame(
1202 IN PRTMP_ADAPTER pAd,
1204 IN BOOLEAN bQosNull)
1206 UCHAR NullFrame[48];
1208 PHEADER_802_11 pHeader_802_11;
1210 // WPA 802.1x secured port control
1211 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1212 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1213 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1214 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1215 || (pAd->StaCfg.IEEE8021X == TRUE)
1217 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1222 NdisZeroMemory(NullFrame, 48);
1223 Length = sizeof(HEADER_802_11);
1225 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1227 pHeader_802_11->FC.Type = BTYPE_DATA;
1228 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1229 pHeader_802_11->FC.ToDs = 1;
1230 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1231 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1232 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1234 if (pAd->CommonCfg.bAPSDForcePowerSave)
1236 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1240 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1242 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1245 pHeader_802_11->Sequence = pAd->Sequence;
1247 // Prepare QosNull function frame
1250 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1252 // copy QOS control bytes
1253 NullFrame[Length] = 0;
1254 NullFrame[Length+1] = 0;
1255 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1258 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1262 // IRQL = DISPATCH_LEVEL
1263 VOID RTMPSendRTSFrame(
1264 IN PRTMP_ADAPTER pAd,
1266 IN unsigned int NextMpduSize,
1269 IN USHORT AckDuration,
1277 // --------------------------------------------------------
1278 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1279 // Find the WPA key, either Group or Pairwise Key
1280 // LEAP + TKIP also use WPA key.
1281 // --------------------------------------------------------
1282 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1283 // In Cisco CCX 2.0 Leap Authentication
1284 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1285 // Instead of the SharedKey, SharedKey Length may be Zero.
1286 VOID STAFindCipherAlgorithm(
1287 IN PRTMP_ADAPTER pAd,
1290 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1291 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1292 UCHAR KeyIdx = 0xff;
1294 PCIPHER_KEY pKey = NULL;
1296 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1300 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1301 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1303 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1305 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1307 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1309 // 4-way handshaking frame must be clear
1310 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1311 (pAd->SharedKey[BSS0][0].KeyLen))
1313 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1317 else if (Cipher == Ndis802_11Encryption1Enabled)
1319 KeyIdx = pAd->StaCfg.DefaultKeyId;
1321 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1322 (Cipher == Ndis802_11Encryption3Enabled))
1324 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1325 KeyIdx = pAd->StaCfg.DefaultKeyId;
1326 else if (pAd->SharedKey[BSS0][0].KeyLen)
1329 KeyIdx = pAd->StaCfg.DefaultKeyId;
1333 CipherAlg = CIPHER_NONE;
1334 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1335 CipherAlg = CIPHER_NONE;
1336 else if ( pAd->StaCfg.WpaSupplicantUP &&
1337 (Cipher == Ndis802_11Encryption1Enabled) &&
1338 (pAd->StaCfg.IEEE8021X == TRUE) &&
1339 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1340 CipherAlg = CIPHER_NONE;
1343 //Header_802_11.FC.Wep = 1;
1344 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1345 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1349 pTxBlk->CipherAlg = CipherAlg;
1350 pTxBlk->pKey = pKey;
1354 VOID STABuildCommon802_11Header(
1355 IN PRTMP_ADAPTER pAd,
1358 HEADER_802_11 *pHeader_802_11;
1361 // MAKE A COMMON 802.11 HEADER
1364 // normal wlan header size : 24 octets
1365 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1367 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1369 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1371 pHeader_802_11->FC.FrDs = 0;
1372 pHeader_802_11->FC.Type = BTYPE_DATA;
1373 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1375 if (pTxBlk->pMacEntry)
1377 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1379 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1380 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1384 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1385 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1390 pHeader_802_11->Sequence = pAd->Sequence;
1391 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1394 pHeader_802_11->Frag = 0;
1396 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1402 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1403 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1404 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1405 pHeader_802_11->FC.ToDs = 1;
1408 else if (ADHOC_ON(pAd))
1410 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1411 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1412 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1413 pHeader_802_11->FC.ToDs = 0;
1417 if (pTxBlk->CipherAlg != CIPHER_NONE)
1418 pHeader_802_11->FC.Wep = 1;
1420 // -----------------------------------------------------------------
1421 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1422 // -----------------------------------------------------------------
1423 if (pAd->CommonCfg.bAPSDForcePowerSave)
1424 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1426 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1429 VOID STABuildCache802_11Header(
1430 IN RTMP_ADAPTER *pAd,
1434 MAC_TABLE_ENTRY *pMacEntry;
1435 PHEADER_802_11 pHeader80211;
1437 pHeader80211 = (PHEADER_802_11)pHeader;
1438 pMacEntry = pTxBlk->pMacEntry;
1441 // Update the cached 802.11 HEADER
1444 // normal wlan header size : 24 octets
1445 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1448 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1451 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1452 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1455 // The addr3 of normal packet send from DS is Dest Mac address.
1457 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1459 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
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 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1468 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1471 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1472 IN RTMP_ADAPTER *pAd,
1475 PUCHAR pHeaderBufPtr;
1476 HEADER_802_11 *pHeader_802_11;
1477 PNDIS_PACKET pNextPacket;
1479 PQUEUE_ENTRY pQEntry;
1481 STAFindCipherAlgorithm(pAd, pTxBlk);
1482 STABuildCommon802_11Header(pAd, pTxBlk);
1485 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1486 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1488 // steal "order" bit to mark "aggregation"
1489 pHeader_802_11->FC.Order = 1;
1491 // skip common header
1492 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1494 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1497 // build QOS Control bytes
1499 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1501 *(pHeaderBufPtr+1) = 0;
1503 pTxBlk->MpduHeaderLen += 2;
1506 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1507 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1508 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1509 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1511 // For RA Aggregation,
1512 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1513 pQEntry = pTxBlk->TxPacketList.Head;
1514 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1515 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1516 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1517 nextBufLen -= LENGTH_802_1Q;
1519 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1520 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1523 pTxBlk->MpduHeaderLen += 2;
1525 return pHeaderBufPtr;
1529 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1530 IN RTMP_ADAPTER *pAd,
1533 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1534 HEADER_802_11 *pHeader_802_11;
1537 STAFindCipherAlgorithm(pAd, pTxBlk);
1538 STABuildCommon802_11Header(pAd, pTxBlk);
1540 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1541 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1543 // skip common header
1544 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1547 // build QOS Control bytes
1549 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1554 *pHeaderBufPtr |= 0x80;
1556 *(pHeaderBufPtr+1) = 0;
1558 pTxBlk->MpduHeaderLen += 2;
1560 //pSaveBufPtr = pHeaderBufPtr;
1563 // padding at front of LLC header
1564 // LLC header should locate at 4-octets aligment
1566 // @@@ MpduHeaderLen excluding padding @@@
1568 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1569 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1570 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1572 return pHeaderBufPtr;
1577 VOID STA_AMPDU_Frame_Tx(
1578 IN PRTMP_ADAPTER pAd,
1581 HEADER_802_11 *pHeader_802_11;
1582 PUCHAR pHeaderBufPtr;
1584 MAC_TABLE_ENTRY *pMacEntry;
1586 PQUEUE_ENTRY pQEntry;
1590 while(pTxBlk->TxPacketList.Head)
1592 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1593 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1594 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1596 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1600 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1602 pMacEntry = pTxBlk->pMacEntry;
1603 if (pMacEntry->isCached)
1605 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1606 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1607 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1608 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1612 STAFindCipherAlgorithm(pAd, pTxBlk);
1613 STABuildCommon802_11Header(pAd, pTxBlk);
1615 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1619 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1621 // skip common header
1622 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1625 // build QOS Control bytes
1627 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1628 *(pHeaderBufPtr+1) = 0;
1630 pTxBlk->MpduHeaderLen += 2;
1634 // HTC control filed following QoS field
1636 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1638 if (pMacEntry->isCached == FALSE)
1641 pHeader_802_11->FC.Order = 1;
1643 NdisZeroMemory(pHeaderBufPtr, 4);
1644 *(pHeaderBufPtr+3) |= 0x80;
1647 pTxBlk->MpduHeaderLen += 4;
1650 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1651 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1653 // skip 802.3 header
1654 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1655 pTxBlk->SrcBufLen -= LENGTH_802_3;
1660 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1661 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1665 // padding at front of LLC header
1666 // LLC header should locate at 4-octets aligment
1668 // @@@ MpduHeaderLen excluding padding @@@
1670 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1671 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1672 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1677 // Insert LLC-SNAP encapsulation - 8 octets
1679 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1680 if (pTxBlk->pExtraLlcSnapEncap)
1682 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1684 // get 2 octets (TypeofLen)
1685 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1687 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1692 if (pMacEntry->isCached)
1694 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1698 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1700 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1701 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1702 pMacEntry->isCached = TRUE;
1705 // calculate Transmitted AMPDU count and ByteCount
1707 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1708 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1711 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1713 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1718 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1720 pAd->RalinkCounters.KickTxCount++;
1721 pAd->RalinkCounters.OneSecTxDoneCount++;
1727 VOID STA_AMSDU_Frame_Tx(
1728 IN PRTMP_ADAPTER pAd,
1731 PUCHAR pHeaderBufPtr;
1733 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1734 USHORT totalMPDUSize=0;
1735 UCHAR *subFrameHeader;
1737 USHORT FirstTx = 0, LastTxIdx = 0;
1740 PQUEUE_ENTRY pQEntry;
1745 ASSERT((pTxBlk->TxPacketList.Number > 1));
1747 while(pTxBlk->TxPacketList.Head)
1749 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1750 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1751 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1753 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1757 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1759 // skip 802.3 header
1760 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1761 pTxBlk->SrcBufLen -= LENGTH_802_3;
1766 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1767 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1772 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1774 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1775 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1779 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1780 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1781 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1782 pHeaderBufPtr += padding;
1783 pTxBlk->MpduHeaderLen = padding;
1788 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1790 subFrameHeader = pHeaderBufPtr;
1791 subFramePayloadLen = pTxBlk->SrcBufLen;
1793 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1796 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1797 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1801 // Insert LLC-SNAP encapsulation - 8 octets
1803 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1805 subFramePayloadLen = pTxBlk->SrcBufLen;
1807 if (pTxBlk->pExtraLlcSnapEncap)
1809 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1811 // get 2 octets (TypeofLen)
1812 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1814 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1815 subFramePayloadLen += LENGTH_802_1_H;
1818 // update subFrame Length field
1819 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1820 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1822 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1825 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1827 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1831 pAd->RalinkCounters.KickTxCount++;
1832 pAd->RalinkCounters.OneSecTxDoneCount++;
1834 // calculate Transmitted AMSDU Count and ByteCount
1836 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1837 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1842 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1843 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1848 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1851 VOID STA_Legacy_Frame_Tx(
1852 IN PRTMP_ADAPTER pAd,
1855 HEADER_802_11 *pHeader_802_11;
1856 PUCHAR pHeaderBufPtr;
1859 PQUEUE_ENTRY pQEntry;
1864 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1865 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1866 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1868 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1872 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1874 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1877 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1878 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1880 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1882 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1884 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1885 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1887 STAFindCipherAlgorithm(pAd, pTxBlk);
1888 STABuildCommon802_11Header(pAd, pTxBlk);
1891 // skip 802.3 header
1892 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1893 pTxBlk->SrcBufLen -= LENGTH_802_3;
1898 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1899 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1902 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1903 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1905 // skip common header
1906 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1908 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1911 // build QOS Control bytes
1913 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1914 *(pHeaderBufPtr+1) = 0;
1916 pTxBlk->MpduHeaderLen += 2;
1919 // The remaining content of MPDU header should locate at 4-octets aligment
1920 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1921 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1922 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1927 // Insert LLC-SNAP encapsulation - 8 octets
1930 // if original Ethernet frame contains no LLC/SNAP,
1931 // then an extra LLC/SNAP encap is required
1933 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
1934 if (pTxBlk->pExtraLlcSnapEncap)
1938 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1941 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
1942 // get 2 octets (TypeofLen)
1943 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
1945 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1952 // use Wcid as Key Index
1955 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1957 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1959 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1961 pAd->RalinkCounters.KickTxCount++;
1962 pAd->RalinkCounters.OneSecTxDoneCount++;
1967 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1971 VOID STA_ARalink_Frame_Tx(
1972 IN PRTMP_ADAPTER pAd,
1975 PUCHAR pHeaderBufPtr;
1977 USHORT totalMPDUSize=0;
1978 USHORT FirstTx, LastTxIdx;
1981 PQUEUE_ENTRY pQEntry;
1986 ASSERT((pTxBlk->TxPacketList.Number== 2));
1989 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
1990 while(pTxBlk->TxPacketList.Head)
1992 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1993 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1995 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1997 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2001 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2003 // skip 802.3 header
2004 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2005 pTxBlk->SrcBufLen -= LENGTH_802_3;
2010 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2011 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2015 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2017 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2019 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2020 // will be updated after final frame was handled.
2021 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2025 // Insert LLC-SNAP encapsulation - 8 octets
2027 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2029 if (pTxBlk->pExtraLlcSnapEncap)
2031 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2033 // get 2 octets (TypeofLen)
2034 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2036 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2040 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2042 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2043 pTxBlk->MpduHeaderLen = 0;
2045 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2046 // DA(6)+SA(6)+FrameType(2)
2047 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2048 pHeaderBufPtr += 12;
2049 // get 2 octets (TypeofLen)
2050 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2052 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2055 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2057 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2059 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2061 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2065 pAd->RalinkCounters.OneSecTxAggregationCount++;
2066 pAd->RalinkCounters.KickTxCount++;
2067 pAd->RalinkCounters.OneSecTxDoneCount++;
2071 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2072 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2077 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2082 VOID STA_Fragment_Frame_Tx(
2083 IN RTMP_ADAPTER *pAd,
2086 HEADER_802_11 *pHeader_802_11;
2087 PUCHAR pHeaderBufPtr;
2090 PACKET_INFO PacketInfo;
2091 USHORT EncryptionOverhead = 0;
2092 UINT32 FreeMpduSize, SrcRemainingBytes;
2096 PQUEUE_ENTRY pQEntry;
2101 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2102 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2103 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2105 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2109 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2110 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2112 STAFindCipherAlgorithm(pAd, pTxBlk);
2113 STABuildCommon802_11Header(pAd, pTxBlk);
2115 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2117 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2118 if (pTxBlk->pPacket == NULL)
2120 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2123 // skip 802.3 header
2124 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2125 pTxBlk->SrcBufLen -= LENGTH_802_3;
2131 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2132 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2135 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2136 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2139 // skip common header
2140 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2142 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2145 // build QOS Control bytes
2147 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2149 *(pHeaderBufPtr+1) = 0;
2151 pTxBlk->MpduHeaderLen += 2;
2155 // padding at front of LLC header
2156 // LLC header should locate at 4-octets aligment
2158 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2159 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2160 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2165 // Insert LLC-SNAP encapsulation - 8 octets
2168 // if original Ethernet frame contains no LLC/SNAP,
2169 // then an extra LLC/SNAP encap is required
2171 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2172 if (pTxBlk->pExtraLlcSnapEncap)
2176 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2179 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2180 // get 2 octets (TypeofLen)
2181 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2183 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2187 // If TKIP is used and fragmentation is required. Driver has to
2188 // append TKIP MIC at tail of the scatter buffer
2189 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2190 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2193 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2194 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2195 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2196 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2197 pTxBlk->SrcBufLen += 8;
2198 pTxBlk->TotalFrameLen += 8;
2199 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2203 // calcuate the overhead bytes that encryption algorithm may add. This
2204 // affects the calculate of "duration" field
2206 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2207 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2208 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2209 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2210 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2211 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2212 else if (pTxBlk->CipherAlg == CIPHER_AES)
2213 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2215 EncryptionOverhead = 0;
2217 // decide how much time an ACK/CTS frame will consume in the air
2218 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2220 // Init the total payload length of this frame.
2221 SrcRemainingBytes = pTxBlk->SrcBufLen;
2223 pTxBlk->TotalFragNum = 0xff;
2227 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2229 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2231 if (SrcRemainingBytes <= FreeMpduSize)
2232 { // this is the last or only fragment
2234 pTxBlk->SrcBufLen = SrcRemainingBytes;
2236 pHeader_802_11->FC.MoreFrag = 0;
2237 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2239 // Indicate the lower layer that this's the last fragment.
2240 pTxBlk->TotalFragNum = fragNum;
2243 { // more fragment is required
2245 pTxBlk->SrcBufLen = FreeMpduSize;
2247 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2248 pHeader_802_11->FC.MoreFrag = 1;
2249 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2253 pTxBlk->FrameGap = IFS_HTTXOP;
2255 pTxBlk->FrameGap = IFS_SIFS;
2257 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2259 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2261 pAd->RalinkCounters.KickTxCount++;
2262 pAd->RalinkCounters.OneSecTxDoneCount++;
2264 // Update the frame number, remaining size of the NDIS packet payload.
2266 // space for 802.11 header.
2267 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2268 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2271 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2272 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2274 pHeader_802_11->Frag++; // increase Frag #
2276 }while(SrcRemainingBytes > 0);
2281 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2285 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2286 while(_pTxBlk->TxPacketList.Head) \
2288 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2289 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2294 ========================================================================
2296 Routine Description:
2297 Copy frame from waiting queue into relative ring buffer and set
2298 appropriate ASIC register to kick hardware encryption before really
2302 pAd Pointer to our adapter
2303 PNDIS_PACKET Pointer to outgoing Ndis frame
2304 NumberOfFrag Number of fragment required
2309 IRQL = DISPATCH_LEVEL
2313 ========================================================================
2315 NDIS_STATUS STAHardTransmit(
2316 IN PRTMP_ADAPTER pAd,
2320 NDIS_PACKET *pPacket;
2321 PQUEUE_ENTRY pQEntry;
2323 // ---------------------------------------------
2324 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2325 // ---------------------------------------------
2327 ASSERT(pTxBlk->TxPacketList.Number);
2328 if (pTxBlk->TxPacketList.Head == NULL)
2330 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2331 return NDIS_STATUS_FAILURE;
2334 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2336 // ------------------------------------------------------------------
2337 // STEP 1. WAKE UP PHY
2338 // outgoing frame always wakeup PHY to prevent frame lost and
2339 // turn off PSM bit to improve performance
2340 // ------------------------------------------------------------------
2341 // not to change PSM bit, just send this frame out?
2342 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2344 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2345 AsicForceWakeup(pAd, TRUE);
2348 // It should not change PSM bit, when APSD turn on.
2349 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2350 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2351 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2353 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2354 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2355 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2358 switch (pTxBlk->TxFrameType)
2360 case TX_AMPDU_FRAME:
2361 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2363 case TX_AMSDU_FRAME:
2364 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2366 case TX_LEGACY_FRAME:
2367 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2369 case TX_MCAST_FRAME:
2370 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2372 case TX_RALINK_FRAME:
2373 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2376 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2380 // It should not happened!
2381 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2382 while(pTxBlk->TxPacketList.Number)
2384 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2385 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2387 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2393 return (NDIS_STATUS_SUCCESS);
2397 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2399 unsigned char *word = value;
2400 unsigned int ret = 0;
2403 for(i=0; i < len; i++)
2406 ret ^=(unsigned int) (word[i]) << mod;
2407 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2412 VOID Sta_Announce_or_Forward_802_3_Packet(
2413 IN PRTMP_ADAPTER pAd,
2414 IN PNDIS_PACKET pPacket,
2415 IN UCHAR FromWhichBSSID)
2420 announce_802_3_packet(pAd, pPacket);
2425 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);